jumps and functions

master
Clyne Sullivan 7 years ago
parent 3b6bcc0e6e
commit 0c3901b3a8

@ -27,6 +27,9 @@ char *strnclone(const char *s, uint32_t n)
} }
void ifunc_set(interpreter *it); void ifunc_set(interpreter *it);
void ifunc_jmp(interpreter *it);
void ifunc_label(interpreter *it);
void ifunc_end(interpreter *it);
variable *idoexpr(interpreter *interp, const char *line); variable *idoexpr(interpreter *interp, const char *line);
@ -40,8 +43,24 @@ void iinit(interpreter *interp)
interp->vnames = (char **)calloc(MAX_VARS, sizeof(char *)); interp->vnames = (char **)calloc(MAX_VARS, sizeof(char *));
interp->stack = (stack_t *)calloc(MAX_STACK, sizeof(stack_t)); interp->stack = (stack_t *)calloc(MAX_STACK, sizeof(stack_t));
interp->stidx = 0; interp->stidx = 0;
interp->lines = (char **)calloc(20, sizeof(char *));
interp->lnidx = 0;
interp->indent = 0;
inew_cfunc(interp, "set", ifunc_set); inew_cfunc(interp, "set", ifunc_set);
inew_cfunc(interp, "jmp", ifunc_jmp);
inew_cfunc(interp, "func", ifunc_label);
inew_cfunc(interp, "end", ifunc_end);
}
void ipush(interpreter *it, void *v)
{
it->stack[it->stidx++] = v;
}
void *ipop(interpreter *it)
{
return it->stack[--it->stidx];
} }
variable *interpreter_get_variable(interpreter *interp, const char *name) variable *interpreter_get_variable(interpreter *interp, const char *name)
@ -193,9 +212,20 @@ 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]; variable *ops[8];
uint32_t ooffset = 0; uint32_t ooffset, offset, next;
uint32_t offset = 0;
uint32_t next; interp->lines[interp->lnidx] = strclone(line);
loop:
if (line[0] == '`') {
goto norun;
} else if (interp->indent > 0) {
if (!strcmp(line, "end"))
interp->indent--;
goto norun;
}
ooffset = 0;
offset = 0;
// step 1 - convert to tokens // step 1 - convert to tokens
while (!eol(line[offset])) { while (!eol(line[offset])) {
@ -221,11 +251,29 @@ int idoline(interpreter *interp, const char *line)
if (ops[0]->value == 0) if (ops[0]->value == 0)
return -3; return -3;
for (uint32_t i = 0; i < ooffset - 1; i++, interp->stidx++) for (uint32_t i = ooffset; --i > 0;)
interp->stack[i] = ops[i + 1]; ipush(interp, ops[i]);
((func_t)ops[0]->value)(interp); if (ops[0]->fromc) {
interp->stidx = 0; ((func_t)ops[0]->value)(interp);
} else {
ipush(interp, (void *)(interp->lnidx + 1));
interp->lnidx = ops[0]->value;
}
interp->stidx -= ooffset - 1;
if ((int32_t)interp->stidx < 0) {
interp->stidx = 0;
return -5;
}
norun:
interp->lnidx++;
if (interp->lines[interp->lnidx] != 0) {
line = interp->lines[interp->lnidx];
goto loop;
}
return 0; return 0;
} }
@ -318,25 +366,35 @@ variable *idoexpr(interpreter *interp, const char *line)
return &result; return &result;
} }
variable *igetarg(interpreter *interp, uint32_t index)
{
return interp->stack[interp->stidx - index - 1];
}
char *igetarg_string(interpreter *interp, uint32_t index) char *igetarg_string(interpreter *interp, uint32_t index)
{ {
if (index >= interp->stidx) if (index >= interp->stidx)
return 0; return 0;
return STR(itostring(interp->stack[index])); variable *v = igetarg(interp, index);
if (v->valtype == FUNC)
return "(func)";
return STR(itostring(v));
} }
int igetarg_integer(interpreter *interp, uint32_t index) int igetarg_integer(interpreter *interp, uint32_t index)
{ {
if (index >= interp->stidx) if (index >= interp->stidx)
return 0; return 0;
return INT(itoint(interp->stack[index])); variable *v = igetarg(interp, index);
return INT(itoint(v));
} }
float igetarg_float(interpreter *interp, uint32_t index) float igetarg_float(interpreter *interp, uint32_t index)
{ {
if (index >= interp->stidx) if (index >= interp->stidx)
return 0; return 0;
return FLOAT(itofloat(interp->stack[index])); variable *v = igetarg(interp, index);
return FLOAT(itofloat(v));
} }
variable *itostring(variable *v) variable *itostring(variable *v)
@ -423,16 +481,36 @@ float iget_float(interpreter *, const char *)
void ifunc_set(interpreter *it) void ifunc_set(interpreter *it)
{ {
if (it->stidx != 2) variable *n = igetarg(it, 0);
return; variable *v = igetarg(it, 1);
variable *n = (variable *)it->stack[0];
variable *v = (variable *)it->stack[1];
n->valtype = v->valtype; n->valtype = v->valtype;
n->value = v->value; n->value = v->value;
} }
void ifunc_label(interpreter *it)
{
variable *n = igetarg(it, 0);
n->valtype = FUNC;
n->value = it->lnidx;
it->indent++;
}
void ifunc_end(interpreter *it)
{
if (it->stidx > 0) {
uint32_t line = (uint32_t)ipop(it);
it->lnidx = line - 1;
}
}
void ifunc_jmp(interpreter *it)
{
int newidx = igetarg_integer(it, 0);
it->lnidx = newidx - 1;
}
/** /**
* Builtin operations * Builtin operations
*/ */

@ -10,6 +10,9 @@ typedef struct {
char **vnames; char **vnames;
stack_t *stack; stack_t *stack;
uint32_t stidx; uint32_t stidx;
char **lines;
uint32_t lnidx;
uint8_t indent;
} interpreter; } interpreter;
typedef void (*func_t)(interpreter *); typedef void (*func_t)(interpreter *);
@ -23,6 +26,7 @@ void inew_cfunc(interpreter *, const char *, func_t);
int idoline(interpreter *, const char *); int idoline(interpreter *, const char *);
variable *igetarg(interpreter *, uint32_t);
char *igetarg_string(interpreter *, uint32_t); char *igetarg_string(interpreter *, uint32_t);
int igetarg_integer(interpreter *, uint32_t); int igetarg_integer(interpreter *, uint32_t);
float igetarg_float(interpreter *, uint32_t); float igetarg_float(interpreter *, uint32_t);

@ -14,8 +14,6 @@ void s_put(interpreter *it)
void s_type(interpreter *it) void s_type(interpreter *it)
{ {
if (it->stidx != 1)
return;
variable *v = (variable *)it->stack[0]; variable *v = (variable *)it->stack[0];
switch (v->valtype) { switch (v->valtype) {
case STRING: case STRING:
@ -56,6 +54,7 @@ int main()
unsigned int size; unsigned int size;
int result; int result;
while (1) { while (1) {
printf("%d> ", interp.lnidx);
getline(&line, &size, stdin); getline(&line, &size, stdin);
*strchr(line, '\n') = '\0'; *strchr(line, '\n') = '\0';
result = idoline(&interp, line); result = idoline(&interp, line);

Loading…
Cancel
Save