diff options
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | cgen.c | 41 | ||||
-rw-r--r-- | copy.c | 3 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rw-r--r-- | parse.c | 10 | ||||
-rw-r--r-- | test.toc | 2 | ||||
-rw-r--r-- | tests/types.toc | 2 | ||||
-rw-r--r-- | types.c | 6 | ||||
-rw-r--r-- | types.h | 9 |
9 files changed, 56 insertions, 22 deletions
@@ -86,6 +86,7 @@ Here are the major versions of `toc`. <tr><td>0.3</td><td><code>struct</code> parameters</td><td>2020 Feb 25</td></tr> <tr><td>0.4</td><td>Variadic functions</td><td>2020 Mar 13</td></tr> <tr><td>0.5</td><td><code>break</code>, <code>continue</code>, <code>defer</code></td><td>2020 Mar 19</td></tr> +<tr><td>0.6</td><td><code>use</code></td><td>2020 Apr 26</td></tr> </table> --- @@ -580,8 +580,11 @@ static void cgen_val_ptr(CGenerator *g, void *v, Type *t) { cgen_fn_name(g, *(FnExpr **)v); break; case TYPE_PTR: - /* You can't have a constant pointer. */ - assert(0); + /* this can happen; as i'm writing this it's only for null */ + cgen_write(g, "(("); + cgen_type_pre(g, t); + cgen_type_post(g, t); + cgen_write(g, ")" ULONGLONG_FMT ")", (ulonglong)*(void **)v); break; case TYPE_BUILTIN: switch (t->builtin) { @@ -1982,11 +1985,12 @@ static void cgen_decl(CGenerator *g, Declaration *d) { cgen_write(g, "; "); } if (has_expr) { + Expression *expr = &d->expr; assert((g->block || g->fn) && !(d->flags & DECL_IS_CONST)); - if (d->expr.type.kind == TYPE_TUPLE) { - cgen_set_tuple(g, NULL, d->idents, NULL, &d->expr); + if (expr->type.kind == TYPE_TUPLE) { + cgen_set_tuple(g, NULL, d->idents, NULL, expr); } else { - cgen_expr_pre(g, &d->expr); + if (expr->kind != EXPR_VAL) cgen_expr_pre(g, expr); if (nidents > 1) { /* set expr__ first to make sure side effects don't happen twice */ cgen_write(g, "{"); @@ -1995,7 +1999,7 @@ static void cgen_decl(CGenerator *g, Declaration *d) { cgen_write(g, " expr_"); cgen_type_post(g, &d->type); cgen_write(g, "; "); - cgen_set(g, NULL, "expr_", &d->expr, NULL); + cgen_set(g, NULL, "expr_", expr, NULL); arr_foreach(d->idents, Identifier, i) { Expression e; @@ -2008,17 +2012,26 @@ static void cgen_decl(CGenerator *g, Declaration *d) { } cgen_write(g, "}"); } else { - if (ident_eq_str(d->idents[0], "_")) { - cgen_expr(g, &d->expr); + Identifier ident = d->idents[0]; + if (ident_eq_str(ident, "_")) { + cgen_expr(g, expr); cgen_write(g, ";"); } else { /* set it directly */ - Expression e = {0}; - e.kind = EXPR_IDENT; - e.type = d->type; - e.flags = EXPR_FOUND_TYPE; - e.ident = d->idents[0]; - cgen_set(g, &e, NULL, &d->expr, NULL); + if (expr->kind == EXPR_VAL) { + /* don't use a temp variable */ + cgen_ident(g, ident); + cgen_write(g, " = "); + cgen_val(g, &expr->val, &expr->type); + cgen_write(g, ";"); + } else { + Expression e = {0}; + e.kind = EXPR_IDENT; + e.type = d->type; + e.flags = EXPR_FOUND_TYPE; + e.ident = ident; + cgen_set(g, &e, NULL, expr, NULL); + } } } } @@ -230,7 +230,8 @@ static inline void copier_ident_translate(Copier *c, Identifier *i) { /* in must be untyped! */ static void copy_expr(Copier *c, Expression *out, Expression *in) { Allocator *a = c->allocr; - *out = *in; + *out = *in; /* NOTE : if in the future you are removing this, make sure in->type is still copied for EXPR_VAL, + which sometimes exists before typing, e.g. for null */ assert(!(in->flags & EXPR_FOUND_TYPE)); switch (in->kind) { case EXPR_LITERAL_FLOAT: @@ -8,8 +8,8 @@ /* @TODO: -null -fix eval pointer arithmetic - we're not multiplying by the size? +fix eval pointer arithmetic - are we not multiplying by the size? + - pointer arithmetic test fix including something twice - just use the non-namespacey version if it exists or pick one namespace to use everywhere otherwise - maybe store info about namespaces which are secretly the same as inline blocks/other namespaces in the Typer &&, || @@ -1265,6 +1265,16 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { e->kind = EXPR_LITERAL_BOOL; e->booll = false; break; + case KW_NULL: { + e->kind = EXPR_VAL; + e->type.kind = TYPE_PTR; + e->type.flags = TYPE_IS_RESOLVED; + Type *ptr = e->type.ptr = parser_malloc(p, sizeof *ptr); + ptr->kind = TYPE_BUILTIN; + ptr->builtin = BUILTIN_VOID; + ptr->flags = TYPE_IS_RESOLVED; + e->val.ptr = NULL; + } break; default: goto unrecognized; } break; @@ -1,7 +1,5 @@ #include "std/io.toc"; main ::= fn() { - x : &void = 18 as &&char; - puti(x as int); } diff --git a/tests/types.toc b/tests/types.toc index 7262637..5117906 100644 --- a/tests/types.toc +++ b/tests/types.toc @@ -25,7 +25,7 @@ main ::= fn() { slice_to_ll ::= fn(t::=, slice: []t) use ll: LinkedList(t) { head = slice[0]; if slice.len == 1 { - tail = 0 as &LinkedList(t); + tail = null; } else { tail = new(LinkedList(t)); *tail = slice_to_ll(slice[1:]); @@ -1651,10 +1651,14 @@ static Status use_ident(Typer *tr, Identifier i, Type *t, Location where) { static Status types_expr(Typer *tr, Expression *e) { if (e->flags & EXPR_FOUND_TYPE) return true; + e->flags |= EXPR_FOUND_TYPE; /* even if failed, pretend we found the type */ + if (e->kind == EXPR_VAL) { + /* can exist, e.g. for null */ + return true; + } Type *t = &e->type; t->flags = TYPE_IS_RESOLVED; t->kind = TYPE_UNKNOWN; /* default to unknown type (in the case of an error) */ - e->flags |= EXPR_FOUND_TYPE; /* even if failed, pretend we found the type */ switch (e->kind) { case EXPR_FN: { if (!type_of_fn(tr, e->fn, &e->type, 0)) { @@ -31,9 +31,15 @@ typedef double Floating; #if __STDC_VERSION__ >= 199901 || defined _MSC_VER #define LONGLONG_AVAILABLE 1 typedef long long longlong; +typedef unsigned long long ulonglong; +#define LONGLONG_FMT "%lld" +#define ULONGLONG_FMT "%llu" #else #define LONGLONG_AVAILABLE 0 typedef long longlong; +typedef unsigned long ulonglong; +#define LONGLONG_FMT "%ld" +#define ULONGLONG_FMT "%lu" #endif @@ -315,6 +321,7 @@ typedef enum { KW_TYPEOF, KW_SIZEOF, KW_ALIGNOF, + KW_NULL, KW_COUNT } Keyword; @@ -329,7 +336,7 @@ static const char *const keywords[KW_COUNT] = { "int", "i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64", "float", "f32", "f64", "void", "Type", "Namespace", "char", "bool", "true", "false", "nms", "use", - "typeof", "sizeof", "alignof" + "typeof", "sizeof", "alignof", "null" }; typedef enum { |