summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eval.c3
-rw-r--r--parse.c27
-rw-r--r--test.toc6
-rw-r--r--tokenizer.c3
-rw-r--r--types.c20
5 files changed, 44 insertions, 15 deletions
diff --git a/eval.c b/eval.c
index 7bea49a..7033367 100644
--- a/eval.c
+++ b/eval.c
@@ -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: {
diff --git a/parse.c b/parse.c
index 811e3e6..9ac94a9 100644
--- a/parse.c
+++ b/parse.c
@@ -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, ")");
diff --git a/test.toc b/test.toc
index 536f095..8d572ac 100644
--- a/test.toc
+++ b/test.toc
@@ -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"};
diff --git a/types.c b/types.c
index e317fab..d0e147e 100644
--- a/types.c
+++ b/types.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: