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