From cc5e08b53e724b425c9db31b3ee9ec445a394ae6 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Fri, 8 Nov 2019 17:50:13 -0500 Subject: added value exprs in preparation for compile time arguments --- cgen.c | 17 +++++++++ decls_cgen.c | 1 + eval.c | 106 +++++++++++++++++++++++++++++--------------------------- main.c | 1 + parse.c | 8 +++-- typedefs_cgen.c | 1 + types.c | 13 ++++--- types.h | 7 +++- 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; -- cgit v1.2.3