From ba8e7628a2e0e48ac89a4bd734edde0c0dfc3929 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Thu, 26 Dec 2019 23:38:39 -0500 Subject: more export --- binfile.c | 39 ++++++++++++++++++++++++++++ export.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- test.toc | 4 +-- types.c | 6 ++++- 4 files changed, 121 insertions(+), 15 deletions(-) diff --git a/binfile.c b/binfile.c index 8a45084..9ca175b 100644 --- a/binfile.c +++ b/binfile.c @@ -4,6 +4,12 @@ static inline void write_u8(FILE *fp, U8 u8) { putc(u8, fp); } +static inline void write_i8(FILE *fp, I8 i8) { + U8 byte = (U8)(i8 < 0 ? -i8 : +i8); + if (i8 < 0) byte |= 0x80; + putc(byte, fp); +} + /* note: a bit of testing seems to reveal that the portable versions for u16/32 are faster than fwrite (but this is not the case for u64). @@ -14,11 +20,21 @@ static inline void write_u16(FILE *fp, U16 u16) { putc(u16 >> 8, fp); } +static inline void write_i16(FILE *fp, I16 i16) { + write_u8(fp, (U8)(i16 & 0xFF)); + write_i8(fp, (I8)(i16 / 0x100)); /* division is necessary here to keep sign */ +} + static inline void write_u32(FILE *fp, U32 u32) { write_u16(fp, u32 & 0xFFFF); write_u16(fp, (U16)(u32 >> 16)); } +static inline void write_i32(FILE *fp, I32 i32) { + write_u16(fp, (U16)(i32 & 0xFFFF)); + write_i16(fp, (I16)(i32 / 0x10000)); +} + static void write_u64(FILE *fp, U64 u64) { #if BINFILE_PORTABLE write_u32(fp, u64 & 0xFFFFFFFF); @@ -28,4 +44,27 @@ static void write_u64(FILE *fp, U64 u64) { #endif } +static void write_i64(FILE *fp, I64 i64) { +#if BINFILE_PORTABLE + write_u32(fp, (U32)(i64 & 0xFFFFFFFF)); + write_i32(fp, (I32)(i64 / 0x100000000)); +#else + fwrite(&i64, sizeof i64, 1, fp); +#endif +} +static void write_f32(FILE *fp, F32 f32) { +#if BINFILE_PORTABLE + /* TODO */ +#else + fwrite(&f32, sizeof f32, 1, fp); +#endif +} + +static void write_f64(FILE *fp, F64 f64) { +#if BINFILE_PORTABLE + /* TODO */ +#else + fwrite(&f64, sizeof f64, 1, fp); +#endif +} diff --git a/export.c b/export.c index 571701e..28e03e0 100644 --- a/export.c +++ b/export.c @@ -36,16 +36,70 @@ static void export_ident(Exporter *ex, Identifier i) { export_u64(ex, i->id); } -static bool export_decl(Exporter *ex, Declaration *d) { - if (!ex) { - err_print(d->where, "Trying to export declaration, but a package output was not specified."); +static inline bool type_contains_reference(Type *type) { + assert(type->flags & TYPE_IS_RESOLVED); + switch (type->kind) { + case TYPE_PTR: + case TYPE_SLICE: + case TYPE_FN: + return true; + case TYPE_TUPLE: + arr_foreach(type->tuple, Type, sub) + if (type_contains_reference(sub)) + return true; return false; - } - export_location(ex, d->where); - if (arr_len(d->idents) > 65535) { - err_print(d->where, "Too many identifiers in a declaration (the maximum is 65535)."); + case TYPE_STRUCT: + arr_foreach(type->struc->fields, Field, field) { + if (type_contains_reference(field->type)) + return true; + } + return false; + case TYPE_ARR: + return type_contains_reference(type->arr.of); + case TYPE_BUILTIN: + case TYPE_VOID: + case TYPE_UNKNOWN: + case TYPE_TYPE: return false; + case TYPE_EXPR: break; } + assert(0); + return false; +} + +static void export_type(Exporter *ex, Type *type) { +} + +static void export_val(Exporter *ex, Value val, Type *type) { + assert(!type_contains_reference(type)); + export_type(ex, type); + switch (type->kind) { + case TYPE_VOID: break; + case TYPE_TYPE: + export_type(ex, val.type); + break; + case TYPE_UNKNOWN: + case TYPE_EXPR: + assert(0); + break; + } +} + +static void export_expr(Exporter *ex, Expression *e) { +} + +enum { + DECL_EXPORT_NONE, + DECL_EXPORT_EXPR, + DECL_EXPORT_VAL +}; + +static void export_decl(Exporter *ex, Declaration *d) { + if (d->type.kind == TYPE_UNKNOWN) { + warn_print(d->where, "Can't export declaration of unknown type."); + return; + } + export_location(ex, d->where); export_u16(ex, (U16)arr_len(d->idents)); arr_foreach(d->idents, Identifier, ident) { export_ident(ex, *ident); @@ -57,10 +111,19 @@ static bool export_decl(Exporter *ex, Declaration *d) { export_u8(ex, constness); U8 expr_kind = 0; - if (d->flags & DECL_HAS_EXPR) expr_kind = 1; /* export expression */ - if (d->flags & DECL_FOUND_VAL) expr_kind = 2; /* export value */ - export_u8(ex, expr_kind); - + if (d->flags & DECL_HAS_EXPR) expr_kind = DECL_EXPORT_EXPR; + if (d->flags & DECL_FOUND_VAL) { + if (type_contains_reference(&d->type)) + expr_kind = DECL_EXPORT_EXPR; + else + expr_kind = DECL_EXPORT_VAL; + } - return true; + export_u8(ex, expr_kind); + + if (expr_kind == DECL_EXPORT_EXPR) { + export_expr(ex, &d->expr); + } else if (expr_kind == DECL_EXPORT_VAL) { + export_val(ex, d->val, &d->type); + } } diff --git a/test.toc b/test.toc index edb175d..d5b1c53 100644 --- a/test.toc +++ b/test.toc @@ -1,2 +1,2 @@ -foo ::= 7; -#export asdf, dsajkhf, sadjkfh ::= 5; \ No newline at end of file +#export foo ::= 7; +asdf, dsajkhf, sadjkfh ::= 5; \ No newline at end of file diff --git a/types.c b/types.c index 075c8de..ffebc1d 100644 --- a/types.c +++ b/types.c @@ -2024,8 +2024,12 @@ static bool types_decl(Typer *tr, Declaration *d) { if (success) { if (d->flags & DECL_EXPORT) { /* export it! */ - if (!export_decl(tr->exptr, d)) + if (!tr->exptr) { + err_print(d->where, "Declaration marked for exporting, but no package output was specified."); success = false; + } else { + export_decl(tr->exptr, d); + } } } else { /* use unknown type if we didn't get the type */ -- cgit v1.2.3