summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--copy.c3
-rw-r--r--eval.c83
-rw-r--r--main.c10
-rw-r--r--parse.c6
-rw-r--r--test.toc15
-rw-r--r--tokenizer.c2
-rw-r--r--types.c10
-rw-r--r--types.h22
8 files changed, 62 insertions, 89 deletions
diff --git a/copy.c b/copy.c
index 4a69967..0b03257 100644
--- a/copy.c
+++ b/copy.c
@@ -118,6 +118,7 @@ static void copy_type(Copier *c, Type *out, Type *in) {
out->slice = copy_type_(c, in->slice);
break;
case TYPE_STRUCT: {
+ /* FIXME */
out->struc = allocr_malloc(c->allocr, sizeof *out->struc);
*out->struc = *in->struc;
size_t nfields = arr_len(in->struc->fields);
@@ -366,6 +367,8 @@ static void copy_stmt(Copier *c, Statement *out, Statement *in) {
}
static void copy_block(Copier *c, Block *out, Block *in, U8 flags) {
+ assert(!(in->flags & BLOCK_FINDING_TYPES));
+
Identifiers out_idents = out->idents;
*out = *in;
if (flags & COPY_BLOCK_DONT_CREATE_IDENTS)
diff --git a/eval.c b/eval.c
index b9001fc..83e2648 100644
--- a/eval.c
+++ b/eval.c
@@ -1523,15 +1523,6 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
return false;
break;
}
- /* make sure function body is typed before calling it */
- if (!types_block(ev->typer, &fn->body)) {
- return false;
- }
- /* NOTE: we're not calling fn_enter because we're manually entering the function */
-
- Value *ret_val;
- Value *arg_tuple = NULL;
- Type *arg_type_tuple = NULL;
/* set parameter values */
Declaration *params = fn->params;
@@ -1549,42 +1540,12 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
Type *type = is_tuple ? &p->type.tuple[idx] : &p->type;
Value *ival = multiple_idents ? &pval->tuple[idx] : pval;
copy_val(NULL, ival, &arg_val, type);
- if (fn->flags & FN_EXPR_CACHE) {
- Value *arg_tuple_member = arr_add(&arg_tuple);
- *(Type *)arr_add(&arg_type_tuple) = *type;
- copy_val(ev->allocr, arg_tuple_member, &arg_val, type);
- }
++arg;
++idx;
}
++arr_hdr(p->val_stack)->len;
}
- if (fn->flags & FN_EXPR_CACHE) {
- Value args;
- args.tuple = arg_tuple;
- Type args_type = {0};
- args_type.flags = TYPE_IS_RESOLVED;
- args_type.tuple = arg_type_tuple;
- bool already_there;
- Instance *i = instance_table_adda(ev->allocr, fn->cache, args, &args_type, &already_there);
- arr_clear(&arg_tuple);
- arr_clear(&arg_type_tuple);
- if (already_there) {
- *v = *i->ret_val;
- return true;
- } else {
- ret_val = i->ret_val = evalr_calloc(ev, 1, sizeof *ret_val);
- if (type_is_builtin(&e->type, BUILTIN_TYPE)) {
- /* placeholder type, overwritten when done */
- ret_val->type = evalr_calloc(ev, 1, sizeof *ret_val);
- ret_val->type->kind = TYPE_UNKNOWN;
- ret_val->type->flags = TYPE_IS_RESOLVED;
- }
- }
-
- }
-
arr_foreach(fn->ret_decls, Declaration, d) {
int idx = 0;
Value ret_decl_val;
@@ -1605,6 +1566,11 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
++idx;
}
}
+
+ /* make sure function body is typed before calling it */
+ if (!types_block(ev->typer, &fn->body))
+ return false;
+
if (!eval_block(ev, &fn->body, v)) {
return false;
}
@@ -1642,13 +1608,6 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
decl_remove_val(p);
arr_foreach(fn->ret_decls, Declaration, d)
decl_remove_val(d);
- if (fn->flags & FN_EXPR_CACHE) {
- if (type_is_builtin(&e->type, BUILTIN_TYPE)) {
- *ret_val->type = *v->type;
- } else {
- *ret_val = *v;
- }
- }
} break;
case EXPR_SLICE: {
SliceExpr *s = &e->slice;
@@ -1792,21 +1751,33 @@ static void eval_exit_stmts(Statement *stmts) {
}
static bool eval_block(Evaluator *ev, Block *b, Value *v) {
+ Block *prev = ev->typer->block;
+ ev->typer->block = b;
+ bool success = true;
arr_foreach(b->stmts, Statement, stmt) {
- if (!eval_stmt(ev, stmt))
- return false;
+ if (!eval_stmt(ev, stmt)) {
+ success = false;
+ goto ret;
+ }
if (ev->returning) break;
}
if (!ev->returning && b->ret_expr) {
Value r;
- if (!eval_expr(ev, b->ret_expr, &r))
- return false;
- /* make a copy so that r's data isn't freed when we exit the block */
- copy_val(NULL, v, &r, &b->ret_expr->type);
- if (b->ret_expr->kind == EXPR_TUPLE)
- free(r.tuple);
+ if (!eval_expr(ev, b->ret_expr, &r)) {
+ success = false;
+ goto ret;
+ }
+ if (!type_is_builtin(&b->ret_expr->type, BUILTIN_TYPE)) {
+ /* make a copy so that r's data isn't freed when we exit the block */
+ copy_val(NULL, v, &r, &b->ret_expr->type);
+ if (b->ret_expr->kind == EXPR_TUPLE)
+ free(r.tuple);
+ } else {
+ *v = r;
+ }
}
eval_exit_stmts(b->stmts);
-
- return true;
+ ret:
+ ev->typer->block = prev;
+ return success;
}
diff --git a/main.c b/main.c
index 391475f..b5e4c6d 100644
--- a/main.c
+++ b/main.c
@@ -18,7 +18,11 @@
/*
TODO:
-allow circular dependencies in types
+fix circular dependencies in types
+struct parameters
+fix struct copying
+replace is_reference in type_resolve_ with system for checking if type is
+ circularly dependent in a bad way, with compiler_sizeof
foo, _ := bar();
nice syntax for #including something into a namespace
run stuff at compile time without assigning it to a constant
@@ -35,14 +39,14 @@ don't allow while {3; 5} or for 0..10 { 3; 5 } (once break is added)
do we need was_expr? (now that, presumably, we have struct arguments)
any odd number of "s for a string
make sure futurely/currently-declared types are only used by pointer/slice
-allow omission of trailing ; in foo ::= fn() {...} or foo ::= nms {...} ?
+allow omission of trailing ; in foo ::= fn() {...} or foo ::= nms {...} or foo ::= struct { ... }?
*/
#include "toc.c"
-#if defined TOC_DEBUG && defined __linux__
+#if defined TOC_DEBUG && defined __linux__ && defined __GNU_LIBRARY__
#include <signal.h>
#include <execinfo.h>
#include <unistd.h>
diff --git a/parse.c b/parse.c
index e258416..b03a213 100644
--- a/parse.c
+++ b/parse.c
@@ -866,11 +866,6 @@ static bool parse_fn_expr(Parser *p, FnExpr *f) {
/* only called when token is fn */
assert(token_is_kw(t->token, KW_FN));
++t->token;
- if (token_is_direct(t->token, DIRECT_CACHE)) {
- f->flags |= FN_EXPR_CACHE;
- f->cache = parser_calloc(p, 1, sizeof *f->cache);
- ++t->token;
- }
if (!token_is_kw(t->token, KW_LPAREN)) {
tokr_err(t, "Expected '(' after 'fn'.");
return false;
@@ -1775,7 +1770,6 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
case DIRECT_FOREIGN:
case DIRECT_EXPORT:
case DIRECT_INCLUDE:
- case DIRECT_CACHE:
tokr_err(t, "Unrecognized expression.");
return false;
case DIRECT_COUNT: assert(0); break;
diff --git a/test.toc b/test.toc
index 56718ab..9eddb80 100644
--- a/test.toc
+++ b/test.toc
@@ -1,14 +1,9 @@
-io ::= nms{
- #include "std/io.toc";
+b ::= struct {
+ next : &a;
};
-
-ll ::= fn() Type {
- struct {
- head : int;
- tail : &ll();
- }
+a::=struct {
+ next : &b;
};
-
main ::= fn() {
- l : ll();
+ l : ll;
};
diff --git a/tokenizer.c b/tokenizer.c
index 36d9aa5..5a7e272 100644
--- a/tokenizer.c
+++ b/tokenizer.c
@@ -19,7 +19,7 @@ static const char *const keywords[KW_COUNT] =
static inline const char *kw_to_str(Keyword k) { return keywords[k]; }
static const char *directives[DIRECT_COUNT] =
- {"C", "sizeof", "alignof", "export", "foreign", "builtin", "include", "cache"};
+ {"C", "sizeof", "alignof", "export", "foreign", "builtin", "include"};
/* Returns KW_COUNT if it's not a keyword */
/* OPTIM: don't use strncmp so much */
diff --git a/types.c b/types.c
index 6765314..abe6795 100644
--- a/types.c
+++ b/types.c
@@ -2213,6 +2213,14 @@ static bool types_expr(Typer *tr, Expression *e) {
static bool types_block(Typer *tr, Block *b) {
if (b->flags & BLOCK_FOUND_TYPES)
return true;
+
+ if (b->flags & BLOCK_FINDING_TYPES) {
+ err_print(b->where, "A circular dependency was found when finding types in this block.\n"
+ "You are using recursion in a way that is not allowed by this language. Sorry!");
+ return false;
+ }
+ b->flags |= BLOCK_FINDING_TYPES;
+
typer_block_enter(tr, b);
bool success = true;
arr_foreach(b->stmts, Statement, s) {
@@ -2248,6 +2256,8 @@ static bool types_block(Typer *tr, Block *b) {
ret:
typer_block_exit(tr);
b->flags |= BLOCK_FOUND_TYPES;
+ b->flags &= (BlockFlags)~(BlockFlags)BLOCK_FINDING_TYPES;
+
return success;
}
diff --git a/types.h b/types.h
index c4851c4..9034f38 100644
--- a/types.h
+++ b/types.h
@@ -230,7 +230,6 @@ typedef enum {
DIRECT_FOREIGN,
DIRECT_BUILTIN,
DIRECT_INCLUDE,
- DIRECT_CACHE,
DIRECT_COUNT
} Directive;
@@ -472,10 +471,12 @@ typedef struct StructDef {
enum {
BLOCK_IS_FN = 0x01,
BLOCK_IS_NMS = 0x02,
- BLOCK_FOUND_TYPES = 0x04
+ BLOCK_FINDING_TYPES = 0x04,
+ BLOCK_FOUND_TYPES = 0x08
};
+typedef U8 BlockFlags;
typedef struct Block {
- U8 flags;
+ BlockFlags flags;
Location where;
Identifiers idents;
struct Statement *stmts;
@@ -596,8 +597,7 @@ typedef struct ForExpr {
enum {
FN_EXPR_FOREIGN = 0x01,
- FN_EXPR_EXPORT = 0x02, /* set by sdecls_cgen.c */
- FN_EXPR_CACHE = 0x04
+ FN_EXPR_EXPORT = 0x02 /* set by sdecls_cgen.c */
};
typedef struct FnExpr {
@@ -617,7 +617,6 @@ typedef struct FnExpr {
the first element is a u64 value whose ith bit (1<<i) is 1
if the ith semi-constant parameter is constant.
*/
- HashTable *cache; /* only set for FN_EXPR_CACHE */
struct {
/* if name = NULL, this is an anonymous function, and id will be the ID of the fn. */
Identifier name;
@@ -628,14 +627,11 @@ typedef struct FnExpr {
typedef struct Instance {
Value val; /* key into hash table */
- union {
+ struct {
+ FnExpr *fn; /* the typed function */
struct {
- FnExpr *fn; /* the typed function */
- struct {
- U64 id;
- } c;
- };
- Value *ret_val; /* return value (for #cached functions). pointer must stay fixed, so this is a Value * */
+ U64 id;
+ } c;
};
} Instance;