summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c8
-rw-r--r--package.c164
-rw-r--r--test.toc2
-rw-r--r--tokenizer.c10
-rw-r--r--types.c9
-rw-r--r--types.h19
6 files changed, 157 insertions, 55 deletions
diff --git a/cgen.c b/cgen.c
index 9ca2537..2ba5cec 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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: {
diff --git a/package.c b/package.c
index 4738781..a5b26b8 100644
--- a/package.c
+++ b/package.c
@@ -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;
diff --git a/test.toc b/test.toc
index 9931d47..0f46697 100644
--- a/test.toc
+++ b/test.toc
@@ -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;
diff --git a/types.c b/types.c
index 4fcf54c..63ae5d4 100644
--- a/types.c
+++ b/types.c
@@ -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: {
diff --git a/types.h b/types.h
index 3fd0fa2..0c6d863 100644
--- a/types.h
+++ b/types.h
@@ -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;