indent fixes, nested conditionals

master
Clyne Sullivan 7 years ago
parent 1d092d70a3
commit 5d85baa270

1
.gitignore vendored

@ -1,2 +1,3 @@
shell shell
*.o *.o
libinterp.a

@ -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: all:
$(CC) $(CFLAGS) -c shelpers.c $(CC) $(CFLAGS) -c shelpers.c
@ -9,4 +12,6 @@ all:
$(CC) $(CFLAGS) -c stack.c $(CC) $(CFLAGS) -c stack.c
$(CC) $(CFLAGS) -c ops.c $(CC) $(CFLAGS) -c ops.c
$(CC) $(CFLAGS) -c variable.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

@ -1,7 +1,11 @@
#include "builtins.h" #include "builtins.h"
#include "stack.h" #include "stack.h"
#include "shelpers.h"
#include <stdlib.h>
extern char *str_func; extern char *str_func;
extern char *str_undef;
int ifunc_set(interpreter *it); int ifunc_set(interpreter *it);
int ifunc_label(interpreter *it); int ifunc_label(interpreter *it);
@ -11,6 +15,14 @@ int ifunc_do(interpreter *it);
int ifunc_while(interpreter *it); int ifunc_while(interpreter *it);
int ifunc_ret(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) void iload_core(interpreter *interp)
{ {
inew_cfunc(interp, "set", ifunc_set); inew_cfunc(interp, "set", ifunc_set);
@ -32,7 +44,9 @@ int ifunc_set(interpreter *it)
n->valtype = v->valtype; n->valtype = v->valtype;
n->value = v->value; 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; return 0;
} }
@ -46,25 +60,26 @@ int ifunc_label(interpreter *it)
n->valtype = FUNC; n->valtype = FUNC;
n->value = it->lnidx; n->value = it->lnidx;
n->svalue = str_func; n->svalue = str_func;
it->indent++; iskip(it);
return 0; return 0;
} }
int ifunc_if(interpreter *it) int ifunc_if(interpreter *it)
{ {
int v = igetarg_integer(it, 0); int v = igetarg_integer(it, 0);
if (v == 0) { if (v == 0)
it->indent++; iskip(it);
} else { void *tmp = ipop(it);
void *tmp = ipop(it); ipush(it, (void *)-1);
ipush(it, (void *)-1); ipush(it, tmp);
ipush(it, tmp);
}
return 0; return 0;
} }
int ifunc_end(interpreter *it) int ifunc_end(interpreter *it)
{ {
if (it->stidx == 0)
return 0;
uint32_t lnidx = (uint32_t)ipop(it) + 1; uint32_t lnidx = (uint32_t)ipop(it) + 1;
if (lnidx != 0) if (lnidx != 0)
it->lnidx = lnidx; it->lnidx = lnidx;
@ -83,8 +98,8 @@ int ifunc_while(interpreter *it)
ipop(it); ipop(it);
int nidx = (int)ipop(it); int nidx = (int)ipop(it);
if (c != 0) { if (c != 0) {
ipush(it, (void *)nidx); //ipush(it, (void *)nidx);
it->lnidx = nidx; it->lnidx = nidx - 1;
} }
ipush(it, 0); ipush(it, 0);
return 0; return 0;

@ -3,6 +3,12 @@
#include "parser.h" #include "parser.h"
#define IUP_COUNT 3
#define IDOWN_COUNT 2
void iload_core(interpreter *it); void iload_core(interpreter *it);
const func_t indent_up[IUP_COUNT];
const func_t indent_down[IDOWN_COUNT];
#endif // BUILTINS_H_ #endif // BUILTINS_H_

@ -7,6 +7,7 @@
#include <ctype.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#define MAX_VARS 48 #define MAX_VARS 48
@ -24,9 +25,10 @@ void iinit(interpreter *interp)
interp->vnames = (char **)malloc(MAX_VARS * sizeof(char *)); interp->vnames = (char **)malloc(MAX_VARS * sizeof(char *));
interp->stack = (stack_t *)malloc(MAX_STACK * sizeof(stack_t)); interp->stack = (stack_t *)malloc(MAX_STACK * sizeof(stack_t));
interp->stidx = 0; interp->stidx = 0;
interp->lines = (char **)calloc(MAX_LINES, sizeof(char *)); interp->lines = (variable ***)malloc(MAX_LINES * sizeof(variable **));
interp->lnidx = 0; interp->lnidx = 0;
interp->indent = 0; interp->indent = 0;
interp->sindent = 0;
for (unsigned int i = 0; i < MAX_VARS; i++) { for (unsigned int i = 0; i < MAX_VARS; i++) {
interp->vars[i].used = 0; interp->vars[i].used = 0;
@ -38,6 +40,30 @@ void iinit(interpreter *interp)
iload_core(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) variable *interpreter_get_variable(interpreter *interp, const char *name)
{ {
for (uint32_t i = 0; i < MAX_VARS; i++) { for (uint32_t i = 0; i < MAX_VARS; i++) {
@ -66,7 +92,7 @@ char *interpreter_get_name(interpreter *interp, variable *v)
return str_undef; 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); variable *v = interpreter_get_variable(interp, name);
if (v != 0) { if (v != 0) {
@ -74,9 +100,10 @@ void inew_string(interpreter *interp, const char *name, char *value)
INT(v) = 0; INT(v) = 0;
v->svalue = strclone(value); 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); variable *v = interpreter_get_variable(interp, name);
if (v != 0) { if (v != 0) {
@ -84,9 +111,10 @@ void inew_integer(interpreter *interp, const char *name, int32_t value)
INT(v) = value; INT(v) = value;
isetstr(v); 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); variable *v = interpreter_get_variable(interp, name);
if (v != 0) { if (v != 0) {
@ -94,6 +122,7 @@ void inew_float(interpreter *interp, const char *name, float value)
FLOAT(v) = value; FLOAT(v) = value;
fsetstr(v); fsetstr(v);
} }
return v;
} }
void inew_cfunc(interpreter *interp, const char *name, func_t func) 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])) if (!eot(line[end + 1]))
return 0; return 0;
// TODO string breakdown // 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; *next = end + 1;
return v; return vmake(0, STRING, strnclone(line + 1, end - 1));
} }
end++; end++;
} }
@ -131,7 +156,8 @@ variable *make_var(interpreter *interp, const char *line, uint32_t *next)
if (eot(line[end])) if (eot(line[end]))
return 0; return 0;
*next = end + 1; *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 } else if (isalpha(line[0])) { // variable/func
uint32_t end = 1; uint32_t end = 1;
for (; isalnum(line[end]); end++); for (; isalnum(line[end]); end++);
@ -141,7 +167,9 @@ variable *make_var(interpreter *interp, const char *line, uint32_t *next)
strncpy(name, line, end); strncpy(name, line, end);
name[end] = '\0'; name[end] = '\0';
*next = end; *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 } else if (isdigit(line[0])) { // number
uint32_t end = 1; uint32_t end = 1;
uint8_t dec = 0; 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)); variable *v;
v->used = 0;
if (dec) { if (dec) {
v->valtype = FLOAT; v = vmakef(strtof(line, 0));
FLOAT(v) = strtof(line, 0); } else
fsetstr(v); v = vmake(0, INTEGER, (void *)atoi(line));
} else {
v->valtype = INTEGER;
INT(v) = atoi(line);
isetstr(v);
}
*next = end; *next = end;
return v; return v;
} }
@ -176,39 +198,34 @@ variable *make_var(interpreter *interp, const char *line, uint32_t *next)
int idoline(interpreter *interp, const char *line) int idoline(interpreter *interp, const char *line)
{ {
variable *ops[8]; uint32_t ooffset = 0, offset = 0, next;
uint32_t ooffset, offset, next; int fret = 0;
if (line[0] == '\0') if (line[0] == '\0')
return 0; return 0;
interp->lines[interp->lnidx] = strclone(line);
loop:
ooffset = 0;
offset = 0;
skipblank(line, eol, &offset); skipblank(line, eol, &offset);
if (line[offset] == '#')
return 0;
if (line[offset] == '#') { interp->lines[interp->lnidx] = (variable **)calloc(8, sizeof(variable *));
goto norun; variable **ops = interp->lines[interp->lnidx];
} else if (interp->indent > 0) {
if (!strcmp(line + offset, "end"))
interp->indent--;
goto norun;
}
// step 1 - convert to tokens // step 1 - convert to tokens
while (!eol(line[offset])) { while (!eol(line[offset])) {
if (offset > 0 && line[offset] == '>') { if (offset > 0 && line[offset] == '>') {
offset++; offset++;
skipblank(line, eol, &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; offset += next;
skipblank(line, eol, &offset); skipblank(line, eol, &offset);
continue; continue;
} }
ops[ooffset] = make_var(interp, line + offset, &next); ops[ooffset] = make_var(interp, line + offset, &next);
if (ops[ooffset] == 0) { if (ops[ooffset] == 0) {
return -4; fret = -4;
goto fail;
} else { } else {
ooffset++; ooffset++;
offset += next; offset += next;
@ -217,14 +234,61 @@ loop:
} }
// step 2 - execute // step 2 - execute
if (ooffset == 0) if (ooffset == 0) {
return -1; fret = -1;
goto fail;
}
if (ops[0]->valtype != FUNC) {
fret = -2;
goto fail;
}
if (ops[0]->valtype != FUNC) if (ops[0]->fromc && ops[0]->value == 0) {
return -2; fret = -3;
goto fail;
}
if (ops[0]->fromc && ops[0]->value == 0) if (ops[ooffset] != (void *)-1)
return -3; 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) { if (ops[0]->fromc) {
for (uint32_t i = ooffset; --i > 0;) for (uint32_t i = ooffset; --i > 0;)
@ -237,7 +301,7 @@ loop:
} else { } else {
char an[6]; char an[6];
for (uint32_t i = 1; i < ooffset; i++) { 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) { switch (ops[i]->valtype) {
case STRING: case STRING:
inew_string(interp, an, ops[i]->svalue); inew_string(interp, an, ops[i]->svalue);
@ -255,26 +319,35 @@ loop:
ipush(interp, (void *)(interp->lnidx)); ipush(interp, (void *)(interp->lnidx));
interp->lnidx = ops[0]->value; interp->lnidx = ops[0]->value;
interp->indent++;
} }
if (ops[ooffset] == (void *)-1)
interp->ret = ops[ooffset + 1];
if ((int32_t)interp->stidx < 0) { if ((int32_t)interp->stidx < 0) {
interp->stidx = 0; interp->stidx = 0;
return -5; return -5;
} }
for (uint32_t i = 0; i < ooffset; i++) { for (uint32_t i = 1; i < ooffset; i++) {
if (!ops[i]->used) if (ops[i] != interp->lines[oldLnidx][i]) {
free(ops[i]->svalue);
free(ops[i]); free(ops[i]);
}
} }
free(ops);
norun: norun:
interp->lnidx++; interp->lnidx++;
if (interp->lines[interp->lnidx] != 0) { if (interp->lines[interp->lnidx] != 0)
line = interp->lines[interp->lnidx];
goto loop; goto loop;
}
return 0; return 0;
fail:
free(interp->lines[interp->lnidx]);
interp->lines[interp->lnidx] = 0;
return fret;
} }
variable *idoexpr(interpreter *interp, const char *line) 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) { 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]); free(ops[i]);
}
} }
result->used = 0;
result->svalue = 0;
if (result->valtype == INTEGER) if (result->valtype == INTEGER)
isetstr(result); isetstr(result);
else else

@ -10,19 +10,25 @@ typedef struct {
char **vnames; char **vnames;
stack_t *stack; stack_t *stack;
uint32_t stidx; uint32_t stidx;
char **lines; variable ***lines;
uint32_t lnidx; uint32_t lnidx;
uint8_t indent; int8_t indent;
uint8_t sindent;
variable *ret; variable *ret;
} interpreter; } interpreter;
#define SKIP (1 << 7)
typedef int (*func_t)(interpreter *); typedef int (*func_t)(interpreter *);
void iinit(interpreter *); void iinit(interpreter *);
void iend(interpreter *it);
void iskip(interpreter *it);
void inew_string(interpreter *, const char *, char *); variable *inew_string(interpreter *, const char *, char *);
void inew_integer(interpreter *, const char *, int32_t); variable *inew_integer(interpreter *, const char *, int32_t);
void inew_float(interpreter *, const char *, float); variable *inew_float(interpreter *, const char *, float);
void inew_cfunc(interpreter *, const char *, func_t); void inew_cfunc(interpreter *, const char *, func_t);
int idoline(interpreter *, const char *); int idoline(interpreter *, const char *);

@ -1,17 +1,18 @@
func inc func divisible
set arg0 (arg0 + 1) if (arg1 == 0)
ret arg0 ret 0
end
ret (arg0 % arg1)
end end
set a 0 set a 0
set b 4
do do
inc a > a set a (a + 1)
if ((a % 9) == 0) divisible a b > i
put a if (i == 0)
print a
end end
while (a < 100) while (a < 100)
if (a == 100) print "All done!"
put "All good!"
end

@ -59,7 +59,7 @@ int main(int argc, char **argv)
} }
iinit(&interp); iinit(&interp);
inew_cfunc(&interp, "put", s_put); inew_cfunc(&interp, "print", s_put);
inew_cfunc(&interp, "tp", s_type); inew_cfunc(&interp, "tp", s_type);
inew_cfunc(&interp, "q", quit); inew_cfunc(&interp, "q", quit);
@ -75,5 +75,6 @@ int main(int argc, char **argv)
} }
fclose(fp); fclose(fp);
iend(&interp);
return 0; return 0;
} }

@ -14,6 +14,7 @@ char *strnclone(const char *s, uint32_t n)
{ {
char *clone = (char *)malloc(n + 1); char *clone = (char *)malloc(n + 1);
strncpy(clone, s, n); strncpy(clone, s, n);
clone[n] = '\0';
return clone; return clone;
} }

@ -5,6 +5,47 @@
#include <stdlib.h> #include <stdlib.h>
extern char *str_undef; 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) void fsetstr(variable *f)
{ {
@ -17,7 +58,7 @@ void isetstr(variable *i)
{ {
if (i->svalue == 0 || i->svalue == str_undef) if (i->svalue == 0 || i->svalue == str_undef)
i->svalue = (char *)malloc(12); i->svalue = (char *)malloc(12);
snprintf(i->svalue, 12, "%d", INT(i)); snprintf(i->svalue, 12, "%d", (int)INT(i));
} }
variable *itostring(variable *v) variable *itostring(variable *v)

@ -9,7 +9,7 @@
typedef struct { typedef struct {
uint8_t used :1; uint8_t used :1;
uint8_t fromc :1; uint8_t fromc :1;
uint8_t valtype :2; uint8_t valtype :4;
uint32_t value; uint32_t value;
char *svalue; char *svalue;
} variable; } variable;
@ -18,9 +18,13 @@ enum valtype {
STRING = 0, STRING = 0,
INTEGER, INTEGER,
FLOAT, FLOAT,
FUNC FUNC,
EXPR
}; };
variable *vmake(uint8_t fromc, uint8_t valtype, void *value);
variable *vmakef(float value);
void isetstr(variable *i); void isetstr(variable *i);
void fsetstr(variable *f); void fsetstr(variable *f);

Loading…
Cancel
Save