]> code.bitgloo.com Git - clyne/interpreter.git/commitdiff
conditionals: if, do/while
authorClyne Sullivan <tullivan99@gmail.com>
Tue, 6 Feb 2018 13:48:21 +0000 (08:48 -0500)
committerClyne Sullivan <tullivan99@gmail.com>
Tue, 6 Feb 2018 13:48:21 +0000 (08:48 -0500)
parser.c
script [new file with mode: 0644]
shell.c

index 87a584e3c5daa2ec97abde1c0a7d4a3ed092dc3b..0f75c9e10bd5de9bc62230c914d60dadd7889fed 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -16,14 +16,14 @@ static char *str_undef = "(undefined)";
 
 char *strclone(const char *s)
 {
-       char *clone = (char *)malloc(strlen(s));
+       char *clone = (char *)malloc(strlen(s) + 1);
        strcpy(clone, s);
        return clone;
 }
 
 char *strnclone(const char *s, uint32_t n)
 {
-       char *clone = (char *)malloc(n);
+       char *clone = (char *)malloc(n + 1);
        strncpy(clone, s, n);
        return clone;
 }
@@ -74,10 +74,25 @@ uint32_t findend(const char *s, char o, char c)
 
        return i;
 }
+
+void skipblank(const char *s, uint8_t (*cmp)(int), uint32_t *offset)
+{
+       uint32_t i = *offset;
+       while (!cmp(s[i])) {
+               if (s[i] != ' ' && s[i] != '\t')
+                       break;
+               i++;
+       }
+       *offset = i;
+}
+
 int ifunc_set(interpreter *it);
 int ifunc_jmp(interpreter *it);
 int ifunc_label(interpreter *it);
 int ifunc_end(interpreter *it);
+int ifunc_if(interpreter *it);
+int ifunc_do(interpreter *it);
+int ifunc_while(interpreter *it);
 
 variable *idoexpr(interpreter *interp, const char *line);
 
@@ -99,6 +114,9 @@ void iinit(interpreter *interp)
        inew_cfunc(interp, "jmp", ifunc_jmp);
        inew_cfunc(interp, "func", ifunc_label);
        inew_cfunc(interp, "end", ifunc_end);
+       inew_cfunc(interp, "if", ifunc_if);
+       inew_cfunc(interp, "do", ifunc_do);
+       inew_cfunc(interp, "while", ifunc_while);
 }
 
 void ipush(interpreter *it, void *v)
@@ -266,6 +284,7 @@ loop:
        offset = 0;
 
        // step 1 - convert to tokens
+       skipblank(line, eol, &offset);
        while (!eol(line[offset])) {
                ops[ooffset] = make_var(interp, line + offset, &next);
                if (ops[ooffset] == 0) {
@@ -274,9 +293,7 @@ loop:
                        ooffset++;
                        offset += next;
                }
-
-               // skip whitespace
-               for (; line[offset] == ' ' && !eol(line[offset]); offset++);
+               skipblank(line, eol, &offset);
        }
 
        // step 2 - execute
@@ -365,7 +382,7 @@ variable *idoexpr(interpreter *interp, const char *line)
        // step 1 - break apart line
 
        // skip whitespace
-       for (; line[offset] == ' ' && !eol(line[offset]); offset++);
+       skipblank(line, eol, &offset);
        while (!eoe(line[offset])) {
                if (line[offset] == '(') {
                        uint8_t indent = 0;
@@ -404,7 +421,7 @@ variable *idoexpr(interpreter *interp, const char *line)
                offset += next;
 
                // skip whitespace
-               for (; line[offset] == ' ' && !eoe(line[offset]); offset++);
+               skipblank(line, eoe, &offset);
                if (eoe(line[offset]))
                        break;
 
@@ -421,7 +438,7 @@ variable *idoexpr(interpreter *interp, const char *line)
                ooffset++;
 
                // skip whitespace
-               for (; line[offset] == ' ' && !eol(line[offset]); offset++);
+               skipblank(line, eol, &offset);
        }
 
        if (ooffset % 2 == 0)
@@ -557,6 +574,14 @@ int ifunc_label(interpreter *it)
        return 0;
 }
 
+int ifunc_if(interpreter *it)
+{
+       int v = igetarg_integer(it, 0);
+       if (v == 0)
+               it->indent++;
+       return 0;
+}
+
 int ifunc_end(interpreter *it)
 {
        if (it->stidx > 0) {
@@ -576,6 +601,25 @@ int ifunc_jmp(interpreter *it)
        return 0;
 }
 
+int ifunc_do(interpreter *it)
+{
+       ipush(it, (void *)it->lnidx);
+       return 0;
+}
+
+int ifunc_while(interpreter *it)
+{
+       int c = igetarg_integer(it, 0);
+       ipop(it);
+       int nidx = (int)ipop(it);
+       if (c != 0) {
+               ipush(it, (void *)nidx);
+               it->lnidx = nidx;
+       }
+       ipush(it, 0);
+       return 0;
+}
+
 /**
  * Builtin operations
  */
diff --git a/script b/script
new file mode 100644 (file)
index 0000000..b31a18e
--- /dev/null
+++ b/script
@@ -0,0 +1,5 @@
+set a 0
+do
+       put a
+       set a (a+1)
+while (a<5)
diff --git a/shell.c b/shell.c
index 1d222695cf37db8f86da2a0d2c47b4309b96c305..751ef8f537bdafeafce192be8a48453f0d16d3d1 100644 (file)
--- a/shell.c
+++ b/shell.c
@@ -41,10 +41,21 @@ int quit(interpreter *it)
        return 0;
 }
 
-int main()
+int main(int argc, char **argv)
 {
        interpreter interp;
 
+       if (argc != 2) {
+               printf("Usage: %s file\n", argv[0]);
+               return -1;
+       }
+
+       FILE *fp = fopen(argv[1], "r");
+       if (fp == 0) {
+               printf("Could not open file: %s\n", argv[1]);
+               return -1;
+       }
+
        iinit(&interp);
        inew_cfunc(&interp, "put", s_put);
        inew_cfunc(&interp, "tp", s_type);
@@ -54,14 +65,13 @@ int main()
        char *line = 0;
        unsigned int size;
        int result;
-       while (1) {
-               printf("%d> ", interp.lnidx);
-               getline(&line, &size, stdin);
+       while (getline(&line, &size, fp) != -1) {
                *strchr(line, '\n') = '\0';
                result = idoline(&interp, line);
                if (result != 0)
                        printf("Error: %d\n", result);
        }
 
+       fclose(fp);
        return 0;
 }