summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-01-10 23:16:58 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-01-10 23:16:58 -0500
commit2b3259e99d2dc75706aea4ce2112e0e1ec5aedf7 (patch)
treebd8ac918c1199533275e381eaba2de28bc226f96
parent56a9ba5ea53a5d0b6268939d6a6e89837c2e4658 (diff)
realized i need to be able to export untyped expressions!
-rw-r--r--package.c180
-rw-r--r--point.toc5
-rw-r--r--test.toc3
-rw-r--r--toc.c7
-rw-r--r--types.h12
5 files changed, 150 insertions, 57 deletions
diff --git a/package.c b/package.c
index 518bf93..221591c 100644
--- a/package.c
+++ b/package.c
@@ -11,6 +11,7 @@ static bool export_block(Exporter *ex, Block *b);
static bool export_expr(Exporter *ex, Expression *e);
static bool import_footer(Importer *i);
static void import_decl(Importer *im, Declaration *d);
+static void import_expr(Importer *im, Expression *e);
static void exptr_create(Exporter *ex, FILE *out) {
ex->out = out;
@@ -106,12 +107,25 @@ static inline void export_vlq(Exporter *ex, U64 x) {
static inline U64 import_vlq(Importer *i) {
return read_vlq(i->in);
}
+static inline void export_len(Exporter *ex, size_t len) {
+ export_vlq(ex, (U64)len);
+}
+static inline size_t import_len(Importer *i) {
+ return (size_t)import_vlq(i);
+}
+
-static void imptr_arr_create_(Importer *im, void **arr, size_t sz, size_t len) {
+static size_t import_arr_(Importer *im, void **arr, size_t sz) {
*arr = NULL;
+ size_t len = import_len(im);
arr_set_lena_(arr, len, sz, im->allocr);
+ return len;
}
-#define imptr_arr_create(im, arr, len) imptr_arr_create_(im, (void **)arr, sizeof **(arr), len)
+/*
+reads length and allocates an array of that length
+returns length
+*/
+#define import_arr(im, arr) import_arr_(im, (void **)arr, sizeof **(arr))
static inline void export_str(Exporter *ex, const char *str, size_t len) {
#ifdef TOC_DEBUG
@@ -164,13 +178,6 @@ static inline void export_optional_ident(Exporter *ex, Identifier i) {
}
}
-static inline void export_len(Exporter *ex, size_t len) {
- export_vlq(ex, (U64)len);
-}
-static inline size_t import_len(Importer *i) {
- return (size_t)import_vlq(i);
-}
-
static const U8 toc_package_indicator[3] = {116, 111, 112};
/* writes the header */
@@ -253,13 +260,15 @@ static bool import_pkg(Allocator *allocr, Package *p, FILE *f, const char *fname
return true;
}
+/* needs to handle unresolved AND resolved types! (for fns with const params) */
static bool export_type(Exporter *ex, Type *type, Location where) {
- assert(type->flags & TYPE_IS_RESOLVED);
if (type->kind == TYPE_BUILTIN) {
export_u8(ex, (U8)((int)type->builtin + TYPE_COUNT));
} else {
export_u8(ex, (U8)type->kind);
- }
+ }
+ assert(sizeof type->flags == 1);
+ export_u8(ex, type->flags);
switch (type->kind) {
case TYPE_VOID:
case TYPE_UNKNOWN:
@@ -275,7 +284,12 @@ static bool export_type(Exporter *ex, Type *type, Location where) {
break;
case TYPE_ARR:
/* smaller arrays are more common */
- export_vlq(ex, type->arr.n);
+ if (type->flags & TYPE_IS_RESOLVED)
+ export_vlq(ex, type->arr.n);
+ else
+ if (!export_expr(ex, type->arr.n_expr))
+ return false;
+
if (!export_type(ex, type->arr.of, where))
return false;
break;
@@ -286,7 +300,7 @@ static bool export_type(Exporter *ex, Type *type, Location where) {
return false;
export_bool(ex, type->fn.constness != NULL);
/* [implied] if (type->fn.constness) */
- assert(sizeof(Constness) == 1); /* future-proofing */
+ possibly_static_assert(sizeof(Constness) == 1); /* future-proofing */
arr_foreach(type->fn.constness, Constness, c)
export_u8(ex, *c);
break;
@@ -306,19 +320,64 @@ static bool export_type(Exporter *ex, Type *type, Location where) {
export_len(ex, (size_t)struc->export.id);
} break;
case TYPE_EXPR:
- assert(0);
- return false;
+ if (!export_expr(ex, type->expr))
+ return false;
+ break;
}
return true;
}
+static inline Type *imptr_new_type(Importer *im) {
+ return imptr_malloc(im, sizeof(Type));
+}
+static inline Expression *imptr_new_expr(Importer *im) {
+ return imptr_malloc(im, sizeof(Expression));
+}
+
static void import_type(Importer *im, Type *type) {
U8 kind = import_u8(im);
if (kind > TYPE_COUNT) {
type->kind = TYPE_BUILTIN;
type->builtin = (BuiltinType)(kind - TYPE_COUNT);
} else {
-
+ type->kind = (TypeKind)kind;
+ }
+ int is_resolved = type->flags & TYPE_IS_RESOLVED;
+ type->flags = import_u8(im);
+ switch (type->kind) {
+ case TYPE_VOID:
+ case TYPE_BUILTIN:
+ case TYPE_UNKNOWN:
+ break;
+ case TYPE_PTR:
+ import_type(im, type->ptr = imptr_new_type(im));
+ break;
+ case TYPE_SLICE:
+ import_type(im, type->slice = imptr_new_type(im));
+ break;
+ case TYPE_TUPLE: {
+ size_t ntypes = import_arr(im, &type->tuple);
+ for (size_t i = 0; i < ntypes; ++i) {
+ import_type(im, &type->tuple[i]);
+ }
+ } break;
+ case TYPE_ARR:
+ if (is_resolved)
+ type->arr.n = import_vlq(im);
+ else
+ import_expr(im, type->arr.n_expr = imptr_new_expr(im));
+ import_type(im, type->arr.of = imptr_new_type(im));
+ break;
+ case TYPE_FN: {
+ size_t i, ntypes = import_arr(im, &type->fn.types);
+ for (i = 0; i < ntypes; ++i)
+ import_type(im, &type->fn.types[i]);
+ bool has_constness = import_bool(im);
+ if (has_constness) {
+ for (i = 0; i < ntypes; ++i)
+ type->fn.constness[i] = import_u8(im);
+ } else type->fn.constness = NULL;
+ } break;
}
}
@@ -441,19 +500,23 @@ static inline bool export_optional_expr(Exporter *ex, Expression *e) {
}
static bool export_expr(Exporter *ex, Expression *e) {
- assert(e->flags & EXPR_FOUND_TYPE);
- if (!export_type(ex, &e->type, e->where))
- return false;
+ possibly_static_assert(sizeof e->flags == 1);
+ export_u8(ex, (U8)e->flags);
+ int found_type = e->flags & EXPR_FOUND_TYPE;
+ if (found_type) {
+ if (!export_type(ex, &e->type, e->where))
+ return false;
+ }
switch (e->kind) {
case EXPR_LITERAL_INT:
/* smaller int literals are more common */
export_vlq(ex, e->intl);
break;
case EXPR_LITERAL_FLOAT:
- if (e->type.builtin == BUILTIN_F32)
- export_f32(ex, (F32)e->floatl);
- else
+ if (e->type.flags & TYPE_IS_FLEXIBLE || e->type.builtin == BUILTIN_F64)
export_f64(ex, (F64)e->floatl);
+ else
+ export_f32(ex, (F32)e->floatl);
break;
case EXPR_LITERAL_BOOL:
export_bool(ex, e->booll);
@@ -465,8 +528,7 @@ static bool export_expr(Exporter *ex, Expression *e) {
fwrite(e->strl.str, 1, e->strl.len, ex->out);
break;
case EXPR_C:
- assert(e->c.code->kind == EXPR_VAL);
- if (!export_val(ex, e->c.code->val, &e->c.code->type, e->where))
+ if (!export_expr(ex, e->c.code))
return false;
break;
case EXPR_IDENT:
@@ -481,17 +543,6 @@ static bool export_expr(Exporter *ex, Expression *e) {
export_u8(ex, (U8)e->binary.op);
if (!export_expr(ex, e->binary.lhs))
return false;
- if (e->binary.op == BINARY_DOT) {
- /* rhs may not typed (if it's a string it will be)! */
- Expression *rhs = e->binary.rhs;
- bool rhs_found_type = (rhs->flags & EXPR_FOUND_TYPE) != 0;
- export_bool(ex, rhs_found_type);
- if (!rhs_found_type) {
- assert(rhs->kind == EXPR_IDENT);
- export_ident(ex, rhs->ident);
- break;
- }
- }
if (!export_expr(ex, e->binary.rhs))
return false;
break;
@@ -532,10 +583,20 @@ static bool export_expr(Exporter *ex, Expression *e) {
CallExpr *c = &e->call;
if (!export_expr(ex, c->fn))
return false;
- export_len(ex, arr_len(c->arg_exprs));
- arr_foreach(c->arg_exprs, Expression, arg)
- if (!export_expr(ex, arg))
- return false;
+ if (found_type) {
+ export_len(ex, arr_len(c->arg_exprs));
+ arr_foreach(c->arg_exprs, Expression, arg)
+ if (!export_expr(ex, arg))
+ return false;
+ } else {
+ export_len(ex, arr_len(c->args));
+ arr_foreach(c->args, Argument, arg) {
+ export_location(ex, arg->where);
+ export_ident(ex, arg->name);
+ if (!export_expr(ex, &arg->val))
+ return false;
+ }
+ }
} break;
case EXPR_IF: {
IfExpr *i = &e->if_;
@@ -553,7 +614,12 @@ static bool export_expr(Exporter *ex, Expression *e) {
return false;
} break;
case EXPR_PKG:
- export_ident(ex, e->pkg.name_ident);
+ if (found_type) {
+ export_ident(ex, e->pkg.name_ident);
+ } else {
+ if (!export_expr(ex, e->pkg.name_expr))
+ return false;
+ }
break;
case EXPR_SLICE: {
SliceExpr *s = &e->slice;
@@ -570,19 +636,22 @@ static bool export_expr(Exporter *ex, Expression *e) {
return false;
export_optional_ident(ex, ea->index);
export_optional_ident(ex, ea->value);
-
if (ea->flags & EACH_IS_RANGE) {
if (!export_expr(ex, ea->range.from))
return false;
if (!export_optional_expr(ex, ea->range.to))
return false;
- if (!export_optional_val(ex, ea->range.stepval, &ea->type, e->where))
- return false;
+ if (found_type) {
+ if (!export_optional_val(ex, ea->range.stepval, &ea->type, e->where))
+ return false;
+ } else {
+ if (!export_optional_expr(ex, ea->range.step))
+ return false;
+ }
} else {
if (!export_expr(ex, ea->of))
return false;
}
-
if (!export_block(ex, &ea->body))
return false;
} break;
@@ -594,6 +663,12 @@ static bool export_expr(Exporter *ex, Expression *e) {
return true;
}
+static void import_expr(Importer *im, Expression *e) {
+ /* TODO */
+ (void)im,(void)e;
+}
+
+
enum {
DECL_EXPORT_NONE,
DECL_EXPORT_EXPR,
@@ -602,7 +677,10 @@ enum {
static bool export_decl(Exporter *ex, Declaration *d) {
assert(ex->started);
- if (d->type.kind == TYPE_UNKNOWN) {
+ bool found_type = (d->flags & DECL_FOUND_TYPE) != 0;
+ export_bool(ex, found_type);
+
+ if (found_type && d->type.kind == TYPE_UNKNOWN) {
err_print(d->where, "Can't export declaration of unknown type.");
return false;
}
@@ -622,8 +700,10 @@ static bool export_decl(Exporter *ex, Declaration *d) {
export_ident(ex, *ident);
}
- if (!export_type(ex, &d->type, d->where))
- return false;
+ if (found_type) {
+ if (!export_type(ex, &d->type, d->where))
+ return false;
+ }
U8 constness = 0;
if (d->flags & DECL_IS_CONST) constness = 1;
@@ -726,8 +806,7 @@ static bool export_struct(Exporter *ex, StructDef *s) {
}
static void import_struct(Importer *im, StructDef *s) {
- size_t nfields = import_len(im);
- imptr_arr_create(im, &s->fields, nfields);
+ size_t nfields = import_arr(im, &s->fields);
for (size_t i = 0; i < nfields; ++i) {
s->fields[i].name = import_ident(im);
import_type(im, &s->fields[i].type);
@@ -803,8 +882,7 @@ static bool import_footer(Importer *im) {
}
}
- size_t n_structs = import_len(im);
- imptr_arr_create(im, &im->structs, n_structs);
+ size_t n_structs = import_arr(im, &im->structs);
for (i = 0; i < n_structs; ++i) {
import_struct(im, &im->structs[i]);
}
diff --git a/point.toc b/point.toc
index 8bf5425..f19f055 100644
--- a/point.toc
+++ b/point.toc
@@ -13,3 +13,8 @@ pkg "point";
mk_point2 ::= fn(x, y:int) p: Point {
p = mk_point(x*x, y*y);
};
+
+#export foo ::= fn(x :: int) int {
+ k : Point = 95;
+ p:=x[3];
+}; \ No newline at end of file
diff --git a/test.toc b/test.toc
index e334817..c835a0b 100644
--- a/test.toc
+++ b/test.toc
@@ -6,6 +6,9 @@ putf ::= fn(x: float) {
#C("printf(\"%f\\n\", (double)x);
");
};
+
+
+
point ::= pkg "point";
main ::= fn() {
}; \ No newline at end of file
diff --git a/toc.c b/toc.c
index 1f6472d..6eb6feb 100644
--- a/toc.c
+++ b/toc.c
@@ -27,6 +27,13 @@
#define inline
#endif
+#if __STDC_VERSION__ >= 201112
+#define possibly_static_assert(cond) static_assert(cond, "Assertion " #cond " failed.")
+#else
+#define possibly_static_assert assert
+#endif
+
+
#include "types.h"
/* forward declarations for debugging */
diff --git a/types.h b/types.h
index af14aa2..f9520a2 100644
--- a/types.h
+++ b/types.h
@@ -398,7 +398,7 @@ enum {
TYPE_IS_FLEXIBLE = 0x01,
TYPE_IS_RESOLVED = 0x02,
};
-typedef U16 TypeFlags;
+typedef U8 TypeFlags;
typedef struct Type {
Location where;
TypeKind kind;
@@ -521,8 +521,8 @@ typedef enum {
typedef struct CallExpr {
struct Expression *fn;
union {
- struct Argument *args;
- struct Expression *arg_exprs;
+ struct Argument *args; /* before typing */
+ struct Expression *arg_exprs; /* after typing */
};
struct Instance *instance; /* NULL = ordinary function, no compile time args */
struct {
@@ -633,7 +633,7 @@ typedef struct Expression {
Type type;
Location where;
ExprKind kind;
- U16 flags;
+ U8 flags;
union {
Floating floatl;
/* Floating floatl; */
@@ -667,8 +667,8 @@ typedef struct Expression {
Type type;
} del;
union {
- struct Expression *name_expr;
- Identifier name_ident;
+ struct Expression *name_expr; /* before typing */
+ Identifier name_ident; /* after typing */
} pkg;
IfExpr if_;
WhileExpr while_;