need to sync with desktop
parent
12fa2716db
commit
025ed8530c
@ -1,24 +1,21 @@
|
|||||||
#ifndef TOKEN_H_
|
#ifndef VARIABLE_H_
|
||||||
#define TOKEN_H_
|
#define VARIABLE_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t nameidx;
|
uint8_t used :1;
|
||||||
uint8_t type;
|
uint8_t fromc :1;
|
||||||
uint8_t info;
|
uint8_t valtype :2;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
|
char *svalue;
|
||||||
} variable;
|
} variable;
|
||||||
|
|
||||||
#define INFO_ARGS(x) ((x) & 0x07)
|
enum valtype {
|
||||||
#define INFO_RET (1 << 3)
|
STRING = 0,
|
||||||
|
INTEGER,
|
||||||
enum vartype {
|
FLOAT,
|
||||||
VALUE = 0,
|
FUNC
|
||||||
VARIABLE,
|
|
||||||
OPERATOR,
|
|
||||||
FUNCTION,
|
|
||||||
CFUNCTION
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TOKEN_H_
|
#endif // VARIABLE_H_
|
||||||
|
@ -1,228 +1,716 @@
|
|||||||
#include <parser.h>
|
#include <parser.h>
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <heap.h>
|
#include <heap.h>
|
||||||
|
|
||||||
#define MAX_VAR 8
|
#include <ctype.h>
|
||||||
#define MAX_STACK 8
|
#include <string.h>
|
||||||
|
|
||||||
static const char *interpreter_operators = "=(";
|
extern int atoi(char *);
|
||||||
|
float strtof(char *s, char **e)
|
||||||
|
{ (void)s; (void)e; return 0;}
|
||||||
|
#include <stdarg.h>
|
||||||
|
extern int ksnprintf(char *, int, const char *, ...);
|
||||||
|
|
||||||
bool strcmp(const char *a, const char *b)
|
#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));
|
||||||
|
strcpy(clone, s);
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *strnclone(const char *s, uint32_t n)
|
||||||
{
|
{
|
||||||
int i = 0;
|
char *clone = (char *)malloc(n);
|
||||||
for (; a[i] == b[i] && a[i] != '\0'; i++);
|
strncpy(clone, s, n);
|
||||||
return a[i] == b[i];
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool strncmp(const char *a, const char *b, int count)
|
void fsetstr(variable *f)
|
||||||
{
|
{
|
||||||
int i = 0;
|
if (f->svalue == 0)
|
||||||
for (; a[i] == b[i] && i < count; i++);
|
f->svalue = (char *)malloc(16);
|
||||||
return i == count;
|
ksnprintf(f->svalue, 16, "%f", FLOAT(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t isalpha(char c)
|
void isetstr(variable *i)
|
||||||
{
|
{
|
||||||
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
|
if (i->svalue == 0)
|
||||||
|
i->svalue = (char *)malloc(12);
|
||||||
|
ksnprintf(i->svalue, 12, "%ld", INT(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t isnum(char c)
|
uint8_t eol(int c)
|
||||||
{
|
{
|
||||||
return (c >= '0' && c <= '9');
|
return c == '\n' || c == '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t isname(char c)
|
uint8_t eot(int c)
|
||||||
{
|
{
|
||||||
return isalpha(c) || isnum(c);
|
return eol(c) || c == ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t isspace(char c)
|
uint8_t eoe(int c)
|
||||||
{
|
{
|
||||||
return (c == ' ' || c == '\t' || c == '\n');
|
return eol(c) || c == ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t isoper(char c)
|
uint32_t findend(const char *s, char o, char c)
|
||||||
{
|
{
|
||||||
for (uint8_t i = 0; i < sizeof(interpreter_operators); i++) {
|
uint8_t indent = 0;
|
||||||
if (c == interpreter_operators[i])
|
uint32_t i;
|
||||||
return 1;
|
for (i = 1; !eol(s[i]); i++) {
|
||||||
|
if (s[i] == o) {
|
||||||
|
indent++;
|
||||||
|
} else if (s[i] == c) {
|
||||||
|
if (indent == 0)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
indent--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void interpreter_init(interpreter *interp)
|
int ifunc_set(interpreter *it);
|
||||||
|
int ifunc_jmp(interpreter *it);
|
||||||
|
int ifunc_label(interpreter *it);
|
||||||
|
int ifunc_end(interpreter *it);
|
||||||
|
|
||||||
|
variable *idoexpr(interpreter *interp, const char *line);
|
||||||
|
|
||||||
|
variable *itostring(variable *v);
|
||||||
|
variable *itoint(variable *v);
|
||||||
|
variable *itofloat(variable *v);
|
||||||
|
|
||||||
|
void iinit(interpreter *interp)
|
||||||
{
|
{
|
||||||
interp->status = READY;
|
interp->vars = (variable *)calloc(MAX_VARS, sizeof(variable));
|
||||||
interp->vcount = 0;
|
interp->vnames = (char **)calloc(MAX_VARS, sizeof(char *));
|
||||||
interp->vars = (variable *)hcalloc(MAX_VAR, sizeof(variable));
|
interp->stack = (stack_t *)calloc(MAX_STACK, sizeof(stack_t));
|
||||||
interp->names = (char **)hcalloc(MAX_VAR, sizeof(char *));
|
interp->stidx = 0;
|
||||||
interp->stack = (stack_t *)hcalloc(MAX_STACK, sizeof(stack_t));
|
interp->lines = (char **)calloc(20, 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void interpreter_define_value(interpreter *interp, const char *name, int32_t value)
|
void ipush(interpreter *it, void *v)
|
||||||
{
|
{
|
||||||
interp->names[interp->vcount] = (char *)name;
|
it->stack[it->stidx++] = v;
|
||||||
interp->vars[interp->vcount].nameidx = interp->vcount;
|
|
||||||
interp->vars[interp->vcount].type = VALUE;
|
|
||||||
interp->vars[interp->vcount].value = (uint32_t)value;
|
|
||||||
interp->vcount++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void interpreter_define_cfunc(interpreter *interp, const char *name, func_t addr)
|
void *ipop(interpreter *it)
|
||||||
{
|
{
|
||||||
interp->names[interp->vcount] = (char *)name;
|
return it->stack[--it->stidx];
|
||||||
interp->vars[interp->vcount].nameidx = interp->vcount;
|
|
||||||
interp->vars[interp->vcount].type = CFUNCTION;
|
|
||||||
interp->vars[interp->vcount].value = (uint32_t)addr;
|
|
||||||
interp->vcount++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t interpreter_get_value(interpreter *interp, const char *name)
|
variable *interpreter_get_variable(interpreter *interp, const char *name)
|
||||||
{
|
{
|
||||||
for (uint16_t i = 0; i < interp->vcount; i++) {
|
for (uint32_t i = 0; i < MAX_VARS; i++) {
|
||||||
if (!strcmp(interp->names[i], name))
|
if (!interp->vars[i].used) {
|
||||||
return (int32_t)interp->vars[i].value;
|
variable *v = &interp->vars[i];
|
||||||
|
v->used = 1;
|
||||||
|
v->fromc = 0;
|
||||||
|
v->valtype = STRING;
|
||||||
|
v->value = 0;
|
||||||
|
v->svalue = str_undef;
|
||||||
|
interp->vnames[i] = strclone(name);
|
||||||
|
return v;
|
||||||
|
} else if (interp->vnames[i] != 0 && !strcmp(interp->vnames[i], name)) {
|
||||||
|
return &interp->vars[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
char *interpreter_get_name(interpreter *interp, variable *v)
|
||||||
* doline section
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool namencmp(const char *name, const char *s)
|
|
||||||
{
|
{
|
||||||
uint16_t i;
|
for (uint32_t i = 0; i < MAX_VARS; i++) {
|
||||||
for (i = 0; name[i] == s[i] && s[i] != '\0'; i++);
|
if (v == &interp->vars[i])
|
||||||
return (name[i] == '\0' && !isname(s[i]));
|
return interp->vnames[i];
|
||||||
|
}
|
||||||
|
return str_undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t spacecount(const char *s)
|
void inew_string(interpreter *interp, const char *name, char *value)
|
||||||
{
|
{
|
||||||
uint16_t i;
|
variable *v = interpreter_get_variable(interp, name);
|
||||||
for (i = 0; isspace(s[i]); i++);
|
if (v != 0) {
|
||||||
return i;
|
v->valtype = STRING;
|
||||||
|
INT(v) = 0;
|
||||||
|
v->svalue = strclone(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *copystr(const char *s, char end)
|
void inew_integer(interpreter *interp, const char *name, int32_t value)
|
||||||
{
|
{
|
||||||
uint16_t len = 0;
|
variable *v = interpreter_get_variable(interp, name);
|
||||||
while (s[len++] != end);
|
if (v != 0) {
|
||||||
char *buf = (char *)hmalloc(len);
|
v->valtype = INTEGER;
|
||||||
for (uint16_t i = 0; i < len; i++)
|
INT(v) = value;
|
||||||
buf[i] = s[i];
|
isetstr(v);
|
||||||
return buf;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *copysubstr(const char *s, int end)
|
void inew_float(interpreter *interp, const char *name, float value)
|
||||||
{
|
{
|
||||||
char *buf = (char *)hmalloc(end);
|
variable *v = interpreter_get_variable(interp, name);
|
||||||
for (uint16_t i = 0; i < end; i++)
|
if (v != 0) {
|
||||||
buf[i] = s[i];
|
v->valtype = FLOAT;
|
||||||
return buf;
|
FLOAT(v) = value;
|
||||||
|
fsetstr(v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable *interpreter_getvar(interpreter *interp, const char *line)
|
void inew_cfunc(interpreter *interp, const char *name, func_t func)
|
||||||
{
|
{
|
||||||
for (uint16_t i = 0; i < interp->vcount; i++) {
|
variable *v = interpreter_get_variable(interp, name);
|
||||||
if (namencmp(interp->names[i], line))
|
if (v != 0) {
|
||||||
return &interp->vars[i];
|
v->fromc = 1;
|
||||||
|
v->valtype = FUNC;
|
||||||
|
v->value = (uint32_t)func;
|
||||||
|
v->svalue = str_func;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable *make_var(interpreter *interp, const char *line, uint32_t *next)
|
||||||
|
{
|
||||||
|
if (line[0] == '\"') { // string literal
|
||||||
|
uint32_t end = 1;
|
||||||
|
while (!eol(line[end])) {
|
||||||
|
if (line[end] == '\"'/* && line[end - 1] != '\\'*/) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
end++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} else if (line[0] == '(') { // equation literal
|
||||||
|
uint32_t end = findend(line, '(', ')');
|
||||||
|
if (eot(line[end]))
|
||||||
|
return 0;
|
||||||
|
*next = end + 1;
|
||||||
|
return idoexpr(interp, line + 1);
|
||||||
|
} else if (isalpha(line[0])) { // variable/func
|
||||||
|
uint32_t end = 1;
|
||||||
|
for (; isalnum(line[end]); end++);
|
||||||
|
if (!eot(line[end]))
|
||||||
|
return 0;
|
||||||
|
char *name = (char *)malloc(end + 1);
|
||||||
|
strncpy(name, line, end);
|
||||||
|
name[end] = '\0';
|
||||||
|
*next = end;
|
||||||
|
return interpreter_get_variable(interp, name);
|
||||||
|
} else if (isdigit(line[0])) { // number
|
||||||
|
uint32_t end = 1;
|
||||||
|
uint8_t dec = 0;
|
||||||
|
for (; !eot(line[end]); end++) {
|
||||||
|
if (!isdigit(line[end])) {
|
||||||
|
if (line[end] == '.') {
|
||||||
|
if (!dec)
|
||||||
|
dec = 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
variable *v = (variable *)malloc(sizeof(variable));
|
||||||
|
v->used = 0;
|
||||||
|
if (dec) {
|
||||||
|
v->valtype = FLOAT;
|
||||||
|
FLOAT(v) = strtof(line, 0);
|
||||||
|
fsetstr(v);
|
||||||
|
} else {
|
||||||
|
v->valtype = INTEGER;
|
||||||
|
INT(v) = atoi(line);
|
||||||
|
isetstr(v);
|
||||||
|
}
|
||||||
|
*next = end;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int interpreter_doline(interpreter *interp, const char *line)
|
int idoline(interpreter *interp, const char *line)
|
||||||
{
|
{
|
||||||
variable *bits[16];
|
variable *ops[8];
|
||||||
uint16_t offset = 0, boffset = 0;
|
uint32_t ooffset, offset, 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;
|
||||||
|
}
|
||||||
|
|
||||||
// check for var/func set or usage
|
ooffset = 0;
|
||||||
int end;
|
offset = 0;
|
||||||
getvar:
|
|
||||||
for (end = 0; isname(line[end]); end++);
|
// step 1 - convert to tokens
|
||||||
variable *var = interpreter_getvar(interp, line);
|
while (!eol(line[offset])) {
|
||||||
|
ops[ooffset] = make_var(interp, line + offset, &next);
|
||||||
|
if (ops[ooffset] == 0) {
|
||||||
|
return -4;
|
||||||
|
} else {
|
||||||
|
ooffset++;
|
||||||
|
offset += next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip whitespace
|
||||||
|
for (; line[offset] == ' ' && !eol(line[offset]); offset++);
|
||||||
|
}
|
||||||
|
|
||||||
|
// step 2 - execute
|
||||||
|
if (ooffset == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (ops[0]->valtype != FUNC)
|
||||||
|
return -2;
|
||||||
|
|
||||||
if (var != 0) {
|
if (ops[0]->value == 0)
|
||||||
bits[boffset++] = var;
|
return -3;
|
||||||
|
|
||||||
|
for (uint32_t i = ooffset; --i > 0;)
|
||||||
|
ipush(interp, ops[i]);
|
||||||
|
|
||||||
|
if (ops[0]->fromc) {
|
||||||
|
int ret = ((func_t)ops[0]->value)(interp);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
// defining new variable
|
ipush(interp, (void *)(interp->lnidx + 1));
|
||||||
interpreter_define_value(interp, copysubstr(line, end), 0);
|
interp->lnidx = ops[0]->value;
|
||||||
goto getvar; // try again
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// skip whitespace/name
|
|
||||||
offset += end;
|
|
||||||
offset += spacecount(line + offset);
|
|
||||||
|
|
||||||
if (boffset == 0 && line[offset] != '=')
|
|
||||||
return -1; // variable not found
|
|
||||||
|
|
||||||
// find operator
|
|
||||||
if (line[offset] == '\0') {
|
|
||||||
// print value
|
|
||||||
return -99;
|
|
||||||
} else if (line[offset] == '=') {
|
|
||||||
// assignment/expression
|
|
||||||
offset++;
|
|
||||||
offset += spacecount(line + offset);
|
|
||||||
bits[0]->value = (uint32_t)copystr(line + offset, '\0');
|
|
||||||
} else if (line[offset] == '(') {
|
|
||||||
// function call
|
|
||||||
offset++;
|
|
||||||
if (bits[0]->type != FUNCTION && bits[0]->type != CFUNCTION)
|
|
||||||
return -2;
|
|
||||||
offset += spacecount(line + offset);
|
|
||||||
|
|
||||||
// collect arg offsets
|
|
||||||
uint16_t offsets[8];
|
|
||||||
uint8_t ooffset = 0;
|
|
||||||
while (line[offset] != ')' && line[offset] != '\0') {
|
|
||||||
offsets[ooffset] = offset;
|
|
||||||
offset += spacecount(line + offset);
|
|
||||||
|
|
||||||
uint8_t isvn = 1;
|
|
||||||
do {
|
|
||||||
if (line[offset] == ' ' || line[offset] == '\t') {
|
|
||||||
offset += spacecount(line + offset);
|
|
||||||
isvn = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line[offset] == ',') {
|
interp->stidx -= ooffset - 1;
|
||||||
offset++;
|
|
||||||
ooffset++;
|
if ((int32_t)interp->stidx < 0) {
|
||||||
break;
|
interp->stidx = 0;
|
||||||
} else if (line[offset] == ')') {
|
return -5;
|
||||||
ooffset++;
|
}
|
||||||
break;
|
|
||||||
} else if (isvn == 0) {
|
for (uint32_t i = 0; i < ooffset; i++) {
|
||||||
return -3;
|
if (!ops[i]->used)
|
||||||
|
free(ops[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
norun:
|
||||||
|
interp->lnidx++;
|
||||||
|
if (interp->lines[interp->lnidx] != 0) {
|
||||||
|
line = interp->lines[interp->lnidx];
|
||||||
|
goto loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
char *mline = line;
|
||||||
|
void *ops[16];
|
||||||
|
uint32_t ooffset = 0;
|
||||||
|
uint32_t offset = 0;
|
||||||
|
uint32_t next;
|
||||||
|
|
||||||
|
// step 1 - break apart line
|
||||||
|
|
||||||
|
// skip whitespace
|
||||||
|
for (; line[offset] == ' ' && !eol(line[offset]); offset++);
|
||||||
|
while (!eoe(line[offset])) {
|
||||||
|
if (line[offset] == '(') {
|
||||||
|
uint8_t indent = 0;
|
||||||
|
uint32_t i;
|
||||||
|
for (i = offset + 1; !eol(line[i]); i++) {
|
||||||
|
if (line[i] == '(') {
|
||||||
|
indent++;
|
||||||
|
} else if (line[i] == ')') {
|
||||||
|
if (indent == 0) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
indent--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} while (++offset);
|
}
|
||||||
|
if (eol(line[i]))
|
||||||
|
return 0;
|
||||||
|
ops[ooffset] = idoexpr(interp, line + offset + 1);
|
||||||
|
offset = i + 1;
|
||||||
|
} else {
|
||||||
|
uint32_t end = offset;
|
||||||
|
char cend = 0;
|
||||||
|
if (line[offset] != '\"') {
|
||||||
|
for (; isalnum(line[end]) || line[end] == '.'; end++);
|
||||||
|
cend = line[end];
|
||||||
|
mline[end] = ' ';
|
||||||
|
}
|
||||||
|
ops[ooffset] = make_var(interp, line + offset, &next);
|
||||||
|
if (end != 0)
|
||||||
|
mline[end] = cend;
|
||||||
}
|
}
|
||||||
|
if (ops[ooffset] == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ooffset++;
|
||||||
|
offset += next;
|
||||||
|
|
||||||
|
// skip whitespace
|
||||||
|
for (; line[offset] == ' ' && !eoe(line[offset]); offset++);
|
||||||
|
if (eoe(line[offset]))
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < IOPS_COUNT; i++) {
|
||||||
|
int len = strlen(iops[i]);
|
||||||
|
if (!strncmp(iops[i], line + offset, len)) {
|
||||||
|
ops[ooffset] = (void *)(i + 1);
|
||||||
|
offset += len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ops[ooffset] == 0)
|
||||||
|
return 0;
|
||||||
|
ooffset++;
|
||||||
|
|
||||||
// populate stack
|
// skip whitespace
|
||||||
for (uint8_t i = 0; i < ooffset; i++) {
|
for (; line[offset] == ' ' && !eol(line[offset]); offset++);
|
||||||
uint16_t j;
|
}
|
||||||
for (j = offsets[i]; line[j] != ' ' && line[j] != '\t' &&
|
|
||||||
line[j] != ',' && line[j] != ')'; j++);
|
|
||||||
j -= offsets[i];
|
|
||||||
|
|
||||||
variable *var = interpreter_getvar(interp, line + offsets[i]);
|
if (ooffset % 2 == 0)
|
||||||
if (var != 0)
|
return 0;
|
||||||
interp->stack[i] = copystr((char *)var->value, '\0');
|
|
||||||
else
|
|
||||||
interp->stack[i] = copysubstr(line + offsets[i], j);
|
|
||||||
}
|
|
||||||
|
|
||||||
((func_t)bits[0]->value)(interp->stack);
|
// step 2 - do operations
|
||||||
} else {
|
result->valtype = ((variable *)ops[0])->valtype;
|
||||||
return -2; // invalid operation
|
result->value = ((variable *)ops[0])->value;
|
||||||
|
for (uint32_t i = 1; i < ooffset; i += 2) {
|
||||||
|
iopfuncs[(uint32_t)ops[i] - 1](result, result, ops[i + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < ooffset; i += 2) {
|
||||||
|
if (!((variable *)ops[i])->used)
|
||||||
|
free(ops[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result->valtype == INTEGER)
|
||||||
|
isetstr(result);
|
||||||
|
else
|
||||||
|
fsetstr(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_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;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue