summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rw-r--r--cgen.c41
-rw-r--r--copy.c3
-rw-r--r--main.c4
-rw-r--r--parse.c10
-rw-r--r--test.toc2
-rw-r--r--tests/types.toc2
-rw-r--r--types.c6
-rw-r--r--types.h9
9 files changed, 56 insertions, 22 deletions
diff --git a/README.md b/README.md
index 5286dfd..1dfee47 100644
--- a/README.md
+++ b/README.md
@@ -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>
---
diff --git a/cgen.c b/cgen.c
index 188a16e..128ad16 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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);
+ }
}
}
}
diff --git a/copy.c b/copy.c
index e34036c..a8b63a2 100644
--- a/copy.c
+++ b/copy.c
@@ -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:
diff --git a/main.c b/main.c
index 0b2fd5c..4ef211e 100644
--- a/main.c
+++ b/main.c
@@ -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
&&, ||
diff --git a/parse.c b/parse.c
index b06e0e1..5cecdfb 100644
--- a/parse.c
+++ b/parse.c
@@ -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;
diff --git a/test.toc b/test.toc
index 891b513..d0f74fb 100644
--- a/test.toc
+++ b/test.toc
@@ -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:]);
diff --git a/types.c b/types.c
index a3fb651..7dcebff 100644
--- a/types.c
+++ b/types.c
@@ -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)) {
diff --git a/types.h b/types.h
index 8ceaa32..3e40d9c 100644
--- a/types.h
+++ b/types.h
@@ -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 {