summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c17
-rw-r--r--decls_cgen.c1
-rw-r--r--eval.c106
-rw-r--r--main.c1
-rw-r--r--parse.c8
-rw-r--r--typedefs_cgen.c1
-rw-r--r--types.c13
-rw-r--r--types.h7
8 files changed, 96 insertions, 58 deletions
diff --git a/cgen.c b/cgen.c
index 0e0a3ce..78b706e 100644
--- a/cgen.c
+++ b/cgen.c
@@ -453,6 +453,9 @@ static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E
static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, const char *prefix, Expression *to) {
IdentID prefix_id; /* ID of prefix for block */
switch (to->kind) {
+ case EXPR_VAL:
+ assert(0); /* never needed at the moment */
+ break;
case EXPR_TUPLE:
/* e.g. a, b = 3, 5; */
for (size_t i = 0; i < arr_len(to->tuple); i++) {
@@ -957,6 +960,17 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
if (e->new.n && !cgen_expr_pre(g, e->new.n))
return false;
break;
+ case EXPR_VAL:
+ if (!cgen_type_pre(g, &e->type, e->where)) return false;
+ e->val_c_id = g->ident_counter++;
+ cgen_write(g, " ");
+ cgen_ident_id(g, e->val_c_id);
+ if (!cgen_type_post(g, &e->type, e->where)) return false;
+ cgen_write(g, " = ");
+ cgen_val(g, &e->val, &e->type, e->where);
+ cgen_write(g, ";");
+ cgen_nl(g);
+ break;
case EXPR_LITERAL_INT:
case EXPR_LITERAL_FLOAT:
case EXPR_LITERAL_BOOL:
@@ -1247,6 +1261,9 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
case EXPR_SLICE:
cgen_ident_id(g, e->slice.c.id);
break;
+ case EXPR_VAL:
+ cgen_ident_id(g, e->val_c_id);
+ break;
}
return true;
}
diff --git a/decls_cgen.c b/decls_cgen.c
index 86ca5f8..ad0c552 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -83,6 +83,7 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
fn_exit(&e->fn);
break;
case EXPR_TYPE:
+ case EXPR_VAL:
case EXPR_C:
case EXPR_DSIZEOF:
case EXPR_DALIGNOF:
diff --git a/eval.c b/eval.c
index a3c2c83..aa60c7b 100644
--- a/eval.c
+++ b/eval.c
@@ -313,21 +313,21 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) {
}
}
-static void fprint_val(FILE *f, Value *v, Type *t) {
+static void fprint_val(FILE *f, Value v, Type *t) {
if (t->kind == TYPE_TUPLE) {
fprintf(f, "(");
for (size_t i = 0; i < arr_len(t->tuple); i++) {
- fprint_val(f, &v->tuple[i], &t->tuple[i]);
+ fprint_val(f, v.tuple[i], &t->tuple[i]);
}
fprintf(f, ")");
} else {
- fprint_val_ptr(f, v, t);
+ fprint_val_ptr(f, &v, t);
}
}
/*
-IMPORTANT: Only pass an evaluator if you want it to use its allocator.
-Otherwise, pass NULL.
+ IMPORTANT: Only pass an evaluator if you want it to use its allocator.
+ Otherwise, pass NULL.
*/
static void val_copy(Evaluator *ev, Value *dest, Value *src, Type *t) {
switch (t->kind) {
@@ -421,21 +421,21 @@ static void val_free(Value *v, Type *t) {
case BUILTIN_F64: \
vout->f64 = (F64)vin->x; break
-#define builtin_int_casts(low, up) \
- case BUILTIN_##up: \
- switch (to) { \
- builtin_casts_to_num(low); \
- case BUILTIN_CHAR: vout->charv = (char)vin->low; break; \
- case BUILTIN_BOOL: vout->boolv = vin->low != 0; break; \
+#define builtin_int_casts(low, up) \
+ case BUILTIN_##up: \
+ switch (to) { \
+ builtin_casts_to_num(low); \
+ case BUILTIN_CHAR: vout->charv = (char)vin->low; break; \
+ case BUILTIN_BOOL: vout->boolv = vin->low != 0; break; \
} break
-#define builtin_float_casts(low, up) \
- case BUILTIN_##up: \
- switch (to) { \
- builtin_casts_to_num(low); \
- case BUILTIN_BOOL: vout->boolv = vin->low != 0.0f; break; \
- case BUILTIN_CHAR: \
- assert(0); break; \
+#define builtin_float_casts(low, up) \
+ case BUILTIN_##up: \
+ switch (to) { \
+ builtin_casts_to_num(low); \
+ case BUILTIN_BOOL: vout->boolv = vin->low != 0.0f; break; \
+ case BUILTIN_CHAR: \
+ assert(0); break; \
} break
static void val_builtin_cast(Value *vin, BuiltinType from, Value *vout, BuiltinType to) {
@@ -895,7 +895,7 @@ static bool eval_set(Evaluator *ev, Expression *set, Value *to) {
}
static void eval_numerical_bin_op(Value lhs, Type *lhs_type, BinaryOp op, Value rhs, Type *rhs_type, Value *out, Type *out_type) {
- /* WARNING: macros ahead */
+ /* WARNING: macros ahead */
#define eval_unary_op_nums_only(op) \
switch (builtin) { \
@@ -903,8 +903,8 @@ static void eval_numerical_bin_op(Value lhs, Type *lhs_type, BinaryOp op, Value
default: assert(0); break; \
}
-#define eval_binary_op_one(low, up, op) \
- case BUILTIN_##up: \
+#define eval_binary_op_one(low, up, op) \
+ case BUILTIN_##up: \
out->low = (up)(lhs.low op rhs.low); break
#define eval_binary_op_nums(builtin, op) \
@@ -920,44 +920,44 @@ static void eval_numerical_bin_op(Value lhs, Type *lhs_type, BinaryOp op, Value
eval_binary_op_one(f64, F64, op)
-#define eval_binary_op_nums_only(op) \
- val_cast(&lhs, lhs_type, &lhs, out_type); \
- val_cast(&rhs, rhs_type, &rhs, out_type); \
- assert(out_type->kind == TYPE_BUILTIN); \
- switch (builtin) { \
- eval_binary_op_nums(builtin, op); \
- default: assert(0); break; \
+#define eval_binary_op_nums_only(op) \
+ val_cast(&lhs, lhs_type, &lhs, out_type); \
+ val_cast(&rhs, rhs_type, &rhs, out_type); \
+ assert(out_type->kind == TYPE_BUILTIN); \
+ switch (builtin) { \
+ eval_binary_op_nums(builtin, op); \
+ default: assert(0); break; \
}
#define eval_binary_bool_op_one(low, up, op) \
case BUILTIN_##up: \
- out->boolv = lhs.low op rhs.low; break
+ out->boolv = lhs.low op rhs.low; break
-#define eval_binary_bool_op_nums(builtin, op) \
- eval_binary_bool_op_one(i8, I8, op); \
- eval_binary_bool_op_one(i16, I16, op); \
- eval_binary_bool_op_one(i32, I32, op); \
- eval_binary_bool_op_one(i64, I64, op); \
- eval_binary_bool_op_one(u8, U8, op); \
- eval_binary_bool_op_one(u16, U16, op); \
- eval_binary_bool_op_one(u32, U32, op); \
- eval_binary_bool_op_one(u64, U64, op); \
- eval_binary_bool_op_one(f32, F32, op); \
- eval_binary_bool_op_one(f64, F64, op); \
- eval_binary_bool_op_one(boolv, BOOL, op); \
+#define eval_binary_bool_op_nums(builtin, op) \
+ eval_binary_bool_op_one(i8, I8, op); \
+ eval_binary_bool_op_one(i16, I16, op); \
+ eval_binary_bool_op_one(i32, I32, op); \
+ eval_binary_bool_op_one(i64, I64, op); \
+ eval_binary_bool_op_one(u8, U8, op); \
+ eval_binary_bool_op_one(u16, U16, op); \
+ eval_binary_bool_op_one(u32, U32, op); \
+ eval_binary_bool_op_one(u64, U64, op); \
+ eval_binary_bool_op_one(f32, F32, op); \
+ eval_binary_bool_op_one(f64, F64, op); \
+ eval_binary_bool_op_one(boolv, BOOL, op); \
eval_binary_bool_op_one(charv, CHAR, op);
-#define eval_binary_bool_op_nums_only(op) \
- {Type *cast_to = lhs_type->flags & TYPE_FLAG_FLEXIBLE ? \
- rhs_type : lhs_type; \
- val_cast(&lhs, lhs_type, &lhs, cast_to); \
- val_cast(&rhs, rhs_type, &rhs, cast_to); \
- assert(lhs_type->kind == TYPE_BUILTIN); \
- switch (builtin) { \
- eval_binary_bool_op_nums(builtin, op); \
- default: \
- assert(!("Invalid builtin to "#op)[0]); break; \
+#define eval_binary_bool_op_nums_only(op) \
+ {Type *cast_to = lhs_type->flags & TYPE_FLAG_FLEXIBLE ? \
+ rhs_type : lhs_type; \
+ val_cast(&lhs, lhs_type, &lhs, cast_to); \
+ val_cast(&rhs, rhs_type, &rhs, cast_to); \
+ assert(lhs_type->kind == TYPE_BUILTIN); \
+ switch (builtin) { \
+ eval_binary_bool_op_nums(builtin, op); \
+ default: \
+ assert(!("Invalid builtin to "#op)[0]); break; \
}}
#define eval_binary_bool_op(op) \
@@ -1495,6 +1495,10 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
} break;
case EXPR_TYPE:
v->type = &e->typeval;
+ break;
+ case EXPR_VAL:
+ *v = e->val;
+ break;
}
return true;
}
diff --git a/main.c b/main.c
index 88ac5f7..3c0c0b5 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,7 @@
/*
TODO:
compile-time arguments
+don't allow pointers to functions with compile-time arguments
don't allow while {3; 5} (once break is added)
any odd number of "s for a string
modifiable strings:
diff --git a/parse.c b/parse.c
index a7ac633..f14cc89 100644
--- a/parse.c
+++ b/parse.c
@@ -27,6 +27,7 @@ static const char *expr_kind_to_str(ExprKind k) {
case EXPR_IDENT: return "identifier";
case EXPR_SLICE: return "slice";
case EXPR_TYPE: return "type";
+ case EXPR_VAL: return "value";
}
assert(0);
return "";
@@ -1956,7 +1957,7 @@ static void fprint_arg_exprs(FILE *out, Expression *args) {
fprintf(out, ")");
}
-static void fprint_val(FILE *f, Value *v, Type *t);
+static void fprint_val(FILE *f, Value v, Type *t);
static void fprint_expr(FILE *out, Expression *e) {
PARSE_PRINT_LOCATION(e->where);
@@ -2048,7 +2049,7 @@ static void fprint_expr(FILE *out, Expression *e) {
if (parse_printing_after_types) {
if (ea->range.stepval) {
fprintf(out, ",");
- fprint_val(out, ea->range.stepval, &ea->type);
+ fprint_val(out, *ea->range.stepval, &ea->type);
}
} else {
if (ea->range.step) {
@@ -2112,6 +2113,9 @@ static void fprint_expr(FILE *out, Expression *e) {
case EXPR_TYPE:
fprint_type(out, &e->typeval);
break;
+ case EXPR_VAL:
+ fprint_val(out, e->val, &e->type);
+ break;
}
if (parse_printing_after_types) {
fprintf(out, ":");
diff --git a/typedefs_cgen.c b/typedefs_cgen.c
index b193e9a..8756298 100644
--- a/typedefs_cgen.c
+++ b/typedefs_cgen.c
@@ -89,6 +89,7 @@ static bool typedefs_expr(CGenerator *g, Expression *e) {
if (e->new.n && !typedefs_expr(g, e->new.n))
return false;
break;
+ case EXPR_VAL:
case EXPR_TYPE:
case EXPR_C:
case EXPR_DSIZEOF:
diff --git a/types.c b/types.c
index 337b97e..a635956 100644
--- a/types.c
+++ b/types.c
@@ -95,8 +95,8 @@ static bool type_must_eq(Location where, Type *expected, Type *got) {
/*
-this expression, which is an array (or slice), must be mutable (otherwise print an error,
-return false)!
+ this expression, which is an array (or slice), must be mutable (otherwise print an error,
+ return false)!
*/
static bool expr_arr_must_mut(Expression *e) {
switch (e->kind) {
@@ -116,6 +116,7 @@ static bool expr_arr_must_mut(Expression *e) {
case EXPR_NEW:
case EXPR_UNARY_OP:
case EXPR_C:
+ case EXPR_VAL:
return true;
case EXPR_SLICE:
return expr_arr_must_mut(e->slice.of);
@@ -218,7 +219,8 @@ static bool expr_must_lval(Expression *e) {
case EXPR_DSIZEOF:
case EXPR_BLOCK:
case EXPR_SLICE:
- case EXPR_TYPE: {
+ case EXPR_TYPE:
+ case EXPR_VAL: {
err_print(e->where, "Cannot use %s as l-value.", expr_kind_to_str(e->kind));
return false;
}
@@ -633,7 +635,7 @@ static bool types_expr(Typer *tr, Expression *e) {
if (last_stmt->kind == STMT_RET) {
/*
last statement is a return, so it doesn't matter that the function has no return value
- ideally this would handle if foo { return 5; } else { return 6; } */
+ ideally this would handle if foo { return 5; } else { return 6; } */
success = true;
goto fn_ret;
}
@@ -1438,6 +1440,9 @@ static bool types_expr(Typer *tr, Expression *e) {
case EXPR_TYPE:
t->kind = TYPE_TYPE;
break;
+ case EXPR_VAL:
+ assert(0);
+ return false;
}
e->type.flags |= TYPE_FLAG_RESOLVED;
return true;
diff --git a/types.h b/types.h
index d6143da..84ae982 100644
--- a/types.h
+++ b/types.h
@@ -367,7 +367,8 @@ typedef enum {
EXPR_DSIZEOF,
EXPR_DALIGNOF,
EXPR_SLICE,
- EXPR_TYPE
+ EXPR_TYPE,
+ EXPR_VAL /* a value (it's useful to have this). for now, tuples are not supported. see cgen_set_tuple */
} ExprKind;
typedef enum {
@@ -535,6 +536,10 @@ typedef struct Expression {
};
struct Expression *tuple;
Type typeval;
+ struct {
+ Value val;
+ IdentID val_c_id;
+ };
};
} Expression;