]> code.bitgloo.com Git - clyne/interpreter.git/commitdiff
conditionals, returns, cleaner code
authorClyne Sullivan <tullivan99@gmail.com>
Wed, 7 Feb 2018 14:26:36 +0000 (09:26 -0500)
committerClyne Sullivan <tullivan99@gmail.com>
Wed, 7 Feb 2018 14:26:36 +0000 (09:26 -0500)
16 files changed:
Makefile
README.md
builtins.c [new file with mode: 0644]
builtins.h [new file with mode: 0644]
ops.c [new file with mode: 0644]
ops.h [new file with mode: 0644]
parser.c
parser.h
script
shell.c
shelpers.c [new file with mode: 0644]
shelpers.h [new file with mode: 0644]
stack.c [new file with mode: 0644]
stack.h [new file with mode: 0644]
variable.c [new file with mode: 0644]
variable.h

index 7fcb26ccd9e91f9180d6dcbc6da5902a8c3c3497..f81b5891781681be3068755425cff1b3316c65ce 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,5 +3,10 @@ CC = gcc -m32
 CFLAGS = -Wall -Wextra -Wno-strict-aliasing -I. -ggdb -fno-builtin
 
 all:
+       $(CC) $(CFLAGS) -c shelpers.c
        $(CC) $(CFLAGS) -c parser.c
-       $(CC) $(CFLAGS) shell.c parser.o -o shell
+       $(CC) $(CFLAGS) -c builtins.c
+       $(CC) $(CFLAGS) -c stack.c
+       $(CC) $(CFLAGS) -c ops.c
+       $(CC) $(CFLAGS) -c variable.c
+       $(CC) $(CFLAGS) shell.c *.o -o shell
index 1a11269268b2a284127bd4428b99e618db716ee4..6084d7c55d25b7f89edc17b1efbbbb11049b6142 100644 (file)
--- a/README.md
+++ b/README.md
@@ -6,14 +6,19 @@ To use this program with your own device, you need some malloc/free implementati
 Only a few commands are built in to the interpreter:  
 * set - set variables
 * func/end - define functions
-* jmp - jump to line
-  
+* if/end - if conditional
+* do/while
+* ret - return value from function
+
 Other features:  
 * function/variable defining in c
 * expression solving  
+* no local variables
+* whitespace hopefully ignored
   
 Soon:  
-* conditionals
 * error messages
+* arrays?
+* maybe for loops
   
 This project is still in heavy development, so don't expect much. To include it in your own project, just link in parser.o and use the header files.
diff --git a/builtins.c b/builtins.c
new file mode 100644 (file)
index 0000000..cda7a93
--- /dev/null
@@ -0,0 +1,118 @@
+#include "builtins.h"
+#include "stack.h"
+
+extern char *str_func;
+
+int ifunc_set(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);
+int ifunc_ret(interpreter *it);
+
+void iload_core(interpreter *interp)
+{
+       inew_cfunc(interp, "set", ifunc_set);
+       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);
+       inew_cfunc(interp, "ret", ifunc_ret);
+}
+
+int ifunc_set(interpreter *it)
+{
+       variable *n = igetarg(it, 0);
+       variable *v = igetarg(it, 1);
+
+       if (n == 0)
+               return -1;
+
+       n->valtype = v->valtype;
+       n->value = v->value;
+       n->svalue = v->svalue;
+       return 0;
+}
+
+int ifunc_label(interpreter *it)
+{
+       variable *n = igetarg(it, 0);
+       
+       if (n == 0)
+               return -1;
+
+       n->valtype = FUNC;
+       n->value = it->lnidx;
+       n->svalue = str_func;
+       it->indent++;
+       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);
+       }
+       return 0;
+}
+
+int ifunc_end(interpreter *it)
+{
+       uint32_t lnidx = (uint32_t)ipop(it) + 1;
+       if (lnidx != 0)
+               it->lnidx = lnidx;
+       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;
+}
+
+int ifunc_ret(interpreter *it)
+{
+       variable *v = igetarg(it, 0);
+       switch (v->valtype) {
+       case INTEGER:
+               inew_integer(it, "RET", INT(v));
+               break;
+       case FLOAT:
+               inew_float(it, "RET", FLOAT(v));
+               break;
+       case STRING:
+               inew_string(it, "RET", v->svalue);
+               break;
+       default:
+               return -1;
+               break;
+       }
+       if (it->ret != 0) {
+               it->ret->valtype = v->valtype;
+               it->ret->value = v->value;
+               it->ret->svalue = v->svalue;
+               it->ret = 0;
+       }
+       return 0;
+}
+
diff --git a/builtins.h b/builtins.h
new file mode 100644 (file)
index 0000000..8739778
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef BUILTINS_H_
+#define BUILTINS_H_
+
+#include "parser.h"
+
+void iload_core(interpreter *it);
+
+#endif // BUILTINS_H_
diff --git a/ops.c b/ops.c
new file mode 100644 (file)
index 0000000..34e7986
--- /dev/null
+++ b/ops.c
@@ -0,0 +1,167 @@
+#include "ops.h"
+
+void iop_add(variable *, variable *, variable *);
+void iop_sub(variable *, variable *, variable *);
+void iop_mult(variable *, variable *, variable *);
+void iop_div(variable *, variable *, variable *);
+void iop_and(variable *, variable *, variable *);
+void iop_or(variable *, variable *, variable *);
+void iop_xor(variable *, variable *, variable *);
+void iop_shr(variable *, variable *, variable *);
+void iop_shl(variable *, variable *, variable *);
+void iop_eq(variable *, variable *, variable *);
+void iop_lt(variable *, variable *, variable *);
+void iop_gt(variable *, variable *, variable *);
+void iop_lte(variable *, variable *, variable *);
+void iop_gte(variable *, variable *, variable *);
+void iop_ne(variable *, variable *, variable *);
+void iop_mod(variable *, variable *, variable *);
+
+char *iops[IOPS_COUNT] = {
+       "+", "-", "*", "/", "&", "|", "^", ">>", "<<",
+       "==", "<", ">", "<=", ">=", "!=", "%"
+};
+
+operation_t iopfuncs[IOPS_COUNT] = {
+       iop_add, iop_sub, iop_mult, iop_div, iop_and,
+       iop_or, iop_xor, iop_shr, iop_shl,
+       iop_eq, iop_lt, iop_gt, iop_lte, iop_gte, iop_ne,
+       iop_mod
+};
+
+
+void iop_add(variable *r, variable *a, variable *b)
+{
+       if (a->valtype == INTEGER && b->valtype == INTEGER) {
+               INT(r) = INT(a) + INT(b);
+       } else {
+               itofloat(a);
+               itofloat(b);
+               FLOAT(r) = FLOAT(a) + FLOAT(b);
+       }
+}
+
+void iop_sub(variable *r, variable *a, variable *b)
+{
+       if (a->valtype == INTEGER && b->valtype == INTEGER) {
+               INT(r) = INT(a) - INT(b);
+       } else {
+               itofloat(a);
+               itofloat(b);
+               FLOAT(r) = FLOAT(a) - FLOAT(b);
+       }
+}
+
+void iop_mult(variable *r, variable *a, variable *b)
+{
+       if (a->valtype == INTEGER && b->valtype == INTEGER) {
+               INT(r) = INT(a) * INT(b);
+       } else {
+               itofloat(a);
+               itofloat(b);
+               FLOAT(r) = FLOAT(a) * FLOAT(b);
+       }
+}
+
+void iop_div(variable *r, variable *a, variable *b)
+{
+       if (a->valtype == INTEGER && b->valtype == INTEGER) {
+               INT(r) = INT(a) / INT(b);
+       } else {
+               itofloat(a);
+               itofloat(b);
+               FLOAT(r) = FLOAT(a) / FLOAT(b);
+       }
+}
+
+void iop_and(variable *r, variable *a, variable *b)
+{
+       if (a->valtype == INTEGER && b->valtype == INTEGER) {
+               INT(r) = INT(a) & INT(b);
+       }
+}
+
+void iop_or(variable *r, variable *a, variable *b)
+{
+       if (a->valtype == INTEGER && b->valtype == INTEGER) {
+               INT(r) = INT(a) | INT(b);
+       }
+}
+
+void iop_xor(variable *r, variable *a, variable *b)
+{
+       if (a->valtype == INTEGER && b->valtype == INTEGER) {
+               INT(r) = INT(a) ^ INT(b);
+       }
+}
+
+void iop_shr(variable *r, variable *a, variable *b)
+{
+       if (a->valtype == INTEGER && b->valtype == INTEGER) {
+               INT(r) = INT(a) >> INT(b);
+       }
+}
+
+void iop_shl(variable *r, variable *a, variable *b)
+{
+       if (a->valtype == INTEGER && b->valtype == INTEGER) {
+               INT(r) = INT(a) << INT(b);
+       }
+}
+
+void iop_eq(variable *r, variable *a, variable *b)
+{
+       if (a->valtype == INTEGER && b->valtype == INTEGER)
+               INT(r) = INT(a) == INT(b);
+       else
+               INT(r) = FLOAT(a) == FLOAT(b);
+}
+
+void iop_lt(variable *r, variable *a, variable *b)
+{
+       if (a->valtype == INTEGER && b->valtype == INTEGER)
+               INT(r) = INT(a) < INT(b);
+       else
+               INT(r) = FLOAT(a) < FLOAT(b);
+}
+
+void iop_gt(variable *r, variable *a, variable *b)
+{
+       if (a->valtype == INTEGER && b->valtype == INTEGER)
+               INT(r) = INT(a) > INT(b);
+       else
+               INT(r) = FLOAT(a) > FLOAT(b);
+}
+
+void iop_lte(variable *r, variable *a, variable *b)
+{
+       if (a->valtype == INTEGER && b->valtype == INTEGER)
+               INT(r) = INT(a) <= INT(b);
+       else
+               INT(r) = FLOAT(a) <= FLOAT(b);
+}
+
+void iop_gte(variable *r, variable *a, variable *b)
+{
+       if (a->valtype == INTEGER && b->valtype == INTEGER)
+               INT(r) = INT(a) >= INT(b);
+       else
+               INT(r) = FLOAT(a) >= FLOAT(b);
+}
+
+void iop_ne(variable *r, variable *a, variable *b)
+{
+       if (a->valtype == INTEGER && b->valtype == INTEGER)
+               INT(r) = INT(a) != INT(b);
+       else
+               INT(r) = FLOAT(a) != FLOAT(b);
+}
+
+void iop_mod(variable *r, variable *a, variable *b)
+{
+       if (a->valtype == INTEGER && b->valtype == INTEGER)
+               INT(r) = INT(a) % INT(b);
+       else
+               INT(r) = 0;
+}
+
diff --git a/ops.h b/ops.h
new file mode 100644 (file)
index 0000000..5c7832f
--- /dev/null
+++ b/ops.h
@@ -0,0 +1,13 @@
+#ifndef OPS_H_
+#define OPS_H_
+
+#include "parser.h"
+
+#define IOPS_COUNT 16
+
+typedef void (*operation_t)(variable *, variable *, variable *);
+
+extern char *iops[IOPS_COUNT];
+extern operation_t iopfuncs[IOPS_COUNT];
+
+#endif // OPS_H_
index 0f75c9e10bd5de9bc62230c914d60dadd7889fed..bd540e08aa61247afc0279f2deb978fc96820085 100644 (file)
--- a/parser.c
+++ b/parser.c
 #include <parser.h>
 
+#include "shelpers.h"
+#include "builtins.h"
+#include "stack.h"
+#include "ops.h"
+
 #include <ctype.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#define MAX_VARS  32
-#define MAX_STACK 32
-
-#define INT(v)   (*((int32_t *)&v->value))
-#define FLOAT(v) (*((float *)&v->value))
-
-static char *str_func = "(func)";
-static char *str_undef = "(undefined)";
-
-char *strclone(const char *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 + 1);
-       strncpy(clone, s, n);
-       return clone;
-}
-
-void fsetstr(variable *f)
-{
-       if (f->svalue == 0)
-               f->svalue = (char *)malloc(16);
-       snprintf(f->svalue, 16, "%f", FLOAT(f));
-}
-
-void isetstr(variable *i)
-{
-       if (i->svalue == 0)
-               i->svalue = (char *)malloc(12);
-       snprintf(i->svalue, 12, "%d", INT(i));
-}
-
-uint8_t eol(int c)
-{
-       return c == '\n' || c == '\0';
-}
-
-uint8_t eot(int c)
-{
-       return eol(c) || c == ' ';
-}
-
-uint8_t eoe(int c)
-{
-       return eol(c) || c == ')';
-}
-
-uint32_t findend(const char *s, char o, char c)
-{
-       uint8_t indent = 0;
-       uint32_t i;
-       for (i = 1; !eol(s[i]); i++) {
-               if (s[i] == o) {
-                       indent++;
-               } else if (s[i] == c) {
-                       if (indent == 0)
-                               break;
-                       else
-                               indent--;
-               }
-       }
-
-       return i;
-}
+#define MAX_VARS  48
+#define MAX_STACK 16
+#define MAX_LINES 1000
 
-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);
+char *str_func = "(func)";
+char *str_undef = "(undefined)";
 
 variable *idoexpr(interpreter *interp, const char *line);
 
-variable *itostring(variable *v);
-variable *itoint(variable *v);
-variable *itofloat(variable *v);
-
 void iinit(interpreter *interp)
 {
-       interp->vars = (variable *)calloc(MAX_VARS, sizeof(variable));
-       interp->vnames = (char **)calloc(MAX_VARS, sizeof(char *));
-       interp->stack = (stack_t *)calloc(MAX_STACK, sizeof(stack_t));
+       interp->vars = (variable *)malloc(MAX_VARS * sizeof(variable));
+       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(20, sizeof(char *));
+       interp->lines = (char **)calloc(MAX_LINES, sizeof(char *));
        interp->lnidx = 0;
        interp->indent = 0;
 
-       inew_cfunc(interp, "set", ifunc_set);
-       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)
-{
-       it->stack[it->stidx++] = v;
-}
+       for (unsigned int i = 0; i < MAX_VARS; i++) {
+               interp->vars[i].used = 0;
+               interp->vnames[i] = 0;
+       }
+       for (unsigned int i = 0; i < MAX_LINES; i++)
+               interp->lines[i] = 0;
 
-void *ipop(interpreter *it)
-{
-       return it->stack[--it->stidx];
+       iload_core(interp);
 }
 
 variable *interpreter_get_variable(interpreter *interp, const char *name)
@@ -270,22 +179,34 @@ int idoline(interpreter *interp, const char *line)
        variable *ops[8];
        uint32_t ooffset, offset, next;
 
+       if (line[0] == '\0')
+               return 0;
+
        interp->lines[interp->lnidx] = strclone(line);
 loop:
+       ooffset = 0;
+       offset = 0;
+
        if (line[0] == '#') {
                goto norun;
        } else if (interp->indent > 0) {
-               if (!strcmp(line, "end"))
+               skipblank(line, eol, &offset);
+               if (!strcmp(line + offset, "end"))
                        interp->indent--;
                goto norun;
        }
 
-       ooffset = 0;
-       offset = 0;
-
        // step 1 - convert to tokens
        skipblank(line, eol, &offset);
        while (!eol(line[offset])) {
+               if (offset > 0 && line[offset] == '>') {
+                       offset++;
+                       skipblank(line, eol, &offset);
+                       interp->ret = make_var(interp, line + offset, &next);
+                       offset += next;
+                       skipblank(line, eol, &offset);
+                       continue;
+               }
                ops[ooffset] = make_var(interp, line + offset, &next);
                if (ops[ooffset] == 0) {
                        return -4;
@@ -303,23 +224,40 @@ loop:
        if (ops[0]->valtype != FUNC)
                return -2;
 
-       if (ops[0]->value == 0)
+       if (ops[0]->fromc && ops[0]->value == 0)
                return -3;
 
-       for (uint32_t i = ooffset; --i > 0;)
-               ipush(interp, ops[i]);
-
        if (ops[0]->fromc) {
+               for (uint32_t i = ooffset; --i > 0;)
+                       ipush(interp, ops[i]);
+
                int ret = ((func_t)ops[0]->value)(interp);
                if (ret != 0)
                        return ret;
+               ipopm(interp, ooffset - 1);
        } else {
-               ipush(interp, (void *)(interp->lnidx + 1));
+               char an[6];
+               for (uint32_t i = 1; i < ooffset; i++) {
+                       snprintf(an, 6, "arg%d", i - 1);
+                       switch (ops[i]->valtype) {
+                       case STRING:
+                               inew_string(interp, an, ops[i]->svalue);
+                               break;
+                       case INTEGER:
+                               inew_integer(interp, an, INT(ops[i]));
+                               break;
+                       case FLOAT:
+                               inew_float(interp, an, FLOAT(ops[i]));
+                               break;
+                       default:
+                               break;
+                       }
+               }
+
+               ipush(interp, (void *)(interp->lnidx));
                interp->lnidx = ops[0]->value;
        }
 
-       interp->stidx -= ooffset - 1;
-
        if ((int32_t)interp->stidx < 0) {
                interp->stidx = 0;
                return -5;
@@ -340,36 +278,6 @@ norun:
        return 0;
 }
 
-typedef void (*operation_t)(variable *, variable *, variable *);
-
-#define IOPS_COUNT 15
-static char *iops[IOPS_COUNT] = {
-       "+", "-", "*", "/", "&", "|", "^", ">>", "<<",
-       "==", "<", ">", "<=", ">=", "!="
-};
-
-void iop_add(variable *, variable *, variable *);
-void iop_sub(variable *, variable *, variable *);
-void iop_mult(variable *, variable *, variable *);
-void iop_div(variable *, variable *, variable *);
-void iop_and(variable *, variable *, variable *);
-void iop_or(variable *, variable *, variable *);
-void iop_xor(variable *, variable *, variable *);
-void iop_shr(variable *, variable *, variable *);
-void iop_shl(variable *, variable *, variable *);
-void iop_eq(variable *, variable *, variable *);
-void iop_lt(variable *, variable *, variable *);
-void iop_gt(variable *, variable *, variable *);
-void iop_lte(variable *, variable *, variable *);
-void iop_gte(variable *, variable *, variable *);
-void iop_ne(variable *, variable *, variable *);
-
-static operation_t iopfuncs[IOPS_COUNT] = {
-       iop_add, iop_sub, iop_mult, iop_div, iop_and,
-       iop_or, iop_xor, iop_shr, iop_shl,
-       iop_eq, iop_lt, iop_gt, iop_lte, iop_gte, iop_ne
-};
-
 variable *idoexpr(interpreter *interp, const char *line)
 {
        variable *result = (variable *)malloc(sizeof(variable));
@@ -413,12 +321,12 @@ variable *idoexpr(interpreter *interp, const char *line)
                        ops[ooffset] = make_var(interp, line + offset, &next);
                        if (end != 0)
                                mline[end] = cend;
+                       offset += next;
                }
                if (ops[ooffset] == 0)
                        return 0;
                
                ooffset++;
-               offset += next;
 
                // skip whitespace
                skipblank(line, eoe, &offset);
@@ -464,290 +372,3 @@ variable *idoexpr(interpreter *interp, const char *line)
        return result;
 }
 
-variable *igetarg(interpreter *interp, uint32_t index)
-{
-       return interp->stack[interp->stidx - index - 1];
-}
-
-char *igetarg_string(interpreter *interp, uint32_t index)
-{
-       if (index >= interp->stidx)
-               return 0;
-       variable *v = igetarg(interp, index);
-       return v->svalue;
-}
-
-int igetarg_integer(interpreter *interp, uint32_t index)
-{
-       if (index >= interp->stidx)
-               return 0;
-       variable *v = igetarg(interp, index);
-       return INT(itoint(v));
-}
-
-float igetarg_float(interpreter *interp, uint32_t index)
-{
-       if (index >= interp->stidx)
-               return 0;
-       variable *v = igetarg(interp, index);
-       return FLOAT(itofloat(v));
-}
-
-variable *itostring(variable *v)
-{
-       switch (v->valtype) {
-       case INTEGER:
-               v->valtype = STRING;
-               isetstr(v);
-               break;
-       case FLOAT:
-               v->valtype = STRING;
-               fsetstr(v);
-               break;
-       }
-       return v;
-}
-
-variable *itoint(variable *v)
-{
-       switch (v->valtype) {
-       case STRING:
-               v->valtype = INTEGER;
-               INT(v) = atoi(v->svalue);
-               isetstr(v);
-               break;
-       case FLOAT:
-               v->valtype = INTEGER;
-               INT(v) = (int32_t)FLOAT(v);
-               isetstr(v);
-               break;
-       }
-       return v;
-}
-
-variable *itofloat(variable *v)
-{
-       switch (v->valtype) {
-       case STRING:
-               v->valtype = FLOAT;
-               FLOAT(v) = strtof(v->svalue, 0);
-               fsetstr(v);
-               break;
-       case INTEGER:
-               v->valtype = FLOAT;
-               FLOAT(v) = (float)INT(v);
-               fsetstr(v);
-               break;
-       }
-       return v;
-}
-
-/**
- * Builtin functions
- */
-
-int ifunc_set(interpreter *it)
-{
-       variable *n = igetarg(it, 0);
-       variable *v = igetarg(it, 1);
-
-       if (n == 0)
-               return -1;
-
-       n->valtype = v->valtype;
-       n->value = v->value;
-       n->svalue = v->svalue;
-       return 0;
-}
-
-int ifunc_label(interpreter *it)
-{
-       variable *n = igetarg(it, 0);
-       
-       if (n == 0)
-               return -1;
-
-       n->valtype = FUNC;
-       n->value = it->lnidx;
-       n->svalue = str_func;
-       it->indent++;
-       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) {
-               uint32_t line = (uint32_t)ipop(it);
-               it->lnidx = line - 1;
-       }
-       return 0;
-}
-
-int ifunc_jmp(interpreter *it)
-{
-       int newidx = igetarg_integer(it, 0);
-       ipop(it);
-       ipush(it, (void *)(it->lnidx + 1));
-       ipush(it, 0);
-       it->lnidx = newidx - 1;
-       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
- */
-
-void iop_add(variable *r, variable *a, variable *b)
-{
-       if (a->valtype == INTEGER && b->valtype == INTEGER) {
-               INT(r) = INT(a) + INT(b);
-       } else {
-               itofloat(a);
-               itofloat(b);
-               FLOAT(r) = FLOAT(a) + FLOAT(b);
-       }
-}
-
-void iop_sub(variable *r, variable *a, variable *b)
-{
-       if (a->valtype == INTEGER && b->valtype == INTEGER) {
-               INT(r) = INT(a) - INT(b);
-       } else {
-               itofloat(a);
-               itofloat(b);
-               FLOAT(r) = FLOAT(a) - FLOAT(b);
-       }
-}
-
-void iop_mult(variable *r, variable *a, variable *b)
-{
-       if (a->valtype == INTEGER && b->valtype == INTEGER) {
-               INT(r) = INT(a) * INT(b);
-       } else {
-               itofloat(a);
-               itofloat(b);
-               FLOAT(r) = FLOAT(a) * FLOAT(b);
-       }
-}
-
-void iop_div(variable *r, variable *a, variable *b)
-{
-       if (a->valtype == INTEGER && b->valtype == INTEGER) {
-               INT(r) = INT(a) / INT(b);
-       } else {
-               itofloat(a);
-               itofloat(b);
-               FLOAT(r) = FLOAT(a) / FLOAT(b);
-       }
-}
-
-void iop_and(variable *r, variable *a, variable *b)
-{
-       if (a->valtype == INTEGER && b->valtype == INTEGER) {
-               INT(r) = INT(a) & INT(b);
-       }
-}
-
-void iop_or(variable *r, variable *a, variable *b)
-{
-       if (a->valtype == INTEGER && b->valtype == INTEGER) {
-               INT(r) = INT(a) | INT(b);
-       }
-}
-
-void iop_xor(variable *r, variable *a, variable *b)
-{
-       if (a->valtype == INTEGER && b->valtype == INTEGER) {
-               INT(r) = INT(a) ^ INT(b);
-       }
-}
-
-void iop_shr(variable *r, variable *a, variable *b)
-{
-       if (a->valtype == INTEGER && b->valtype == INTEGER) {
-               INT(r) = INT(a) >> INT(b);
-       }
-}
-
-void iop_shl(variable *r, variable *a, variable *b)
-{
-       if (a->valtype == INTEGER && b->valtype == INTEGER) {
-               INT(r) = INT(a) << INT(b);
-       }
-}
-
-void iop_eq(variable *r, variable *a, variable *b)
-{
-       if (a->valtype == INTEGER && b->valtype == INTEGER)
-               INT(r) = INT(a) == INT(b);
-       else
-               INT(r) = FLOAT(a) == FLOAT(b);
-}
-
-void iop_lt(variable *r, variable *a, variable *b)
-{
-       if (a->valtype == INTEGER && b->valtype == INTEGER)
-               INT(r) = INT(a) < INT(b);
-       else
-               INT(r) = FLOAT(a) < FLOAT(b);
-}
-
-void iop_gt(variable *r, variable *a, variable *b)
-{
-       if (a->valtype == INTEGER && b->valtype == INTEGER)
-               INT(r) = INT(a) > INT(b);
-       else
-               INT(r) = FLOAT(a) > FLOAT(b);
-}
-
-void iop_lte(variable *r, variable *a, variable *b)
-{
-       if (a->valtype == INTEGER && b->valtype == INTEGER)
-               INT(r) = INT(a) <= INT(b);
-       else
-               INT(r) = FLOAT(a) <= FLOAT(b);
-}
-
-void iop_gte(variable *r, variable *a, variable *b)
-{
-       if (a->valtype == INTEGER && b->valtype == INTEGER)
-               INT(r) = INT(a) >= INT(b);
-       else
-               INT(r) = FLOAT(a) >= FLOAT(b);
-}
-
-void iop_ne(variable *r, variable *a, variable *b)
-{
-       if (a->valtype == INTEGER && b->valtype == INTEGER)
-               INT(r) = INT(a) != INT(b);
-       else
-               INT(r) = FLOAT(a) != FLOAT(b);
-}
-
index 83a81e1218814075c3236bc62fcc13dce102c075..4e4699e21810dab2f1d7bbe7f296b0cbe97f7b14 100644 (file)
--- a/parser.h
+++ b/parser.h
@@ -13,6 +13,7 @@ typedef struct {
        char **lines;
        uint32_t lnidx;
        uint8_t indent;
+       variable *ret;
 } interpreter;
 
 typedef int (*func_t)(interpreter *);
@@ -26,9 +27,4 @@ void inew_cfunc(interpreter *, const char *, func_t);
 
 int idoline(interpreter *, const char *);
 
-variable *igetarg(interpreter *, uint32_t);
-char *igetarg_string(interpreter *, uint32_t);
-int igetarg_integer(interpreter *, uint32_t); 
-float igetarg_float(interpreter *, uint32_t);
-
 #endif // PARSER_H_
diff --git a/script b/script
index b31a18e5896c6d2cd11820afb874f13e8a125e72..3b807a24fa43df962669950dafeeef62ff7190c9 100644 (file)
--- a/script
+++ b/script
@@ -1,5 +1,17 @@
+func inc
+       set arg0 (arg0 + 1)
+       ret arg0
+end
+
 set a 0
 do
-       put a
-       set a (a+1)
-while (a<5)
+       inc a > a
+       if ((a % 9) == 0)
+               put a
+       end
+while (a < 100)
+
+if (a == 100)
+       put "All good!"
+end
+
diff --git a/shell.c b/shell.c
index 751ef8f537bdafeafce192be8a48453f0d16d3d1..0c0c4df8db98998425f7b1c47d7f520c99d950e0 100644 (file)
--- a/shell.c
+++ b/shell.c
@@ -1,5 +1,7 @@
 #include <parser.h>
 
+#include "stack.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
diff --git a/shelpers.c b/shelpers.c
new file mode 100644 (file)
index 0000000..0d2da24
--- /dev/null
@@ -0,0 +1,63 @@
+#include "shelpers.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+char *strclone(const char *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 + 1);
+       strncpy(clone, s, n);
+       return clone;
+}
+
+uint8_t eol(int c)
+{
+       return c == '\n' || c == '\0';
+}
+
+uint8_t eot(int c)
+{
+       return eol(c) || c == ' ';
+}
+
+uint8_t eoe(int c)
+{
+       return eol(c) || c == ')';
+}
+
+uint32_t findend(const char *s, char o, char c)
+{
+       uint8_t indent = 0;
+       uint32_t i;
+       for (i = 1; !eol(s[i]); i++) {
+               if (s[i] == o) {
+                       indent++;
+               } else if (s[i] == c) {
+                       if (indent == 0)
+                               break;
+                       else
+                               indent--;
+               }
+       }
+
+       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;
+}
+
diff --git a/shelpers.h b/shelpers.h
new file mode 100644 (file)
index 0000000..7f2ad63
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef SHELPERS_H_
+#define SHELPERS_H_
+
+#include <stdint.h>
+
+/**
+ * Clones the given string, malloc'ing a new one.
+ * @param s the string to clone
+ * @return the malloc'd copy
+ */
+char *strclone(const char *s);
+
+/**
+ * Clones the given string until the given count.
+ * @param s the string to clone
+ * @param n the number of characters to clone
+ * @return the malloc'd copy
+ */
+char *strnclone(const char *s, uint32_t n);
+
+
+/**
+ * Returns non-zero if the character is considered an end-of-line.
+ * @param c a character
+ * @return non-zero if eol, zero if not
+ */
+uint8_t eol(int c);
+
+/**
+ * Returns non-zero if the character is considered an end-of-token.
+ * @param c a character
+ * @return non-zero if eot, zero if not
+ */
+uint8_t eot(int c);
+
+/**
+ * Returns non-zero if the character is considered an end-of-expression.
+ * @param c a character
+ * @return non-zero if eoe, zero if not
+ */
+uint8_t eoe(int c);
+
+
+/**
+ * Finds the matching end character in a string, e.g. matching parens.
+ * @param s the string to search
+ * @param o the starting, opening character (e.g. '(')
+ * @param c the end, closing character (e.g. ')')
+ * @return offset of the end character in the string
+ */
+uint32_t findend(const char *s, char o, char c);
+
+/**
+ * Increments offset until the character in the string is not blank or fails
+ * the given comparison.
+ * @param s the string to use
+ * @param cmp a comparing function, stops search if returns true
+ * @param offset the variable to increment while searching
+ */
+void skipblank(const char *s, uint8_t (*cmp)(int), uint32_t *offset);
+
+#endif // SHELPERS_H_
diff --git a/stack.c b/stack.c
new file mode 100644 (file)
index 0000000..d970bc2
--- /dev/null
+++ b/stack.c
@@ -0,0 +1,46 @@
+#include "stack.h"
+
+void ipush(interpreter *it, void *v)
+{
+       it->stack[it->stidx++] = v;
+}
+
+void *ipop(interpreter *it)
+{
+       return it->stack[--it->stidx];
+}
+
+void ipopm(interpreter *it, uint32_t count)
+{
+       it->stidx -= count;
+}
+
+variable *igetarg(interpreter *interp, uint32_t index)
+{
+       return interp->stack[interp->stidx - index - 1];
+}
+
+char *igetarg_string(interpreter *interp, uint32_t index)
+{
+       if (index >= interp->stidx)
+               return 0;
+       variable *v = igetarg(interp, index);
+       return v->svalue;
+}
+
+int igetarg_integer(interpreter *interp, uint32_t index)
+{
+       if (index >= interp->stidx)
+               return 0;
+       variable *v = igetarg(interp, index);
+       return INT(itoint(v));
+}
+
+float igetarg_float(interpreter *interp, uint32_t index)
+{
+       if (index >= interp->stidx)
+               return 0;
+       variable *v = igetarg(interp, index);
+       return FLOAT(itofloat(v));
+}
+
diff --git a/stack.h b/stack.h
new file mode 100644 (file)
index 0000000..d5a7f96
--- /dev/null
+++ b/stack.h
@@ -0,0 +1,15 @@
+#ifndef STACK_H_
+#define STACK_H_
+
+#include "parser.h"
+
+void ipush(interpreter *it, void *v);
+void *ipop(interpreter *it);
+void ipopm(interpreter *it, uint32_t count);
+variable *igetarg(interpreter *interp, uint32_t index);
+char *igetarg_string(interpreter *interp, uint32_t index);
+int igetarg_integer(interpreter *interp, uint32_t index);
+float igetarg_float(interpreter *interp, uint32_t index);
+
+
+#endif // STACK_H_
diff --git a/variable.c b/variable.c
new file mode 100644 (file)
index 0000000..727ca0c
--- /dev/null
@@ -0,0 +1,71 @@
+#include "variable.h"
+#include "parser.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+extern char *str_undef;
+
+void fsetstr(variable *f)
+{
+       if (f->svalue == 0 || f->svalue == str_undef)
+               f->svalue = (char *)malloc(16);
+       snprintf(f->svalue, 16, "%f", FLOAT(f));
+}
+
+void isetstr(variable *i)
+{
+       if (i->svalue == 0 || i->svalue == str_undef)
+               i->svalue = (char *)malloc(12);
+       snprintf(i->svalue, 12, "%d", INT(i));
+}
+
+variable *itostring(variable *v)
+{
+       switch (v->valtype) {
+       case INTEGER:
+               v->valtype = STRING;
+               isetstr(v);
+               break;
+       case FLOAT:
+               v->valtype = STRING;
+               fsetstr(v);
+               break;
+       }
+       return v;
+}
+
+variable *itoint(variable *v)
+{
+       switch (v->valtype) {
+       case STRING:
+               v->valtype = INTEGER;
+               INT(v) = atoi(v->svalue);
+               isetstr(v);
+               break;
+       case FLOAT:
+               v->valtype = INTEGER;
+               INT(v) = (int32_t)FLOAT(v);
+               isetstr(v);
+               break;
+       }
+       return v;
+}
+
+variable *itofloat(variable *v)
+{
+       switch (v->valtype) {
+       case STRING:
+               v->valtype = FLOAT;
+               FLOAT(v) = strtof(v->svalue, 0);
+               fsetstr(v);
+               break;
+       case INTEGER:
+               v->valtype = FLOAT;
+               FLOAT(v) = (float)INT(v);
+               fsetstr(v);
+               break;
+       }
+       return v;
+}
+
index 067ce138345f8dd4e6479d4528ee87d285f85287..82c6b2583cdc481c2a20a6bb0f7468c03f75137f 100644 (file)
@@ -3,6 +3,9 @@
 
 #include <stdint.h>
 
+#define INT(v)   (*((int32_t *)&v->value))
+#define FLOAT(v) (*((float *)&v->value))
+
 typedef struct {
        uint8_t used :1;
        uint8_t fromc :1;
@@ -18,4 +21,11 @@ enum valtype {
        FUNC
 };
 
+void isetstr(variable *i);
+void fsetstr(variable *f);
+
+variable *itostring(variable *v);
+variable *itoint(variable *v);
+variable *itofloat(variable *v);
+
 #endif // VARIABLE_H_