#include #include #include #include "types.h" #include "parser.h" #include "interpreter.h" #include "string_utils.h" extern Token tokens[]; extern int pc; extern long memory[]; extern int sp; extern int bp; extern Symbol locals[]; extern int loc_cnt; extern Func funcs[]; extern int func_cnt; extern NativeFuncDef native_funcs[]; extern int native_func_cnt; extern long ax; extern void error(char *msg); extern void match(int type); extern int find_local(char *name, int len); extern int find_func(char *name, int len); extern int find_native_func(char *name, int len); extern void statement(); long factor() { if (pc >= MAX_TOK) return 0; Token *t = &tokens[pc]; long val = 0; if (t->type == Num) { pc++; return t->val; } else if (t->type == Dbl) { pc++; union { double d; long l; } u; u.d = t->dval; return u.l; } else if (t->type == Str) { pc++; return (long)t->text; } else if (t->type == '(') { pc++; val = expression(); match(')'); return val; } else if (t->type == Id) { if (pc + 1 >= MAX_TOK) return 0; if (tokens[pc + 1].type == '(') { int nf_idx = find_native_func(t->text, t->val); if (nf_idx != -1) { if (nf_idx < 0 || nf_idx >= native_func_cnt) return 0; pc += 2; long args[10]; int argc = 0; if (pc >= MAX_TOK) return 0; if (tokens[pc].type != ')') { do { if (argc >= 10) break; args[argc++] = expression(); if (pc >= MAX_TOK) return 0; } while (tokens[pc].type == ',' && pc++); } match(')'); return native_funcs[nf_idx].func(args, argc); } int f_idx = find_func(t->text, t->val); if (f_idx == -1) error("Unknown function"); if (f_idx < 0 || f_idx >= func_cnt) return 0; pc += 2; int old_bp = bp; long args[10]; int argc = 0; if (pc >= MAX_TOK) return 0; if (tokens[pc].type != ')') { do { if (argc >= 10) break; args[argc++] = expression(); if (pc >= MAX_TOK) return 0; } while (tokens[pc].type == ',' && pc++); } match(')'); int ret_pc = pc; if (sp >= MEM_SIZE) return 0; if (bp < 0 || bp >= MEM_SIZE) return 0; memory[sp] = bp; bp = sp++; if (sp >= MEM_SIZE) return 0; memory[sp++] = ret_pc; for(int i=0; i= MEM_SIZE) break; memory[sp++] = args[i]; } pc = funcs[f_idx].entry_point; statement(); val = ax; if (bp < 0 || bp >= MEM_SIZE) return 0; sp = bp; if (sp < 0 || sp >= MEM_SIZE) return 0; bp = memory[sp]; pc = ret_pc; return val; } else { int idx = find_local(t->text, t->val); if (idx == -1) error("Undefined variable"); if (idx < 0 || idx >= loc_cnt) return 0; pc++; Symbol *sym = &locals[idx]; if (pc < MAX_TOK && (tokens[pc].type == Inc || tokens[pc].type == Dec)) { long val = memory[sym->addr]; if (tokens[pc].type == Inc) { memory[sym->addr]++; } else { memory[sym->addr]--; } pc++; return val; } if (pc >= MAX_TOK) return 0; if (tokens[pc].type == '[') { pc++; long start_or_index = expression(); if (pc >= MAX_TOK) return 0; if (tokens[pc].type == ':') { pc++; long end = expression(); match(']'); if (sym->addr < 0 || sym->addr >= MEM_SIZE) return 0; long val = memory[sym->addr]; if (is_string_ptr(val)) { return slice_string(val, start_or_index, end); } else { error("Slicing only works on strings"); } } else { match(']'); long addr = sym->addr + start_or_index; if (addr < 0 || addr >= MEM_SIZE) return 0; return memory[addr]; } } if (sym->is_array) { return sym->addr; } if (sym->addr < 0 || sym->addr >= MEM_SIZE) return 0; return memory[sym->addr]; } } return 0; } long unary() { if (pc >= MAX_TOK) return 0; if (tokens[pc].type == Inc || tokens[pc].type == Dec) { int op = tokens[pc++].type; Token *t = &tokens[pc]; if (t->type != Id) error("Expected identifier after ++/--"); int idx = find_local(t->text, t->val); if (idx == -1) error("Undefined variable"); pc++; long addr = locals[idx].addr; if (op == Inc) { memory[addr]++; } else { memory[addr]--; } return memory[addr]; } if (tokens[pc].type == '*') { pc++; int addr = unary(); if (addr > MEM_SIZE * 8 || addr < 0) { return *(char*)addr; } if (addr < 0 || addr >= MEM_SIZE) return 0; return memory[addr]; } else if (tokens[pc].type == '&') { pc++; if (pc >= MAX_TOK) return 0; Token *t = &tokens[pc]; if (t->type != Id) error("Expected identifier after &"); int idx = find_local(t->text, t->val); if (idx == -1) error("Undefined variable"); if (idx < 0 || idx >= loc_cnt) return 0; pc++; return locals[idx].addr; } else if (tokens[pc].type == '-') { pc++; return -unary(); } return factor(); } long term() { long val = unary(); while (pc < MAX_TOK && (tokens[pc].type == '*' || tokens[pc].type == '/')) { int op = tokens[pc++].type; long val2 = unary(); if (op == '*') val = val * val2; else { if (val2 != 0) val = val / val2; else val = 0; } } return val; } long add() { long val = term(); while (pc < MAX_TOK && (tokens[pc].type == '+' || tokens[pc].type == '-')) { int op = tokens[pc++].type; long val2 = term(); if (op == '+') { if (is_string_ptr(val) && is_string_ptr(val2)) { val = concat_strings(val, val2); } else { val = val + val2; } } else { val = val - val2; } } return val; } long relational() { long val = add(); while (pc < MAX_TOK && tokens[pc].type >= Eq && tokens[pc].type <= Ge) { int op = tokens[pc++].type; long val2 = add(); if (op == Eq) val = val == val2; if (op == Ne) val = val != val2; if (op == Lt) val = val < val2; if (op == Gt) val = val > val2; } return val; } long logical_and() { long val = relational(); while (pc < MAX_TOK && tokens[pc].type == And) { pc++; long val2 = relational(); val = val && val2; } return val; } long logical_or() { long val = logical_and(); while (pc < MAX_TOK && tokens[pc].type == Or) { pc++; long val2 = logical_and(); val = val || val2; } return val; } long expression() { if (pc >= MAX_TOK) return 0; if (tokens[pc].type == '*') { int save_pc = pc; unary(); if (pc >= MAX_TOK) return 0; if (tokens[pc].type == '=') { pc = save_pc; pc++; long addr = unary(); match('='); long val = expression(); if (addr >= 0 && addr < MEM_SIZE) memory[addr] = val; return val; } pc = save_pc; } if (pc >= MAX_TOK) return 0; if (tokens[pc].type == Id) { if (pc + 1 >= MAX_TOK) return 0; if (tokens[pc+1].type == '[') { int idx = find_local(tokens[pc].text, tokens[pc].val); if (idx == -1) error("Assign to unknown var"); if (idx < 0 || idx >= loc_cnt) return 0; pc += 2; long start_or_index = expression(); if (pc >= MAX_TOK) return 0; if (tokens[pc].type == ':') { pc++; long end = expression(); match(']'); if (locals[idx].addr < 0 || locals[idx].addr >= MEM_SIZE) return 0; long val = memory[locals[idx].addr]; if (is_string_ptr(val)) { return slice_string(val, start_or_index, end); } else { error("Slicing only works on strings"); } } match(']'); int addr = locals[idx].addr; if (pc >= MAX_TOK) return 0; if (tokens[pc].type == '=') { pc++; long val = expression(); long target_addr = addr + start_or_index; if (target_addr >= 0 && target_addr < MEM_SIZE) { memory[target_addr] = val; } return val; } long read_addr = addr + start_or_index; if (read_addr < 0 || read_addr >= MEM_SIZE) return 0; return memory[read_addr]; } else if (tokens[pc+1].type == '=') { int idx = find_local(tokens[pc].text, tokens[pc].val); if (idx == -1) error("Assign to unknown var"); if (idx < 0 || idx >= loc_cnt) return 0; pc += 2; long val = expression(); if (locals[idx].addr >= 0 && locals[idx].addr < MEM_SIZE) { memory[locals[idx].addr] = val; } return val; } } return logical_or(); }