]> code.bitgloo.com Git - clyne/interpreter.git/commitdiff
indent fixes, nested conditionals
authorClyne Sullivan <tullivan99@gmail.com>
Mon, 12 Feb 2018 16:23:17 +0000 (11:23 -0500)
committerClyne Sullivan <tullivan99@gmail.com>
Mon, 12 Feb 2018 16:23:17 +0000 (11:23 -0500)
.gitignore
Makefile
builtins.c
builtins.h
parser.c
parser.h
script
shell.c
shelpers.c
variable.c
variable.h

index 6a2f0f7a37504ae7f2fca13030b0f745dd1fba69..fc79a9e3ce522b0de2c4ae21a5737fff9db30d59 100644 (file)
@@ -1,2 +1,3 @@
 shell
 *.o
+libinterp.a
index f81b5891781681be3068755425cff1b3316c65ce..1d66f11ac8ad010b96e30e2c39832f425aed2bc7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,9 @@
-CC = gcc -m32
+#CC = gcc -m32
+#AR = ar
+CC = arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsigned-char
+AR = arm-none-eabi-ar
 
-CFLAGS = -Wall -Wextra -Wno-strict-aliasing -I. -ggdb -fno-builtin
+CFLAGS = -Wall -Wextra -I. -fno-builtin -ggdb
 
 all:
        $(CC) $(CFLAGS) -c shelpers.c
@@ -9,4 +12,6 @@ all:
        $(CC) $(CFLAGS) -c stack.c
        $(CC) $(CFLAGS) -c ops.c
        $(CC) $(CFLAGS) -c variable.c
-       $(CC) $(CFLAGS) shell.c *.o -o shell
+       $(AR) r libinterp.a *.o
+       @rm -f *.o
+       #$(CC) $(CFLAGS) shell.c -o shell -L. -l interp
index cda7a9309e2cf3c1d54f0c749cdc1b411b4f21f5..c77c8b9fba31c66b628a3e65eb513672a2fa2061 100644 (file)
@@ -1,7 +1,11 @@
 #include "builtins.h"
 #include "stack.h"
+#include "shelpers.h"
+
+#include <stdlib.h>
 
 extern char *str_func;
+extern char *str_undef;
 
 int ifunc_set(interpreter *it);
 int ifunc_label(interpreter *it);
@@ -11,6 +15,14 @@ int ifunc_do(interpreter *it);
 int ifunc_while(interpreter *it);
 int ifunc_ret(interpreter *it);
 
+const func_t indent_up[IUP_COUNT] = {
+       ifunc_if, ifunc_do, ifunc_label
+};
+
+const func_t indent_down[IDOWN_COUNT] = {
+       ifunc_end, ifunc_while
+};
+
 void iload_core(interpreter *interp)
 {
        inew_cfunc(interp, "set", ifunc_set);
@@ -32,7 +44,9 @@ int ifunc_set(interpreter *it)
 
        n->valtype = v->valtype;
        n->value = v->value;
-       n->svalue = v->svalue;
+       if (n->svalue != 0 && n->svalue != str_func && n->svalue != str_undef)
+               free(n->svalue);
+       n->svalue = strclone(v->svalue);
        return 0;
 }
 
@@ -46,25 +60,26 @@ int ifunc_label(interpreter *it)
        n->valtype = FUNC;
        n->value = it->lnidx;
        n->svalue = str_func;
-       it->indent++;
+       iskip(it);
        return 0;
 }
 
 int ifunc_if(interpreter *it)
 {
        int v = igetarg_integer(it, 0);
-       if (v == 0) {
-               it->indent++;
-       } else {
-               void *tmp = ipop(it);
-               ipush(it, (void *)-1);
-               ipush(it, tmp);
-       }
+       if (v == 0)
+               iskip(it);
+       void *tmp = ipop(it);
+       ipush(it, (void *)-1);
+       ipush(it, tmp);
        return 0;
 }
 
 int ifunc_end(interpreter *it)
 {
+       if (it->stidx == 0)
+               return 0;
+
        uint32_t lnidx = (uint32_t)ipop(it) + 1;
        if (lnidx != 0)
                it->lnidx = lnidx;
@@ -83,8 +98,8 @@ int ifunc_while(interpreter *it)
        ipop(it);
        int nidx = (int)ipop(it);
        if (c != 0) {
-               ipush(it, (void *)nidx);
-               it->lnidx = nidx;
+               //ipush(it, (void *)nidx);
+               it->lnidx = nidx - 1;
        }
        ipush(it, 0);
        return 0;
index 873977873e3dba55c8af1612428d5aa2aa12f683..91c6e8c14128ebde53d38ef6994a5854c84ba549 100644 (file)
@@ -3,6 +3,12 @@
 
 #include "parser.h"
 
+#define IUP_COUNT 3
+#define IDOWN_COUNT 2
+
 void iload_core(interpreter *it);
 
+const func_t indent_up[IUP_COUNT];
+const func_t indent_down[IDOWN_COUNT];
+
 #endif // BUILTINS_H_
index ac739a0025766a78ca3205cd4e258858957aee96..b100123ced17f85169dc45ed25d711aa3286e7cd 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -7,6 +7,7 @@
 
 #include <ctype.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 
 #define MAX_VARS  48
@@ -24,9 +25,10 @@ void iinit(interpreter *interp)
        interp->vnames = (char **)malloc(MAX_VARS * sizeof(char *));
        interp->stack = (stack_t *)malloc(MAX_STACK * sizeof(stack_t));
        interp->stidx = 0;
-       interp->lines = (char **)calloc(MAX_LINES, sizeof(char *));
+       interp->lines = (variable ***)malloc(MAX_LINES * sizeof(variable **));
        interp->lnidx = 0;
        interp->indent = 0;
+       interp->sindent = 0;
 
        for (unsigned int i = 0; i < MAX_VARS; i++) {
                interp->vars[i].used = 0;
@@ -38,6 +40,30 @@ void iinit(interpreter *interp)
        iload_core(interp);
 }
 
+void iend(interpreter *it)
+{
+       for (unsigned int i = 0; i < MAX_VARS; i++) {
+               if (it->vars[i].used == 1) {
+                       char *s = it->vars[i].svalue;
+                       if (s != 0 && s != str_undef && s != str_func)
+                               free(s);
+                       free(it->vnames[i]);
+               }
+       }
+       for (unsigned int i = 0; i < MAX_LINES; i++)
+               free(it->lines[i]);
+       free(it->vars);
+       free(it->vnames);
+       free(it->stack);
+       free(it->lines);
+}
+
+void iskip(interpreter *it)
+{
+       if (!(it->sindent & SKIP))
+               it->sindent = it->indent | SKIP;
+}
+
 variable *interpreter_get_variable(interpreter *interp, const char *name)
 {
        for (uint32_t i = 0; i < MAX_VARS; i++) {
@@ -66,7 +92,7 @@ char *interpreter_get_name(interpreter *interp, variable *v)
        return str_undef;
 }
 
-void inew_string(interpreter *interp, const char *name, char *value)
+variable *inew_string(interpreter *interp, const char *name, char *value)
 {
        variable *v = interpreter_get_variable(interp, name);
        if (v != 0) {
@@ -74,9 +100,10 @@ void inew_string(interpreter *interp, const char *name, char *value)
                INT(v) = 0;
                v->svalue = strclone(value);
        }
+       return v;
 }
 
-void inew_integer(interpreter *interp, const char *name, int32_t value)
+variable *inew_integer(interpreter *interp, const char *name, int32_t value)
 {
        variable *v = interpreter_get_variable(interp, name);
        if (v != 0) {
@@ -84,9 +111,10 @@ void inew_integer(interpreter *interp, const char *name, int32_t value)
                INT(v) = value;
                isetstr(v);
        }
+       return v;
 }
 
-void inew_float(interpreter *interp, const char *name, float value)
+variable *inew_float(interpreter *interp, const char *name, float value)
 {
        variable *v = interpreter_get_variable(interp, name);
        if (v != 0) {
@@ -94,6 +122,7 @@ void inew_float(interpreter *interp, const char *name, float value)
                FLOAT(v) = value;
                fsetstr(v);
        }
+       return v;
 }
 
 void inew_cfunc(interpreter *interp, const char *name, func_t func)
@@ -116,12 +145,8 @@ variable *make_var(interpreter *interp, const char *line, uint32_t *next)
                                if (!eot(line[end + 1]))
                                        return 0;
                                // TODO string breakdown
-                               variable *v = (variable *)malloc(sizeof(variable));
-                               v->used = 0;
-                               v->valtype = STRING;
-                               v->svalue = strnclone(line + 1, end - 1);
                                *next = end + 1;
-                               return v;
+                               return vmake(0, STRING, strnclone(line + 1, end - 1));
                        }
                        end++;
                }
@@ -131,7 +156,8 @@ variable *make_var(interpreter *interp, const char *line, uint32_t *next)
                if (eot(line[end]))
                        return 0;
                *next = end + 1;
-               return idoexpr(interp, line + 1);
+               return vmake(0, EXPR, strnclone(line + 1, end));
+               //return idoexpr(interp, line + 1);
        } else if (isalpha(line[0])) { // variable/func
                uint32_t end = 1;
                for (; isalnum(line[end]); end++);
@@ -141,7 +167,9 @@ variable *make_var(interpreter *interp, const char *line, uint32_t *next)
                strncpy(name, line, end);
                name[end] = '\0';
                *next = end;
-               return interpreter_get_variable(interp, name);
+               variable *v = interpreter_get_variable(interp, name);
+               free(name);
+               return v;
        } else if (isdigit(line[0])) { // number
                uint32_t end = 1;
                uint8_t dec = 0;
@@ -157,17 +185,11 @@ variable *make_var(interpreter *interp, const char *line, uint32_t *next)
                                }
                        }
                }
-               variable *v = (variable *)malloc(sizeof(variable));
-               v->used = 0;
+               variable *v;
                if (dec) {
-                       v->valtype = FLOAT;
-                       FLOAT(v) = strtof(line, 0);
-                       fsetstr(v);
-               } else {
-                       v->valtype = INTEGER;
-                       INT(v) = atoi(line);
-                       isetstr(v);
-               }
+                       v = vmakef(strtof(line, 0));
+               } else
+                       v = vmake(0, INTEGER, (void *)atoi(line));
                *next = end;
                return v;
        }
@@ -176,39 +198,34 @@ variable *make_var(interpreter *interp, const char *line, uint32_t *next)
 
 int idoline(interpreter *interp, const char *line)
 {
-       variable *ops[8];
-       uint32_t ooffset, offset, next;
+       uint32_t ooffset = 0, offset = 0, next;
+       int fret = 0;
 
        if (line[0] == '\0')
                return 0;
-
-       interp->lines[interp->lnidx] = strclone(line);
-loop:
-       ooffset = 0;
-       offset = 0;
        skipblank(line, eol, &offset);
+       if (line[offset] == '#')
+               return 0;
 
-       if (line[offset] == '#') {
-               goto norun;
-       } else if (interp->indent > 0) {
-               if (!strcmp(line + offset, "end"))
-                       interp->indent--;
-               goto norun;
-       }
+       interp->lines[interp->lnidx] = (variable **)calloc(8, sizeof(variable *));
+       variable **ops = interp->lines[interp->lnidx];
 
        // step 1 - convert to tokens
        while (!eol(line[offset])) {
                if (offset > 0 && line[offset] == '>') {
                        offset++;
                        skipblank(line, eol, &offset);
-                       interp->ret = make_var(interp, line + offset, &next);
+                       variable *r = make_var(interp, line + offset, &next);
+                       ops[ooffset] = (void *)-1;
+                       ops[ooffset + 1] = r;
                        offset += next;
                        skipblank(line, eol, &offset);
                        continue;
                }
                ops[ooffset] = make_var(interp, line + offset, &next);
                if (ops[ooffset] == 0) {
-                       return -4;
+                       fret = -4;
+                       goto fail;
                } else {
                        ooffset++;
                        offset += next;
@@ -217,14 +234,61 @@ loop:
        }
 
        // step 2 - execute
-       if (ooffset == 0)
-               return -1;
+       if (ooffset == 0) {
+               fret = -1;
+               goto fail;
+       }
+
+       if (ops[0]->valtype != FUNC) {
+               fret = -2;
+               goto fail;
+       }
 
-       if (ops[0]->valtype != FUNC)
-               return -2;
+       if (ops[0]->fromc && ops[0]->value == 0) {
+               fret = -3;
+               goto fail;
+       }
 
-       if (ops[0]->fromc && ops[0]->value == 0)
-               return -3;
+       if (ops[ooffset] != (void *)-1)
+               ops[ooffset] = 0;
+
+loop:
+       for (uint8_t i = 0; i < IUP_COUNT; i++) {
+               if (interp->lines[interp->lnidx][0]->value
+                       == (uint32_t)indent_up[i]) {
+                       interp->indent++;
+                       goto cont;
+               }
+       }
+       for (uint8_t i = 0; i < IDOWN_COUNT; i++) {
+               if (interp->lines[interp->lnidx][0]->value
+                       == (uint32_t)indent_down[i]) {
+                       if (--interp->indent < 0) {
+                               fret = -6;
+                               goto fail;
+                       }
+                       if (interp->indent < (interp->sindent & ~(SKIP)))
+                               interp->sindent &= ~(SKIP);
+                       else
+                               goto cont;
+                       break;
+               }
+       }
+
+cont:
+       if (interp->indent > 0 && interp->sindent & SKIP)
+               goto norun;
+
+       ops = (variable **)malloc(8 * sizeof(variable *));
+       memcpy(ops, interp->lines[interp->lnidx], 8 * sizeof(variable *));
+       uint32_t oldLnidx = interp->lnidx;
+       
+       // eval expressions
+       ooffset = 1;
+       for (; ops[ooffset] != 0 && ops[ooffset] != (void *)-1; ooffset++) {
+               if (ops[ooffset]->valtype == EXPR)
+                       ops[ooffset] = idoexpr(interp, ops[ooffset]->svalue);
+       }
 
        if (ops[0]->fromc) {
                for (uint32_t i = ooffset; --i > 0;)
@@ -237,7 +301,7 @@ loop:
        } else {
                char an[6];
                for (uint32_t i = 1; i < ooffset; i++) {
-                       snprintf(an, 6, "arg%d", i - 1);
+                       snprintf(an, 6, "arg%d", (int)(i - 1));
                        switch (ops[i]->valtype) {
                        case STRING:
                                inew_string(interp, an, ops[i]->svalue);
@@ -255,26 +319,35 @@ loop:
 
                ipush(interp, (void *)(interp->lnidx));
                interp->lnidx = ops[0]->value;
+               interp->indent++;
        }
 
+       if (ops[ooffset] == (void *)-1)
+               interp->ret = ops[ooffset + 1];
+
        if ((int32_t)interp->stidx < 0) {
                interp->stidx = 0;
                return -5;
        }
 
-       for (uint32_t i = 0; i < ooffset; i++) {
-               if (!ops[i]->used)
+       for (uint32_t i = 1; i < ooffset; i++) {
+               if (ops[i] != interp->lines[oldLnidx][i]) {
+                       free(ops[i]->svalue);
                        free(ops[i]);
+               }
        }
-
+       free(ops);
 norun:
        interp->lnidx++;
-       if (interp->lines[interp->lnidx] != 0) {
-               line = interp->lines[interp->lnidx];
+       if (interp->lines[interp->lnidx] != 0)
                goto loop;
-       }
 
        return 0;
+
+fail:
+       free(interp->lines[interp->lnidx]);
+       interp->lines[interp->lnidx] = 0;
+       return fret;
 }
 
 variable *idoexpr(interpreter *interp, const char *line)
@@ -359,10 +432,16 @@ variable *idoexpr(interpreter *interp, const char *line)
        }
 
        for (uint32_t i = 0; i < ooffset; i += 2) {
-               if (!((variable *)ops[i])->used)
+               if (!((variable *)ops[i])->used) {
+                       char *s = ((variable *)ops[i])->svalue;
+                       if (s != 0 && s != str_undef)
+                               free(s);
                        free(ops[i]);
+               }
        }
-
+       
+       result->used = 0;
+       result->svalue = 0;
        if (result->valtype == INTEGER)
                isetstr(result);
        else
index 4e4699e21810dab2f1d7bbe7f296b0cbe97f7b14..92a8eb3eacab0ef669e5d6ffdb26a773c9b9b506 100644 (file)
--- a/parser.h
+++ b/parser.h
@@ -10,19 +10,25 @@ typedef struct {
        char **vnames;
        stack_t *stack;
        uint32_t stidx;
-       char **lines;
+       variable ***lines;
        uint32_t lnidx;
-       uint8_t indent;
+       int8_t indent;
+       uint8_t sindent;
        variable *ret;
 } interpreter;
 
+#define SKIP (1 << 7)
+
 typedef int (*func_t)(interpreter *);
 
 void iinit(interpreter *);
+void iend(interpreter *it);
+
+void iskip(interpreter *it);
 
-void inew_string(interpreter *, const char *, char *);
-void inew_integer(interpreter *, const char *, int32_t);
-void inew_float(interpreter *, const char *, float);
+variable *inew_string(interpreter *, const char *, char *);
+variable *inew_integer(interpreter *, const char *, int32_t);
+variable *inew_float(interpreter *, const char *, float);
 void inew_cfunc(interpreter *, const char *, func_t);
 
 int idoline(interpreter *, const char *);
diff --git a/script b/script
index 3b807a24fa43df962669950dafeeef62ff7190c9..dac7da5a71ac74656ae187acef6f05eab0f435d0 100644 (file)
--- a/script
+++ b/script
@@ -1,17 +1,18 @@
-func inc
-       set arg0 (arg0 + 1)
-       ret arg0
+func divisible
+       if (arg1 == 0)
+               ret 0
+       end
+       ret (arg0 % arg1)
 end
 
 set a 0
+set b 4
 do
-       inc a > a
-       if ((a % 9) == 0)
-               put a
+       set a (a + 1)
+       divisible a b > i
+       if (i == 0)
+               print a
        end
 while (a < 100)
 
-if (a == 100)
-       put "All good!"
-end
-
+print "All done!"
diff --git a/shell.c b/shell.c
index 0c0c4df8db98998425f7b1c47d7f520c99d950e0..c63b1bc4307b63bcef5dec9c80dd10fb23901ba7 100644 (file)
--- a/shell.c
+++ b/shell.c
@@ -59,7 +59,7 @@ int main(int argc, char **argv)
        }
 
        iinit(&interp);
-       inew_cfunc(&interp, "put", s_put);
+       inew_cfunc(&interp, "print", s_put);
        inew_cfunc(&interp, "tp", s_type);
        inew_cfunc(&interp, "q", quit);
 
@@ -75,5 +75,6 @@ int main(int argc, char **argv)
        }
 
        fclose(fp);
+       iend(&interp);
        return 0;
 }
index 0d2da24ff57e0233b77638350fcff0a0c6dddb41..fbde4ababa32d9b019e662097056c0da629a4bd3 100644 (file)
@@ -14,6 +14,7 @@ char *strnclone(const char *s, uint32_t n)
 {
        char *clone = (char *)malloc(n + 1);
        strncpy(clone, s, n);
+       clone[n] = '\0';
        return clone;
 }
 
index 727ca0c1a9bc94e4f15a3c49ae6b489905cbb81c..620a4b6023ebde5fb5dd9b4cf8507e5381705fb9 100644 (file)
@@ -5,6 +5,47 @@
 #include <stdlib.h>
 
 extern char *str_undef;
+extern char *str_func;
+
+variable *vmake(uint8_t fromc, uint8_t valtype, void *value)
+{
+       variable *v = (variable *)malloc(sizeof(variable));
+       v->used = 0;
+       v->fromc = fromc;
+       v->valtype = valtype;
+       v->value = 0;
+       v->svalue = 0;
+       switch (valtype) {
+       case STRING:
+               v->value = 0;
+               v->svalue = value;
+               break;
+       case INTEGER:
+               INT(v) = (int32_t)value;
+               isetstr(v);
+               break;
+       case FUNC:
+               v->value = (uint32_t)value;
+               v->svalue = str_func;
+               break;
+       case EXPR:
+               v->value = 0;
+               v->svalue = value;
+               break;
+       }
+       return v;
+}
+
+variable *vmakef(float value)
+{
+       variable *v = (variable *)malloc(sizeof(variable));
+       v->used = 0;
+       v->fromc = 0;
+       v->valtype = FLOAT;
+       FLOAT(v) = value;
+       fsetstr(v);
+       return v;
+}
 
 void fsetstr(variable *f)
 {
@@ -17,7 +58,7 @@ void isetstr(variable *i)
 {
        if (i->svalue == 0 || i->svalue == str_undef)
                i->svalue = (char *)malloc(12);
-       snprintf(i->svalue, 12, "%d", INT(i));
+       snprintf(i->svalue, 12, "%d", (int)INT(i));
 }
 
 variable *itostring(variable *v)
index 82c6b2583cdc481c2a20a6bb0f7468c03f75137f..e5aa20c76e8ad049ab10b63ccac5f900ba15c01f 100644 (file)
@@ -9,7 +9,7 @@
 typedef struct {
        uint8_t used :1;
        uint8_t fromc :1;
-       uint8_t valtype :2;
+       uint8_t valtype :4;
        uint32_t value;
        char *svalue;
 } variable;
@@ -18,9 +18,13 @@ enum valtype {
        STRING = 0,
        INTEGER,
        FLOAT,
-       FUNC
+       FUNC,
+       EXPR
 };
 
+variable *vmake(uint8_t fromc, uint8_t valtype, void *value);
+variable *vmakef(float value);
+
 void isetstr(variable *i);
 void fsetstr(variable *f);