aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile11
-rw-r--r--builtins.c37
-rw-r--r--builtins.h6
-rw-r--r--parser.c183
-rw-r--r--parser.h16
-rw-r--r--script21
-rw-r--r--shell.c3
-rw-r--r--shelpers.c1
-rw-r--r--variable.c43
-rw-r--r--variable.h8
11 files changed, 245 insertions, 85 deletions
diff --git a/.gitignore b/.gitignore
index 6a2f0f7..fc79a9e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
shell
*.o
+libinterp.a
diff --git a/Makefile b/Makefile
index f81b589..1d66f11 100644
--- 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
diff --git a/builtins.c b/builtins.c
index cda7a93..c77c8b9 100644
--- a/builtins.c
+++ b/builtins.c
@@ -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;
diff --git a/builtins.h b/builtins.h
index 8739778..91c6e8c 100644
--- a/builtins.h
+++ b/builtins.h
@@ -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_
diff --git a/parser.c b/parser.c
index ac739a0..b100123 100644
--- 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
diff --git a/parser.h b/parser.h
index 4e4699e..92a8eb3 100644
--- 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 3b807a2..dac7da5 100644
--- 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 0c0c4df..c63b1bc 100644
--- 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;
}
diff --git a/shelpers.c b/shelpers.c
index 0d2da24..fbde4ab 100644
--- a/shelpers.c
+++ b/shelpers.c
@@ -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;
}
diff --git a/variable.c b/variable.c
index 727ca0c..620a4b6 100644
--- a/variable.c
+++ b/variable.c
@@ -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)
diff --git a/variable.h b/variable.h
index 82c6b25..e5aa20c 100644
--- a/variable.h
+++ b/variable.h
@@ -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);