summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-02-07 23:47:45 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-02-07 23:47:45 -0500
commitc08e40d37be72e84e7fe0e48e6e97f95b9c1bf5e (patch)
tree06fdeb2cd1b8a88709e6075e6f26aa6b6600c64e
parentd64fa6da5b83e770bc4877655b70982d74c37a42 (diff)
(in progress) trying to get eval recursion to work
-rw-r--r--eval.c135
-rw-r--r--main.c5
-rw-r--r--parse.c6
-rw-r--r--test.toc7
-rw-r--r--types.h17
5 files changed, 103 insertions, 67 deletions
diff --git a/eval.c b/eval.c
index a6ff7aa..8a0c944 100644
--- a/eval.c
+++ b/eval.c
@@ -729,25 +729,49 @@ static bool eval_expr_ptr_at_index(Evaluator *ev, Expression *e, void **ptr, Typ
return eval_val_ptr_at_index(e->where, &arr, i, ltype, ptr, type);
}
-static bool eval_address_of_ident(Identifier i, Type *type, Location where, void **ptr) {
- if (!(i->flags & IDENT_HAS_VAL)) {
- if (i->decl_kind == IDECL_DECL) {
- Declaration *decl = i->decl;
- if (!(decl->flags & DECL_IS_CONST) || !(decl->flags & DECL_FOUND_VAL)) goto runtime_var;
- i->val = decl->val;
- i->flags |= IDENT_HAS_VAL;
+static Value *ident_val(Identifier i) {
+ switch (i->decl_kind) {
+ case IDECL_FOR: {
+ ForExpr *fo = i->for_;
+ Value *v = *(Value **)arr_last(fo->val_stack);
+ if (i == fo->index) {
+ if (fo->value)
+ v = &v->tuple[0];
} else {
- runtime_var:
- err_print(where, "Cannot take address of run time variable at compile time.");
- return false;
+ if (fo->index)
+ v = &v->tuple[1];
}
+ return v;
+ }
+ case IDECL_DECL: {
+ Declaration *decl = i->decl;
+ int idx = decl_ident_index(decl, i);
+ if (decl->flags & DECL_IS_CONST)
+ return decl_val_at_index(decl, idx);
+ else if (decl->val_stack) {
+ Value *valp = *(Value **)arr_last(decl->val_stack);
+ if (decl->type.kind == TYPE_TUPLE)
+ return &valp->tuple[idx];
+ else
+ return valp;
+ } else
+ return NULL; /* uh oh... this is a runtime-only variable */
+ }
+ case IDECL_NONE: break;
+ }
+ assert(0);
+ return NULL;
+
+}
+
+static inline bool eval_address_of_ident(Identifier i, Location where, Type *type, void **ptr) {
+ Value *val = ident_val(i);
+ if (!val) {
+ char *s = ident_to_str(i);
+ err_print(where, "Cannot access value of variable %s at compile time.", s);
+ return false;
}
- if (type->kind == TYPE_ARR)
- *ptr = i->val.arr; /* point directly to data */
- else if (type->kind == TYPE_STRUCT)
- *ptr = i->val.struc;
- else
- *ptr = &i->val;
+ *ptr = val_get_ptr(val, type);
return true;
}
@@ -778,9 +802,8 @@ static bool eval_ptr_to_struct_field(Evaluator *ev, Expression *dot_expr, void *
void *ptr;
assert(type_is_builtin(struct_type, BUILTIN_NMS));
Identifier translated = dot_expr->binary.dot.translated_ident;
- if (!eval_address_of_ident(translated, &dot_expr->type, dot_expr->where, &ptr)) {
- return false;
- }
+ if (!eval_address_of_ident(translated, dot_expr->where, &dot_expr->type, &ptr))
+ return false;
*p = ptr;
}
return true;
@@ -789,7 +812,7 @@ static bool eval_ptr_to_struct_field(Evaluator *ev, Expression *dot_expr, void *
static bool eval_address_of(Evaluator *ev, Expression *e, void **ptr) {
switch (e->kind) {
case EXPR_IDENT: {
- if (!eval_address_of_ident(e->ident, &e->type, e->where, ptr))
+ if (!eval_address_of_ident(e->ident, e->where, &e->type, ptr))
return false;
} break;
case EXPR_UNARY_OP:
@@ -834,11 +857,12 @@ static bool eval_set(Evaluator *ev, Expression *set, Value *to) {
switch (set->kind) {
case EXPR_IDENT: {
Identifier i = set->ident;
- if (!(i->flags & IDENT_HAS_VAL)) {
+ Value *ival = ident_val(i);
+ if (!ival) {
err_print(set->where, "Cannot set value of run time variable at compile time.");
return false;
}
- i->val = *to;
+ *ival = *to;
} break;
case EXPR_UNARY_OP:
switch (set->unary.op) {
@@ -1105,17 +1129,9 @@ static bool eval_ident(Evaluator *ev, Identifier ident, Value *v, Location where
assert(d->type.flags & TYPE_IS_RESOLVED);
}
}
- if (ident->flags & IDENT_HAS_VAL) {
- *v = ident->val;
- } else if (is_decl && (d->flags & DECL_IS_CONST)) {
- if (!(d->flags & DECL_FOUND_VAL)) {
- assert(d->flags & DECL_HAS_EXPR);
- if (!eval_expr(ev, &d->expr, &d->val)) return false;
- d->flags |= DECL_FOUND_VAL;
- }
- int index = ident_index_in_decl(ident, d);
- assert(index != -1);
- *v = *decl_val_at_index(d, index);
+ Value *ival = ident_val(ident);
+ if (ival) {
+ *v = *ival;
} else {
char *s = ident_to_str(ident);
@@ -1126,6 +1142,15 @@ static bool eval_ident(Evaluator *ev, Identifier ident, Value *v, Location where
return true;
}
+static Value *decl_add_val(Declaration *d) {
+ Value **valpp = arr_add(&d->val_stack);
+ Value *valp = *valpp = err_malloc(sizeof *valp);
+ if (d->type.kind == TYPE_TUPLE)
+ valp->tuple = err_malloc(arr_len(d->idents) * sizeof *valp->tuple);
+ return valp;
+}
+
+
static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
#define eval_unary_op_one(low, up, op) \
@@ -1308,17 +1333,19 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
ForExpr *fo = e->for_;
Value *index_val;
Value *value_val;
+ Value **for_valpp = arr_add(&fo->val_stack);
+ Value *for_valp = *for_valpp = err_malloc(sizeof *for_valp);
+ if (fo->index && fo->value) {
+ /* make a tuple */
+ for_valp->tuple = err_malloc(2 * sizeof *for_valp->tuple);
+ }
if (fo->index) {
- Identifier i = fo->index;
- i->flags |= IDENT_HAS_VAL;
- index_val = &i->val;
+ index_val = fo->value ? &for_valp->tuple[0] : for_valp;
} else {
index_val = NULL;
}
if (fo->value) {
- Identifier i = fo->value;
- i->flags |= IDENT_HAS_VAL;
- value_val = &i->val;
+ value_val = fo->value ? &for_valp->tuple[1] : for_valp;
} else {
value_val = NULL;
}
@@ -1490,32 +1517,35 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
long arg = 0;
arr_foreach(params, Declaration, p) {
int idx = 0;
+ Value *pval = decl_add_val(p);
+ bool is_tuple = p->type.kind == TYPE_TUPLE;
arr_foreach(p->idents, Identifier, i) {
Value arg_val;
if (!eval_expr(ev, &e->call.arg_exprs[arg], &arg_val))
return false;
- Type *type = p->type.kind == TYPE_TUPLE ? &p->type.tuple[idx++] : &p->type;
- copy_val(NULL, &(*i)->val, &arg_val, type);
- (*i)->flags |= IDENT_HAS_VAL;
+ Type *type = is_tuple ? &p->type.tuple[idx] : &p->type;
+ Value *ival = is_tuple ? &pval->tuple[idx] : pval;
+ copy_val(NULL, ival, &arg_val, type);
++arg;
+ ++idx;
}
}
arr_foreach(fn->ret_decls, Declaration, d) {
int idx = 0;
- Value val;
+ Value ret_decl_val;
if (d->flags & DECL_HAS_EXPR)
- if (!eval_expr(ev, &d->expr, &val))
+ if (!eval_expr(ev, &d->expr, &ret_decl_val))
return false;
-
+ Value *dval = decl_add_val(d);
arr_foreach(d->idents, Identifier, i) {
+ Value *ival = d->type.kind == TYPE_TUPLE ? &dval->tuple[idx] : dval;
Type *type = d->type.kind == TYPE_TUPLE ? &d->type.tuple[idx] : &d->type;
if (d->flags & DECL_HAS_EXPR) {
- (*i)->val = d->type.kind == TYPE_TUPLE ? val.tuple[idx] : val;
+ *ival = d->type.kind == TYPE_TUPLE ? ret_decl_val.tuple[idx] : ret_decl_val;
} else {
- (*i)->val = val_zero(type);
+ *ival = val_zero(type);
}
- (*i)->flags |= IDENT_HAS_VAL;
++idx;
}
}
@@ -1634,18 +1664,19 @@ static bool eval_decl(Evaluator *ev, Declaration *d) {
if (!is_const) {
int index = 0;
+ Value *dval = decl_add_val(d);
+ bool is_tuple = d->type.kind == TYPE_TUPLE;
arr_foreach(d->idents, Identifier, ip) {
- Identifier i = *ip;
+ Value *ival = is_tuple ? &dval->tuple[index] : dval;
Type *type = decl_type_at_index(d, index);
if (!is_const) {
if (has_expr) {
- copy_val(NULL, &i->val, &val, type);
+ copy_val(NULL, ival, is_tuple ? &val.tuple[index] : &val, type);
} else {
- i->val = val_zero(type);
+ *ival = val_zero(type);
}
}
++index;
- i->flags |= IDENT_HAS_VAL;
}
}
return true;
diff --git a/main.c b/main.c
index 720dbdf..c578f87 100644
--- a/main.c
+++ b/main.c
@@ -18,6 +18,9 @@
/*
TODO:
+fix eval recursion
+make sure that you can't access runtime things from eval
+big leak check with tuples (see "TODO: tuples allocated here will never be freed!")
struct parameters - to allow circular dependencies in types
foo, _ := bar();
nice syntax for #including something into a namespace
@@ -32,7 +35,7 @@ switch to / add as an alternative: libffi
---
X ::= newtype(int); or something
don't allow while {3; 5} (once break is added)
-better printing of types (take was_expr into account)
+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 {...} ?
diff --git a/parse.c b/parse.c
index 7d13602..b03a213 100644
--- a/parse.c
+++ b/parse.c
@@ -1173,6 +1173,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
case KW_FOR: {
e->kind = EXPR_FOR;
ForExpr *fo = e->for_ = parser_malloc(p, sizeof *fo);
+ fo->val_stack = NULL;
fo->flags = 0;
fo->value = NULL;
fo->index = NULL;
@@ -1849,7 +1850,8 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 fla
d->where.start = t->token;
d->idents = NULL;
d->flags = 0;
-
+ d->val_stack = NULL;
+
if ((flags & PARSE_DECL_ALLOW_EXPORT) && token_is_direct(t->token, DIRECT_EXPORT)) {
d->flags |= DECL_EXPORT;
++t->token;
@@ -2502,7 +2504,7 @@ static bool ident_is_definitely_const(Identifier i) {
Declaration *decl = i->decl;
if (i->decl_kind != IDECL_DECL || !(decl->flags & DECL_IS_CONST))
return false;
- if (i->flags & DECL_FOREIGN) {
+ if (i->decl->flags & DECL_FOREIGN) {
if (decl->foreign.lib && COMPILE_TIME_FOREIGN_FN_SUPPORT)
return true;
else
diff --git a/test.toc b/test.toc
index 96b180a..b676fbe 100644
--- a/test.toc
+++ b/test.toc
@@ -1,8 +1,7 @@
-io ::= nms {
- #include "std/io.toc";
+factorial ::= fn(x: int) int {
+x*2
};
main ::= fn() {
- io.puts("Hello");
- int;
+ a ::= factorial(10);
}; \ No newline at end of file
diff --git a/types.h b/types.h
index f0f6025..bf74d9c 100644
--- a/types.h
+++ b/types.h
@@ -166,11 +166,6 @@ typedef union Value {
struct Namespace *nms;
} Value;
-enum {
- IDENT_HAS_VAL = 0x01
-
-};
-
typedef enum {
IDECL_NONE,
IDECL_DECL,
@@ -188,9 +183,7 @@ typedef struct IdentSlot {
struct ForExpr *for_;
};
struct Identifiers *idents;
- Value val;
SOURCE_LOCATION
- U16 flags;
} IdentSlot;
typedef struct StrHashTableSlot {
@@ -607,6 +600,7 @@ typedef struct ForExpr {
} range;
struct Expression *of;
};
+ Value **val_stack; /* see Declaration for comments */
} ForExpr;
@@ -810,7 +804,14 @@ typedef struct Declaration {
};
} foreign;
};
- Value val; /* only for constant decls. */
+ union {
+ Value val; /* only for constant decls. */
+
+ /* for eval, for non-constant decls.: */
+ /* the pointers to values need to be fixed, which is why this isn't just Value *. */
+ /* OPTIM: some freeable block array of values somewhere which we can just use a pointer to? */
+ Value **val_stack;
+ };
} Declaration;
typedef enum {