summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-12-26 23:38:39 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2019-12-26 23:38:39 -0500
commitba8e7628a2e0e48ac89a4bd734edde0c0dfc3929 (patch)
treed2bf64cdebd7d6afb37542842ae5b351ad71e01d
parent7dfcdf50dda531095f1b1235fafa002457107e6c (diff)
more export
-rw-r--r--binfile.c39
-rw-r--r--export.c87
-rw-r--r--test.toc4
-rw-r--r--types.c6
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 */