diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-11-08 13:21:56 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-11-08 13:21:56 -0500 |
commit | 5589c039120d2f0f6918104d116e3d3eca36080a (patch) | |
tree | ccf3eea66f64f5e61510219cf8cb97c93fa28a64 | |
parent | 6800a6691602aa3b38fc8fea182bf4d1cef092ef (diff) |
+=, -=, /=, *=
-rwxr-xr-x | build.sh | 2 | ||||
-rw-r--r-- | cgen.c | 8 | ||||
-rw-r--r-- | eval.c | 16 | ||||
-rw-r--r-- | parse.c | 27 | ||||
-rw-r--r-- | test.toc | 19 | ||||
-rw-r--r-- | tokenizer.c | 4 | ||||
-rw-r--r-- | types.c | 13 | ||||
-rw-r--r-- | types.h | 10 |
8 files changed, 80 insertions, 19 deletions
@@ -22,7 +22,7 @@ else WARNINGS='-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wno-pointer-to-int-cast -Wno-unused-parameter' fi -DEBUG_FLAGS="-Og -g3 $WARNINGS -std=c11 -DTOC_DEBUG" +DEBUG_FLAGS="-O0 -g3 $WARNINGS -std=c11 -DTOC_DEBUG" RELEASE_FLAGS="-O3 -s -DNDEBUG $WARNINGS -std=c11" if [ "$1" = "release" ]; then @@ -1029,6 +1029,14 @@ static bool cgen_expr(CGenerator *g, Expression *e) { s = "=="; break; case BINARY_NE: s = "!="; break; + case BINARY_SET_ADD: + s = "+="; break; + case BINARY_SET_SUB: + s = "-="; break; + case BINARY_SET_MUL: + s = "*="; break; + case BINARY_SET_DIV: + s = "/="; break; case BINARY_AT_INDEX: cgen_write(g, "("); switch (e->binary.lhs->type.kind) { @@ -1125,6 +1125,22 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { case BINARY_SET: if (!eval_set(ev, e->binary.lhs, &rhs)) return false; break; + case BINARY_SET_ADD: + case BINARY_SET_SUB: + case BINARY_SET_MUL: + case BINARY_SET_DIV: { + BinaryOp subop = (BinaryOp)0; + switch (e->binary.op) { + case BINARY_SET_ADD: subop = BINARY_ADD; break; + case BINARY_SET_SUB: subop = BINARY_SUB; break; + case BINARY_SET_MUL: subop = BINARY_MUL; break; + case BINARY_SET_DIV: subop = BINARY_DIV; break; + default: assert(0); + } + eval_numerical_bin_op(lhs, &e->binary.lhs->type, subop, rhs, &e->binary.rhs->type, v, &e->binary.lhs->type); + if (!eval_set(ev, e->binary.lhs, v)) return false; + break; + } break; case BINARY_AT_INDEX: { void *ptr; Type *type; @@ -52,6 +52,10 @@ static const char *binary_op_to_str(BinaryOp b) { case BINARY_MUL: return "*"; case BINARY_DIV: return "/"; case BINARY_SET: return "="; + case BINARY_SET_ADD: return "+="; + case BINARY_SET_SUB: return "-="; + case BINARY_SET_MUL: return "*="; + case BINARY_SET_DIV: return "/="; case BINARY_AT_INDEX: return "[]"; case BINARY_LT: return "<"; case BINARY_LE: return "<="; @@ -869,13 +873,18 @@ static void fprint_expr(FILE *out, Expression *e); #define NEW_PRECEDENCE 22 static int op_precedence(Keyword op) { switch (op) { - case KW_EQ: return 0; + case KW_EQ: + case KW_PLUS_EQ: + case KW_MINUS_EQ: + case KW_ASTERISK_EQ: + case KW_SLASH_EQ: + return 0; case KW_COMMA: return 1; case KW_LT: return 3; case KW_GT: return 3; case KW_LE: return 3; case KW_GE: return 3; - case KW_EQEQ: return 3; + case KW_EQ_EQ: return 3; case KW_NE: return 3; case KW_PLUS: return 10; case KW_MINUS: return 20; @@ -1393,7 +1402,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { case KW_MINUS: op = BINARY_SUB; break; - case KW_EQEQ: + case KW_EQ_EQ: op = BINARY_EQ; break; case KW_NE: @@ -1414,6 +1423,18 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { case KW_EQ: op = BINARY_SET; break; + case KW_PLUS_EQ: + op = BINARY_SET_ADD; + break; + case KW_MINUS_EQ: + op = BINARY_SET_SUB; + break; + case KW_ASTERISK_EQ: + op = BINARY_SET_MUL; + break; + case KW_SLASH_EQ: + op = BINARY_SET_DIV; + break; case KW_ASTERISK: op = BINARY_MUL; break; @@ -9,20 +9,15 @@ putf @= fn(x: float) { "); }; - -sum @= fn() int { - -x := 3; -total := 0; -each x := 1..10{ - total = total + x; - total -} - +lsh @= fn(x: int, bits: int) int { + each 1..bits { + x *= 2; + } + x }; main @= fn() { - puti(sum()); - X @= sum(); + puti(lsh(2, 15)); + X @= lsh(2, 15); puti(X); }; diff --git a/tokenizer.c b/tokenizer.c index ab668fc..adbb7b1 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -1,5 +1,7 @@ static const char *keywords[KW_COUNT] = - {";", ":", "@", ",", "(", ")", "{", "}", "[", "]", "==", "!=", "<=", "<", ">=", ">", + {";", ":", "@", ",", "(", ")", "{", "}", "[", "]", "==", + "+=", "-=", "*=", "/=", + "!=", "<=", "<", ">=", ">", "+", "-", "*", "!", "&", "/", "..", ".", "=", "if", "elif", "else", "while", "each", "return", "fn", "as", @@ -1177,10 +1177,13 @@ static bool types_expr(Typer *tr, Expression *e) { } switch (o) { case BINARY_SET: + case BINARY_SET_ADD: + case BINARY_SET_SUB: + case BINARY_SET_MUL: + case BINARY_SET_DIV: if (!expr_must_lval(e->binary.lhs)) { return false; } - /* fallthrough */ case BINARY_ADD: case BINARY_SUB: @@ -1270,6 +1273,14 @@ static bool types_expr(Typer *tr, Expression *e) { err_print(e->where, "Invalid types to operator %s: %s and %s", op, s1, s2); return false; } + if (o == BINARY_SET_ADD || + o == BINARY_SET_SUB || + o == BINARY_SET_MUL || + o == BINARY_SET_DIV) { + t->kind = TYPE_VOID; /* actually, it's just void */ + t->flags = 0; + } + break; } case BINARY_AT_INDEX: @@ -164,7 +164,11 @@ typedef enum { KW_RBRACE, KW_LSQUARE, KW_RSQUARE, - KW_EQEQ, + KW_EQ_EQ, + KW_PLUS_EQ, + KW_MINUS_EQ, + KW_ASTERISK_EQ, + KW_SLASH_EQ, KW_NE, KW_LE, KW_LT, @@ -381,6 +385,10 @@ typedef enum { BINARY_SUB, BINARY_MUL, BINARY_DIV, + BINARY_SET_ADD, /* e.g. x += y */ + BINARY_SET_SUB, + BINARY_SET_MUL, + BINARY_SET_DIV, BINARY_GT, BINARY_LT, BINARY_GE, |