conditionals, returns, cleaner code

master
Clyne Sullivan 7 years ago
parent e3cbc8086c
commit 2b8cf5e771

@ -3,5 +3,10 @@ CC = gcc -m32
CFLAGS = -Wall -Wextra -Wno-strict-aliasing -I. -ggdb -fno-builtin CFLAGS = -Wall -Wextra -Wno-strict-aliasing -I. -ggdb -fno-builtin
all: all:
$(CC) $(CFLAGS) -c shelpers.c
$(CC) $(CFLAGS) -c parser.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

@ -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: Only a few commands are built in to the interpreter:
* set - set variables * set - set variables
* func/end - define functions * func/end - define functions
* jmp - jump to line * if/end - if conditional
* do/while
* ret - return value from function
Other features: Other features:
* function/variable defining in c * function/variable defining in c
* expression solving * expression solving
* no local variables
* whitespace hopefully ignored
Soon: Soon:
* conditionals
* error messages * 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. 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.

@ -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;
}

@ -0,0 +1,8 @@
#ifndef BUILTINS_H_
#define BUILTINS_H_
#include "parser.h"
void iload_core(interpreter *it);
#endif // BUILTINS_H_

167
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;
}

13
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_

@ -1,132 +1,41 @@
#include <parser.h> #include <parser.h>
#include "shelpers.h"
#include "builtins.h"
#include "stack.h"
#include "ops.h"
#include <ctype.h> #include <ctype.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define MAX_VARS 32 #define MAX_VARS 48
#define MAX_STACK 32 #define MAX_STACK 16
#define MAX_LINES 1000
#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;
}
void skipblank(const char *s, uint8_t (*cmp)(int), uint32_t *offset) char *str_func = "(func)";
{ char *str_undef = "(undefined)";
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); variable *idoexpr(interpreter *interp, const char *line);
variable *itostring(variable *v);
variable *itoint(variable *v);
variable *itofloat(variable *v);
void iinit(interpreter *interp) void iinit(interpreter *interp)
{ {
interp->vars = (variable *)calloc(MAX_VARS, sizeof(variable)); interp->vars = (variable *)malloc(MAX_VARS * sizeof(variable));
interp->vnames = (char **)calloc(MAX_VARS, sizeof(char *)); interp->vnames = (char **)malloc(MAX_VARS * sizeof(char *));
interp->stack = (stack_t *)calloc(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(20, sizeof(char *)); interp->lines = (char **)calloc(MAX_LINES, sizeof(char *));
interp->lnidx = 0; interp->lnidx = 0;
interp->indent = 0; interp->indent = 0;
inew_cfunc(interp, "set", ifunc_set); for (unsigned int i = 0; i < MAX_VARS; i++) {
inew_cfunc(interp, "jmp", ifunc_jmp); interp->vars[i].used = 0;
inew_cfunc(interp, "func", ifunc_label); interp->vnames[i] = 0;
inew_cfunc(interp, "end", ifunc_end); }
inew_cfunc(interp, "if", ifunc_if); for (unsigned int i = 0; i < MAX_LINES; i++)
inew_cfunc(interp, "do", ifunc_do); interp->lines[i] = 0;
inew_cfunc(interp, "while", ifunc_while);
}
void ipush(interpreter *it, void *v)
{
it->stack[it->stidx++] = v;
}
void *ipop(interpreter *it) iload_core(interp);
{
return it->stack[--it->stidx];
} }
variable *interpreter_get_variable(interpreter *interp, const char *name) variable *interpreter_get_variable(interpreter *interp, const char *name)
@ -270,22 +179,34 @@ int idoline(interpreter *interp, const char *line)
variable *ops[8]; variable *ops[8];
uint32_t ooffset, offset, next; uint32_t ooffset, offset, next;
if (line[0] == '\0')
return 0;
interp->lines[interp->lnidx] = strclone(line); interp->lines[interp->lnidx] = strclone(line);
loop: loop:
ooffset = 0;
offset = 0;
if (line[0] == '#') { if (line[0] == '#') {
goto norun; goto norun;
} else if (interp->indent > 0) { } else if (interp->indent > 0) {
if (!strcmp(line, "end")) skipblank(line, eol, &offset);
if (!strcmp(line + offset, "end"))
interp->indent--; interp->indent--;
goto norun; goto norun;
} }
ooffset = 0;
offset = 0;
// step 1 - convert to tokens // step 1 - convert to tokens
skipblank(line, eol, &offset); skipblank(line, eol, &offset);
while (!eol(line[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); ops[ooffset] = make_var(interp, line + offset, &next);
if (ops[ooffset] == 0) { if (ops[ooffset] == 0) {
return -4; return -4;
@ -303,23 +224,40 @@ loop:
if (ops[0]->valtype != FUNC) if (ops[0]->valtype != FUNC)
return -2; return -2;
if (ops[0]->value == 0) if (ops[0]->fromc && ops[0]->value == 0)
return -3; return -3;
for (uint32_t i = ooffset; --i > 0;)
ipush(interp, ops[i]);
if (ops[0]->fromc) { if (ops[0]->fromc) {
for (uint32_t i = ooffset; --i > 0;)
ipush(interp, ops[i]);
int ret = ((func_t)ops[0]->value)(interp); int ret = ((func_t)ops[0]->value)(interp);
if (ret != 0) if (ret != 0)
return ret; return ret;
ipopm(interp, ooffset - 1);
} else { } 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->lnidx = ops[0]->value;
} }
interp->stidx -= ooffset - 1;
if ((int32_t)interp->stidx < 0) { if ((int32_t)interp->stidx < 0) {
interp->stidx = 0; interp->stidx = 0;
return -5; return -5;
@ -340,36 +278,6 @@ norun:
return 0; 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 *idoexpr(interpreter *interp, const char *line)
{ {
variable *result = (variable *)malloc(sizeof(variable)); 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); ops[ooffset] = make_var(interp, line + offset, &next);
if (end != 0) if (end != 0)
mline[end] = cend; mline[end] = cend;
offset += next;
} }
if (ops[ooffset] == 0) if (ops[ooffset] == 0)
return 0; return 0;
ooffset++; ooffset++;
offset += next;
// skip whitespace // skip whitespace
skipblank(line, eoe, &offset); skipblank(line, eoe, &offset);
@ -464,290 +372,3 @@ 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)
{
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);
}

@ -13,6 +13,7 @@ typedef struct {
char **lines; char **lines;
uint32_t lnidx; uint32_t lnidx;
uint8_t indent; uint8_t indent;
variable *ret;
} interpreter; } interpreter;
typedef int (*func_t)(interpreter *); typedef int (*func_t)(interpreter *);
@ -26,9 +27,4 @@ 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);
int igetarg_integer(interpreter *, uint32_t);
float igetarg_float(interpreter *, uint32_t);
#endif // PARSER_H_ #endif // PARSER_H_

@ -1,5 +1,17 @@
func inc
set arg0 (arg0 + 1)
ret arg0
end
set a 0 set a 0
do do
put a inc a > a
set a (a+1) if ((a % 9) == 0)
while (a<5) put a
end
while (a < 100)
if (a == 100)
put "All good!"
end

@ -1,5 +1,7 @@
#include <parser.h> #include <parser.h>
#include "stack.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>

@ -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;
}

@ -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_

@ -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));
}

@ -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_

@ -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;
}

@ -3,6 +3,9 @@
#include <stdint.h> #include <stdint.h>
#define INT(v) (*((int32_t *)&v->value))
#define FLOAT(v) (*((float *)&v->value))
typedef struct { typedef struct {
uint8_t used :1; uint8_t used :1;
uint8_t fromc :1; uint8_t fromc :1;
@ -18,4 +21,11 @@ enum valtype {
FUNC FUNC
}; };
void isetstr(variable *i);
void fsetstr(variable *f);
variable *itostring(variable *v);
variable *itoint(variable *v);
variable *itofloat(variable *v);
#endif // VARIABLE_H_ #endif // VARIABLE_H_

Loading…
Cancel
Save