258 lines
6.6 KiB
C
Raw Normal View History

2025-11-22 22:22:43 +01:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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() {
Token *t = &tokens[pc];
long val = 0;
if (t->type == Num) {
pc++;
return t->val;
}
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 (tokens[pc + 1].type == '(') {
int nf_idx = find_native_func(t->text, t->val);
if (nf_idx != -1) {
pc += 2;
long args[10];
int argc = 0;
if (tokens[pc].type != ')') {
do {
args[argc++] = expression();
} 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");
pc += 2;
int old_bp = bp;
long args[10];
int argc = 0;
if (tokens[pc].type != ')') {
do {
args[argc++] = expression();
} while (tokens[pc].type == ',' && pc++);
}
match(')');
int ret_pc = pc;
memory[sp] = bp; bp = sp++;
memory[sp++] = ret_pc;
for(int i=0; i<argc; i++) memory[sp++] = args[i];
pc = funcs[f_idx].entry_point;
statement();
val = ax;
sp = bp;
bp = memory[sp];
pc = ret_pc;
return val;
}
else {
int idx = find_local(t->text, t->val);
if (idx == -1) error("Undefined variable");
pc++;
Symbol *sym = &locals[idx];
if (tokens[pc].type == '[') {
pc++;
long start_or_index = expression();
if (tokens[pc].type == ':') {
pc++;
long end = expression();
match(']');
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(']');
return memory[sym->addr + start_or_index];
}
}
if (sym->is_array) {
return sym->addr;
}
return memory[sym->addr];
}
}
return 0;
}
long unary() {
if (tokens[pc].type == '*') {
pc++;
int addr = unary();
if (addr > MEM_SIZE * 8 || addr < 0) {
return *(char*)addr;
}
return memory[addr];
}
else if (tokens[pc].type == '&') {
pc++;
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++;
return locals[idx].addr;
}
else if (tokens[pc].type == '-') {
pc++;
return -unary();
}
return factor();
}
long term() {
long val = unary();
while (tokens[pc].type == '*' || tokens[pc].type == '/') {
int op = tokens[pc++].type;
long val2 = unary();
if (op == '*') val = val * val2;
else val = val / val2;
}
return val;
}
long add() {
long val = term();
while (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 (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 expression() {
if (tokens[pc].type == '*') {
int save_pc = pc;
unary();
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 (tokens[pc].type == Id) {
if (tokens[pc+1].type == '[') {
int idx = find_local(tokens[pc].text, tokens[pc].val);
if (idx == -1) error("Assign to unknown var");
pc += 2;
long start_or_index = expression();
if (tokens[pc].type == ':') {
pc++;
long end = expression();
match(']');
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 (tokens[pc].type == '=') {
pc++;
long val = expression();
memory[addr + start_or_index] = val;
return val;
}
return memory[addr + start_or_index];
} else if (tokens[pc+1].type == '=') {
int idx = find_local(tokens[pc].text, tokens[pc].val);
if (idx == -1) error("Assign to unknown var");
pc += 2;
long val = expression();
memory[locals[idx].addr] = val;
return val;
}
}
return relational();
}