]> ocean-lang.org Git - ocean/commitdiff
oceani: introduce type->prepare()
authorNeilBrown <neil@brown.name>
Sun, 28 Apr 2019 03:10:15 +0000 (13:10 +1000)
committerNeilBrown <neil@brown.name>
Wed, 1 May 2019 08:09:53 +0000 (18:09 +1000)
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 <neil@brown.name>
csrc/oceani.mdc

index 7e74b8480c0073cd28c295f7abd50b36677d53c4..e29f8915a856e9620c5c26e1dd4be63f6a0ec664 100644 (file)
@@ -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);