From 7254210307fb5abce5630bfad8606e6ebc102ae9 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sun, 28 Apr 2019 13:10:15 +1000 Subject: [PATCH] oceani: introduce type->prepare() During parsing and analysis we don't want to "init" a variable as that can allocate memory - when we add arrays, we might not know yet how much memory. So introduce 'prepare' to prepare a value - such that calling free on it will work - without allocating. 'init' is then called when a variable is declared - unless something is assigned to it instead. Signed-off-by: NeilBrown --- csrc/oceani.mdc | 49 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index 7e74b84..e29f891 100644 --- a/csrc/oceani.mdc +++ b/csrc/oceani.mdc @@ -447,6 +447,7 @@ which are often passed around by value. struct text name; struct type *next; struct value (*init)(struct type *type); + struct value (*prepare)(struct type *type); struct value (*parse)(struct type *type, char *str); void (*print)(struct value val); int (*cmp_order)(struct value v1, struct value v2); @@ -504,6 +505,16 @@ which are often passed around by value. v.type->free(v); } + static struct value val_prepare(struct type *type) + { + struct value rv; + + if (type) + return type->prepare(type); + rv.type = type; + return rv; + } + static struct value val_init(struct type *type) { struct value rv; @@ -623,6 +634,31 @@ to parse each type from a string. ###### value functions + static struct value _val_prepare(struct type *type) + { + struct value rv; + + rv.type = type; + switch(type->vtype) { + case Vnone: + break; + case Vnum: + memset(&rv.num, 0, sizeof(rv.num)); + break; + case Vstr: + rv.str.txt = NULL; + rv.str.len = 0; + break; + case Vbool: + rv.bool = 0; + break; + case Vlabel: + rv.label = NULL; + break; + } + return rv; + } + static struct value _val_init(struct type *type) { struct value rv; @@ -764,6 +800,7 @@ to parse each type from a string. static struct type base_prototype = { .init = _val_init, + .prepare = _val_prepare, .parse = _parse_value, .print = _print_value, .cmp_order = _value_cmp, @@ -1099,7 +1136,7 @@ all pending-scope variables become conditionally scoped. v->scope = InScope; v->in_scope = c->in_scope; c->in_scope = v; - v->val = val_init(NULL); + v->val = val_prepare(NULL); return v; } @@ -1627,7 +1664,7 @@ link to find the primary instance. if (v) { v->where_decl = $0; v->where_set = $0; - v->val = val_init($<3); + v->val = val_prepare($<3); } else { v = var_ref(config2context(config), $1.txt); $0->var = v; @@ -1644,7 +1681,7 @@ link to find the primary instance. if (v) { v->where_decl = $0; v->where_set = $0; - v->val = val_init($<3); + v->val = val_prepare($<3); v->constant = 1; } else { v = var_ref(config2context(config), $1.txt); @@ -1663,7 +1700,7 @@ link to find the primary instance. /* This might be a label - allocate a var just in case */ v = var_decl(config2context(config), $1.txt); if (v) { - v->val = val_init(Tlabel); + v->val = val_prepare(Tlabel); v->val.label = &v->val; v->where_set = $0; } @@ -1721,7 +1758,7 @@ link to find the primary instance. v = v->merged; if (v->val.type == NULL) { if (type && *ok != 0) { - v->val = val_init(type); + v->val = val_prepare(type); v->where_set = prog; *ok = 2; } @@ -3172,7 +3209,7 @@ analysis is a bit more interesting at this level. struct var *v = cast(var, b->left); if (!v->var->val.type) { v->var->where_set = b; - v->var->val = val_init(Tstr); + v->var->val = val_prepare(Tstr); } } b = cast(binode, prog); -- 2.43.0