diff options
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 122 |
1 files changed, 117 insertions, 5 deletions
@@ -179,6 +179,8 @@ static bool val_truthiness(Value *v, Type *t) { return false; } + + static I64 val_to_i64(Value *v, BuiltinType v_type) { switch (v_type) { case BUILTIN_I8: return (I64)v->i8; @@ -195,6 +197,8 @@ static I64 val_to_i64(Value *v, BuiltinType v_type) { return 0; } + + static U64 val_to_u64(Value *v, BuiltinType v_type) { if (v_type == BUILTIN_U64) return v->u64; return (U64)val_to_i64(v, v_type); @@ -229,6 +233,106 @@ static void u64_to_val(Value *v, BuiltinType v_type, U64 x) { i64_to_val(v, v_type, (I64)x); } + +static bool val_is_nonnegative(Value *v, Type *t) { + assert(t->kind == TYPE_BUILTIN); + if (!type_builtin_is_signed(t->builtin)) + return true; + return val_to_i64(v, t->builtin) >= 0; +} + +static void fprint_val_ptr(FILE *f, void *p, Type *t) { + switch (t->kind) { + case TYPE_VOID: + fprintf(f, "(void)"); + break; + case TYPE_UNKNOWN: + fprintf(f, "???"); + break; + case TYPE_BUILTIN: + switch (t->builtin) { + case BUILTIN_I8: fprintf(f, "%"PRId8, *(I8 *)p); break; + case BUILTIN_U8: fprintf(f, "%"PRIu8, *(U8 *)p); break; + case BUILTIN_I16: fprintf(f, "%"PRId16, *(I16 *)p); break; + case BUILTIN_U16: fprintf(f, "%"PRIu16, *(U16 *)p); break; + case BUILTIN_I32: fprintf(f, "%"PRId32, *(I32 *)p); break; + case BUILTIN_U32: fprintf(f, "%"PRIu32, *(U32 *)p); break; + case BUILTIN_I64: fprintf(f, "%"PRId64, *(I64 *)p); break; + case BUILTIN_U64: fprintf(f, "%"PRIu64, *(U64 *)p); break; + case BUILTIN_F32: fprintf(f, F32_FMT, *(F32 *)p); break; + case BUILTIN_F64: fprintf(f, F64_FMT, *(F64 *)p); break; + case BUILTIN_CHAR: fprintf(f, "'%c'", *(char *)p); break; + case BUILTIN_BOOL: fprintf(f, "%s", *(bool *)p ? "true" : "false"); break; + } + break; + case TYPE_FN: + fprintf(f, "<function @ %p>", (void *)*(FnExpr **)p); + break; + case TYPE_TUPLE: + fprintf(f, "<tuple>"); + break; + case TYPE_ARR: { + fprintf(f, "["); /* TODO: change? when array initializers are added */ + size_t n = t->arr.n; + if (n > 5) n = 5; + for (size_t i = 0; i < n; i++) { + if (i) fprintf(f, ", "); + fprint_val_ptr(f, *(char **)p + i * compiler_sizeof(t->arr.of), t->arr.of); + } + if (t->arr.n > n) { + fprintf(f, ", ..."); + } + fprintf(f, "]"); + } break; + case TYPE_PTR: + fprintf(f, "<pointer: %p>", *(void **)p); + break; + case TYPE_SLICE: { + fprintf(f, "["); /* TODO: change? when slice initializers are added */ + Slice slice = *(Slice *)p; + I64 n = slice.n; + if (n > 5) n = 5; + for (I64 i = 0; i < n; i++) { + if (i) fprintf(f, ", "); + fprint_val_ptr(f, (char *)slice.data + i * (I64)compiler_sizeof(t->arr.of), t->arr.of); + } + if (slice.n > n) { + fprintf(f, ", ..."); + } + fprintf(f, "]"); + } break; + case TYPE_TYPE: + fprint_type(f, *(Type **)p); + break; + case TYPE_USER: + fprint_val_ptr(f, p, type_user_underlying(t)); + break; + case TYPE_STRUCT: + fprintf(f, "["); /* TODO: change? when struct initializers are added */ + arr_foreach(t->struc.fields, Field, fi) { + if (fi != t->struc.fields) + fprintf(f, ", "); + fprint_ident(f, fi->name); + fprintf(f, ": "); + fprint_val_ptr(f, *(char **)p + fi->offset, fi->type); + } + fprintf(f, "]"); + break; + } +} + +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]); + } + fprintf(f, ")"); + } else { + fprint_val_ptr(f, v, t); + } +} + /* IMPORTANT: Only pass an evaluator if you want it to use its allocator. Otherwise, pass NULL. @@ -680,7 +784,7 @@ static bool eval_address_of(Evaluator *ev, Expression *e, void **ptr) { switch (e->kind) { case EXPR_IDENT: { IdentDecl *id = ident_decl(e->ident); - if (!(id->flags & IDECL_FLAG_HAS_VAL)) { + if (!(id->flags & IDECL_HAS_VAL)) { err_print(e->where, "Cannot take address of run time variable at compile time."); return false; } @@ -735,7 +839,7 @@ static bool eval_set(Evaluator *ev, Expression *set, Value *to) { switch (set->kind) { case EXPR_IDENT: { IdentDecl *id = ident_decl(set->ident); - if (!(id->flags & IDECL_FLAG_HAS_VAL)) { + if (!(id->flags & IDECL_HAS_VAL)) { err_print(set->where, "Cannot set value of run time variable at compile time."); return false; } @@ -1043,6 +1147,14 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { if (!eval_block(ev, &w->body, &e->type, v)) return false; } } break; + case EXPR_EACH: { + EachExpr *ea = &e->each; + /* TODO: ASDF */ + if (ea->flags & EACH_IS_RANGE) { + + } else { + } + } break; case EXPR_BLOCK: if (!eval_block(ev, &e->block, &e->type, v)) return false; break; @@ -1069,7 +1181,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { Declaration *d = idecl->decl; if (!types_decl(ev->typer, d)) return false; assert(d->type.flags & TYPE_FLAG_RESOLVED); - if (idecl->flags & IDECL_FLAG_HAS_VAL) { + if (idecl->flags & IDECL_HAS_VAL) { *v = idecl->val; } else if (d->flags & DECL_FLAG_CONST) { if (!(d->flags & DECL_FLAG_FOUND_VAL)) { @@ -1166,7 +1278,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { Type *type = p->type.kind == TYPE_TUPLE ? &p->type.tuple[idx++] : &p->type; IdentDecl *id = ident_decl(*i); val_copy(NULL, &id->val, &args[arg], type); - id->flags |= IDECL_FLAG_HAS_VAL; + id->flags |= IDECL_HAS_VAL; arg++; } } @@ -1270,7 +1382,7 @@ static bool eval_decl(Evaluator *ev, Declaration *d) { } } index++; - id->flags |= IDECL_FLAG_HAS_VAL; + id->flags |= IDECL_HAS_VAL; } } return true; |