diff options
-rw-r--r-- | eval.c | 31 | ||||
-rw-r--r-- | parse.c | 6 | ||||
-rw-r--r-- | test.toc | 18 | ||||
-rw-r--r-- | tokenizer.c | 2 | ||||
-rw-r--r-- | types.h | 19 |
5 files changed, 57 insertions, 19 deletions
@@ -1529,6 +1529,10 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { } /* 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; long arg = 0; @@ -1545,11 +1549,35 @@ 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); + } + + } arr_foreach(fn->ret_decls, Declaration, d) { int idx = 0; @@ -1608,7 +1636,8 @@ 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) + *ret_val = *v; } break; case EXPR_SLICE: { SliceExpr *s = &e->slice; @@ -866,6 +866,11 @@ 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; @@ -1770,6 +1775,7 @@ 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; @@ -2,19 +2,13 @@ io ::= nms{ #include "std/io.toc"; }; -foo ::= fn(a: [3]int) { - a[0] = 128; +ll ::= fn() Type { + struct { + head : int; + tail : &ll(); + } }; -f ::= fn() int { - a : [3]int; - foo(a); - a[0] -}; main ::= fn() { - a ::= f(); - b := f(); - io.puti(a); - io.puti(b); - + l : ll(); }; diff --git a/tokenizer.c b/tokenizer.c index 5a7e272..36d9aa5 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"}; + {"C", "sizeof", "alignof", "export", "foreign", "builtin", "include", "cache"}; /* Returns KW_COUNT if it's not a keyword */ /* OPTIM: don't use strncmp so much */ @@ -131,6 +131,7 @@ typedef struct BlockArr { ArrBlock *blocks; } BlockArr; +/* initialize to 0 */ typedef struct HashTable { void *data; bool *occupied; @@ -229,6 +230,7 @@ typedef enum { DIRECT_FOREIGN, DIRECT_BUILTIN, DIRECT_INCLUDE, + DIRECT_CACHE, DIRECT_COUNT } Directive; @@ -594,7 +596,8 @@ typedef struct ForExpr { enum { FN_EXPR_FOREIGN = 0x01, - FN_EXPR_EXPORT = 0x02 /* set by sdecls_cgen.c */ + FN_EXPR_EXPORT = 0x02, /* set by sdecls_cgen.c */ + FN_EXPR_CACHE = 0x04 }; typedef struct FnExpr { @@ -614,6 +617,7 @@ 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; @@ -624,10 +628,15 @@ typedef struct FnExpr { typedef struct Instance { Value val; /* key into hash table */ - FnExpr *fn; /* the typed function */ - struct { - U64 id; - } c; + union { + 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 * */ + }; } Instance; typedef struct CastExpr { |