diff options
-rw-r--r-- | eval.c | 3 | ||||
-rw-r--r-- | parse.c | 27 | ||||
-rw-r--r-- | test.toc | 6 | ||||
-rw-r--r-- | tokenizer.c | 3 | ||||
-rw-r--r-- | types.c | 20 |
5 files changed, 44 insertions, 15 deletions
@@ -35,6 +35,9 @@ static bool eval_expr_as_int(Expression *e, Integer *i) { *i = -of; return true; } + case UNARY_ADDRESS: + err_print(e->where, "Use of pointer as integer constant."); + return false; } break; case EXPR_BINARY_OP: { @@ -70,7 +70,8 @@ typedef enum { } ExprKind; typedef enum { - UNARY_MINUS + UNARY_MINUS, + UNARY_ADDRESS /* &x */ } UnaryOp; typedef enum { @@ -178,6 +179,15 @@ typedef enum { static bool parse_expr(Parser *p, Expression *e, Token *end); static bool parse_decl(Parser *p, Declaration *d, DeclEndType ends_with); +static const char *unary_op_to_str(UnaryOp u) { + switch (u) { + case UNARY_MINUS: return "-"; + case UNARY_ADDRESS: return "&"; + } + assert(0); + return ""; +} + static const char *binary_op_to_str(BinaryOp b) { switch (b) { case BINARY_PLUS: return "+"; @@ -341,6 +351,7 @@ static int op_precedence(Keyword op) { case KW_COMMA: return 5; case KW_PLUS: return 10; case KW_MINUS: return 20; + case KW_AMPERSAND: return 25; case KW_ASTERISK: return 30; case KW_SLASH: return 40; default: return NOT_AN_OP; @@ -895,15 +906,15 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { return false; } - /* This is a unary op not a binary one. */ + /* Check if his is a unary op not a binary one (e.g. +-3 => +(-3), not (+)-(3)). */ while (lowest_precedence_op != t->token && lowest_precedence_op[-1].kind == TOKEN_KW && op_precedence(lowest_precedence_op[-1].kw) != NOT_AN_OP) { lowest_precedence_op--; } - /* Unary */ if (lowest_precedence_op == t->token) { + /* Unary */ UnaryOp op; bool is_unary; switch (lowest_precedence_op->kw) { @@ -916,6 +927,10 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { is_unary = true; op = UNARY_MINUS; break; + case KW_AMPERSAND: + is_unary= true; + op = UNARY_ADDRESS; + break; default: is_unary = false; break; @@ -1249,11 +1264,7 @@ static void fprint_expr(FILE *out, Expression *e) { fprintf(out, ")"); break; case EXPR_UNARY_OP: - switch (e->unary.op) { - case UNARY_MINUS: - fprintf(out, "-"); - break; - } + fprintf(out, "%s", unary_op_to_str(e->unary.op)); fprintf(out, "("); fprint_expr(out, e->unary.of); fprintf(out, ")"); @@ -1,4 +1,6 @@ main @= fn() { - x, y, z : *int; - foo : *f32; + x : int; + y : *i64 = &x; + N @= 12.3; + z := &N; }; diff --git a/tokenizer.c b/tokenizer.c index 63d36ee..3ea8ced 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -31,6 +31,7 @@ typedef enum { KW_PLUS, KW_MINUS, KW_ASTERISK, + KW_AMPERSAND, KW_SLASH, KW_LAST_SYMBOL = KW_SLASH, /* last one entirely consisting of symbols */ KW_FN, @@ -50,7 +51,7 @@ typedef enum { static const char *keywords[KW_COUNT] = {";", "=", ":", "@", ",", "(", ")", "{", "}", "[", "]", "==", "<", "<=", "+", "-", "*", - "/", "fn", "int", "i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64", "f32", "f64"}; + "&", "/", "fn", "int", "i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64", "f32", "f64"}; static const char *directives[DIRECT_COUNT] = {"C"}; @@ -119,7 +119,7 @@ static bool type_must_eq(Location where, Type *expected, Type *got) { return true; } -/* Prints an error and returns false if the given expression is not an l-value */ +/* sometimes prints an error and returns false if the given expression is not an l-value */ static bool expr_must_lval(Expression *e) { switch (e->kind) { case EXPR_IDENT: { @@ -144,7 +144,6 @@ static bool expr_must_lval(Expression *e) { default: break; } - err_print(e->where, "Cannot assign to non-lvalue."); return false; } @@ -333,7 +332,8 @@ static bool type_of_expr(Expression *e) { } break; case EXPR_UNARY_OP: { - Type *of_type = &e->unary.of->type; + Expression *of = e->unary.of; + Type *of_type = &of->type; if (!type_of_expr(e->unary.of)) return false; switch (e->unary.op) { case UNARY_MINUS: @@ -344,6 +344,15 @@ static bool type_of_expr(Expression *e) { } *t = *of_type; break; + case UNARY_ADDRESS: + if (!expr_must_lval(of)) { + err_print(e->where, "Cannot take address of non-lvalue."); /* FEATURE: better err */ + return false; + } + t->kind = TYPE_PTR; + t->ptr.of = malloc(sizeof *t->ptr.of); /* OPTIM */ + *t->ptr.of = *of_type; + break; } } break; case EXPR_BINARY_OP: { @@ -354,7 +363,10 @@ static bool type_of_expr(Expression *e) { return false; switch (e->binary.op) { case BINARY_SET: - if (!expr_must_lval(e->binary.lhs)) return false; + if (!expr_must_lval(e->binary.lhs)) { + err_print(e->where, "You can only assign to an lvalue."); /* FEATURE: better err */ + return false; + } /* fallthrough */ case BINARY_PLUS: case BINARY_MINUS: |