diff options
-rw-r--r-- | cgen.c | 8 | ||||
-rw-r--r-- | package.c | 164 | ||||
-rw-r--r-- | test.toc | 2 | ||||
-rw-r--r-- | tokenizer.c | 10 | ||||
-rw-r--r-- | types.c | 9 | ||||
-rw-r--r-- | types.h | 19 |
6 files changed, 157 insertions, 55 deletions
@@ -1144,7 +1144,7 @@ static bool cgen_expr(CGenerator *g, Expression *e) { cgen_write(g, "%.16Lf", (long double)e->floatl); /* TODO(eventually): better precision? */ break; case EXPR_LITERAL_INT: - cgen_write(g, UINTEGER_FMT, e->intl); + cgen_write(g, "%"PRIu64, e->intl); break; case EXPR_LITERAL_STR: { size_t c; @@ -1394,11 +1394,9 @@ static bool cgen_expr(CGenerator *g, Expression *e) { } break; case EXPR_C: { - Value val; - if (!eval_expr(g->evalr, e->c.code, &val)) - return false; + assert(e->kind == EXPR_VAL); cgen_indent(g); - fwrite(val.slice.data, 1, (size_t)val.slice.n, cgen_writing_to(g)); + fwrite(e->val.slice.data, 1, (size_t)e->val.slice.n, cgen_writing_to(g)); } break; case EXPR_DSIZEOF: case EXPR_DALIGNOF: { @@ -55,56 +55,119 @@ static void export_location(Exporter *ex, Location where) { static void export_ident(Exporter *ex, Identifier i) { assert(i->id); - export_u64(ex, i->id); + if (sizeof i->id == 8) { + export_u64(ex, (U64)i->id); + } else { + assert(sizeof i->id == 4); + export_u32(ex, (U32)i->id); + } } -static void export_type(Exporter *ex, Type *type) { -} -static bool export_len(Exporter *ex, size_t len, const char *for_, Location where) { +static bool export_len16(Exporter *ex, size_t len, const char *for_, Location where) { if (len > 65535) { err_print(where, "Too many %s (the maximum is 65535).", for_); return false; } - export_len(ex, (U16)len); + export_u16(ex, (U16)len); return true; } - -static bool export_val(Exporter *ex, Value val, Type *type, Location where) { - export_type(ex, type); +static bool export_type(Exporter *ex, Type *type, Location where) { + assert(type->flags & TYPE_IS_RESOLVED); + export_u8(ex, (U8)type->kind); switch (type->kind) { - case TYPE_VOID: break; + case TYPE_VOID: + case TYPE_TYPE: + case TYPE_UNKNOWN: + break; + case TYPE_PTR: export_type(ex, type->ptr, where); break; + case TYPE_SLICE: export_type(ex, type->slice, where); break; case TYPE_BUILTIN: - switch (type->builtin) { - case BUILTIN_I8: export_i8(ex, val.i8); break; - case BUILTIN_U8: export_u8(ex, val.u8); break; - case BUILTIN_I16: export_i16(ex, val.i16); break; - case BUILTIN_U16: export_u16(ex, val.u16); break; - case BUILTIN_I32: export_i32(ex, val.i32); break; - case BUILTIN_U32: export_u32(ex, val.u32); break; - case BUILTIN_I64: export_i64(ex, val.i64); break; - case BUILTIN_U64: export_u64(ex, val.u64); break; - case BUILTIN_F32: export_f32(ex, val.f32); break; - case BUILTIN_F64: export_f64(ex, val.f64); break; - case BUILTIN_BOOL: export_bool(ex, val.boolv); break; - case BUILTIN_CHAR: export_char(ex, val.charv); break; - } + export_u8(ex, (U8)type->builtin); break; case TYPE_TUPLE: - if (arr_len(type->tuple) > 65535) { - err_print(where, "Too many types in one tuple."); + if (!export_len16(ex, arr_len(type->tuple), "types in a tuple", where)) return false; + arr_foreach(type->tuple, Type, sub) + if (!export_type(ex, sub, where)) + return false; + break; + case TYPE_ARR: + export_u64(ex, type->arr.n); + if (!export_type(ex, type->arr.of, where)) + return false; + break; + case TYPE_EXPR: + assert(0); + return false; + } + return true; +} + +static bool export_val(Exporter *ex, Value val, Type *type, Location where); +static bool export_val_ptr(Exporter *ex, void *val, Type *type, Location where) { + switch (type->kind) { + case TYPE_VOID: break; + case TYPE_BUILTIN: + switch (type->builtin) { + case BUILTIN_I8: export_i8(ex, *(I8 *)val); break; + case BUILTIN_U8: export_u8(ex, *(U8 *)val); break; + case BUILTIN_I16: export_i16(ex, *(I16 *)val); break; + case BUILTIN_U16: export_u16(ex, *(U16 *)val); break; + case BUILTIN_I32: export_i32(ex, *(I32 *)val); break; + case BUILTIN_U32: export_u32(ex, *(U32 *)val); break; + case BUILTIN_I64: export_i64(ex, *(I64 *)val); break; + case BUILTIN_U64: export_u64(ex, *(U64 *)val); break; + case BUILTIN_F32: export_f32(ex, *(F32 *)val); break; + case BUILTIN_F64: export_f64(ex, *(F64 *)val); break; + case BUILTIN_BOOL: export_bool(ex, *(bool *)val); break; + case BUILTIN_CHAR: export_char(ex, *(char *)val); break; } - export_u16((U16)arr_len(type->tuple)); - break; + case TYPE_TUPLE: { + size_t n = arr_len(type->tuple); + Value *vals = *(Value **)val; + for (size_t i = 0; i < n; ++i) { + if (!export_val(ex, vals[i], &type->tuple[i], where)) + return false; + } + } break; case TYPE_TYPE: - export_type(ex, val.type); + if (!export_type(ex, *(Type **)val, where)) + return false; break; case TYPE_PTR: err_print(where, "Cannot export pointer."); return false; + case TYPE_ARR: { + size_t item_size = compiler_sizeof(type->arr.of); + char *ptr = val; + for (U64 i = 0; i < type->arr.n; ++i) { + if (!export_val_ptr(ex, ptr, type->arr.of, where)) + return false; + ptr += item_size; + } + } break; + case TYPE_STRUCT: + eval_struct_find_offsets(type); + arr_foreach(type->struc->fields, Field, f) { + if (!export_val_ptr(ex, (char *)val + f->offset, f->type, where)) + return false; + } + break; + case TYPE_SLICE: { + Slice slice = *(Slice *)val; + I64 n = slice.n; + size_t item_size = compiler_sizeof(type->slice); + export_i64(ex, n); + char *ptr = slice.data; + for (I64 i = 0; i < n; ++i) { + if (!export_val_ptr(ex, ptr, type->slice, where)) + return false; + ptr += item_size; + } + } break; case TYPE_UNKNOWN: case TYPE_EXPR: assert(0); @@ -113,7 +176,42 @@ static bool export_val(Exporter *ex, Value val, Type *type, Location where) { return true; } +static bool export_val(Exporter *ex, Value val, Type *type, Location where) { + return export_val_ptr(ex, val_get_ptr(&val, type), type, where); +} + static bool export_expr(Exporter *ex, Expression *e) { + assert(e->flags & EXPR_FOUND_TYPE); + if (!export_type(ex, &e->type, e->where)) + return false; + switch (e->kind) { + case EXPR_LITERAL_INT: + export_u64(ex, e->intl); + break; + case EXPR_LITERAL_FLOAT: + if (e->type.builtin == BUILTIN_F32) + export_f32(ex, (F32)e->floatl); + else + export_f64(ex, (F64)e->floatl); + break; + case EXPR_LITERAL_BOOL: + export_bool(ex, e->booll); + break; + case EXPR_LITERAL_CHAR: + export_char(ex, e->charl); + break; + case EXPR_LITERAL_STR: + fwrite(e->strl.str, 1, e->strl.len, ex->out); + break; + case EXPR_C: + assert(e->c.code->kind == EXPR_VAL); + export_val(ex, e->c.code->val, &e->c.code->type, e->where); + break; + case EXPR_IDENT: + export_ident(ex, e->ident); + break; + + } return true; } @@ -129,16 +227,15 @@ static bool export_decl(Exporter *ex, Declaration *d) { return false; } export_location(ex, d->where); - size_t n_idents = arr_len(d->idents); - if (n_idents > 65535) { - err_print(d->where, "Too many identifiers in one declaration (the maximum is 65535)."); + if (!export_len16(ex, arr_len(d->idents), "identifiers in one declaration", d->where)) return false; - } - export_u16(ex, (U16)arr_len(d->idents)); arr_foreach(d->idents, Identifier, ident) { export_ident(ex, *ident); } + if (!export_type(ex, &d->type, d->where)) + return false; + U8 constness = 0; if (d->flags & DECL_IS_CONST) constness = 1; else if (d->flags & DECL_SEMI_CONST) constness = 2; @@ -151,7 +248,6 @@ static bool export_decl(Exporter *ex, Declaration *d) { expr_kind = DECL_EXPORT_VAL; export_u8(ex, expr_kind); - if (expr_kind == DECL_EXPORT_EXPR) { if (!export_expr(ex, &d->expr)) return false; @@ -1,2 +1,4 @@ #export foo :: f64 = 0.07321; // asdf, dsajkhf, sadjkfh ::= 5; +// #export asdf ::= "asdfasdfasdf"; +#export zla := foo;
\ No newline at end of file diff --git a/tokenizer.c b/tokenizer.c index 5d245d9..710ea25 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -94,7 +94,7 @@ static void fprint_token(FILE *out, Token *t) { fprintf(out, "number: "); switch (t->num.kind) { case NUM_LITERAL_INT: - fprintf(out, INTEGER_FMT, t->num.intval); + fprintf(out, "%"PRIu64, t->num.intval); break; case NUM_LITERAL_FLOAT: fprintf(out, "%g", (double)t->num.floatval); @@ -406,14 +406,14 @@ static bool tokenize_string(Tokenizer *t, char *str) { } switch (n->kind) { case NUM_LITERAL_INT: - if ((UInteger)n->intval > (UInteger)UINTEGER_MAX / (UInteger)base || - (UInteger)n->intval * (UInteger)base > (UInteger)UINTEGER_MAX - (UInteger)digit) { + if (n->intval > U64_MAX / (U64)base || + n->intval * (U64)base > U64_MAX - (U64)digit) { /* too big! */ tokenization_err(t, "Number too big to fit in a numeric literal."); goto err; } - n->intval *= (UInteger)base; - n->intval += (UInteger)digit; + n->intval *= (U64)base; + n->intval += (U64)digit; break; case NUM_LITERAL_FLOAT: n->floatval += decimal_pow10 * (Floating)digit; @@ -473,14 +473,14 @@ static bool type_resolve(Typer *tr, Type *t, Location where) { if (type_builtin_is_signed(n_expr->type.builtin)) { I64 ssize = val_to_i64(&val, n_expr->type.builtin); if (ssize < 0) { - err_print(t->arr.n_expr->where, "Negative array length (" INTEGER_FMT ")", ssize); + err_print(t->arr.n_expr->where, "Negative array length (%" PRId64 ")", ssize); return false; } size = (U64)ssize; } else { size = val_to_u64(&val, n_expr->type.builtin); } - t->arr.n = (UInteger)size; + t->arr.n = (U64)size; if (!type_resolve(tr, t->arr.of, where)) return false; } break; @@ -1482,6 +1482,11 @@ static bool types_expr(Typer *tr, Expression *e) { free(s); return false; } + Value code_val; + if (!eval_expr(tr->evalr, code, &code_val)) + return false; + code->val = code_val; + code->kind = EXPR_VAL; t->kind = TYPE_UNKNOWN; } break; case EXPR_DSIZEOF: { @@ -5,8 +5,6 @@ */ /* NOTE: make sure you edit copy.c when you make a change to expression-related types or type-related types in this file! */ -typedef int64_t Integer; -typedef uint64_t UInteger; typedef long double Floating; /* OPTIM: Switch to double, but make sure floating-point literals are right */ #if __STDC_VERSION__ < 201112 @@ -24,20 +22,23 @@ typedef union { typedef max_align_t MaxAlign; #endif -#define INTEGER_MAX INT64_MAX -#define UINTEGER_MAX UINT64_MAX -#define INTEGER_FMT "%"PRId64 -#define UINTEGER_FMT "%"PRIu64 - typedef uint8_t U8; +#define U8_MAX UINT8_MAX typedef uint16_t U16; +#define U16_MAX UINT16_MAX typedef uint32_t U32; +#define U32_MAX UINT32_MAX typedef uint64_t U64; +#define U64_MAX UINT64_MAX typedef int8_t I8; +#define I8_MAX INT8_MAX typedef int16_t I16; +#define I16_MAX INT16_MAX typedef int32_t I32; +#define I32_MAX INT32_MAX typedef int64_t I64; +#define I64_MAX INT64_MAX /* NOTE: if you change these, make sure you change hash_tables.c */ typedef float F32; @@ -272,7 +273,7 @@ typedef enum { typedef struct NumLiteral { NumLiteralKind kind; union { - UInteger intval; + U64 intval; Floating floatval; }; } NumLiteral; @@ -585,7 +586,7 @@ typedef struct Expression { union { Floating floatl; /* Floating floatl; */ - UInteger intl; + U64 intl; StrLiteral strl; bool booll; char charl; |