feat: add return_flag and params_start for proper function return handling and parameter scanning
Implement a dedicated return_flag variable to replace the magic number -999 for return statements, enabling correct early exit from nested blocks. Add params_start field to Func struct to track parameter declaration positions, allowing the interpreter to properly map function arguments to local variables during function calls. Extend the test suite with new test files for arrays, comparison operators, logical operators, pointers, functions, trigonometry, and file seek operations, along with corresponding Makefile targets to execute them.
This commit is contained in:
@@ -16,3 +16,4 @@ char *src_code;
|
||||
char str_pool[STR_POOL_SIZE];
|
||||
int str_pool_idx = 0;
|
||||
long ax = 0;
|
||||
int return_flag = 0;
|
||||
|
||||
+6
-5
@@ -73,7 +73,7 @@ void statement() {
|
||||
pc++;
|
||||
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != '}' && tokens[pc].type != 0) {
|
||||
statement();
|
||||
if (ax == -999 || ax == -998 || ax == -997) {
|
||||
if (return_flag || ax == -998 || ax == -997) {
|
||||
int brace = 1;
|
||||
while (brace > 0 && pc < MAX_TOK && pc < tk_idx && tokens[pc].type != 0) {
|
||||
if (tokens[pc].type == '{') brace++;
|
||||
@@ -139,14 +139,14 @@ void statement() {
|
||||
match(')');
|
||||
if (cond) {
|
||||
statement();
|
||||
if (ax == -999 || ax == -998 || ax == -997) return;
|
||||
if (return_flag || ax == -998 || ax == -997) return;
|
||||
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) { pc++; skip_block(); }
|
||||
} else {
|
||||
skip_block();
|
||||
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) {
|
||||
pc++;
|
||||
statement();
|
||||
if (ax == -999 || ax == -998 || ax == -997) return;
|
||||
if (return_flag || ax == -998 || ax == -997) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,7 +169,7 @@ void statement() {
|
||||
}
|
||||
body_start = pc;
|
||||
statement();
|
||||
if (ax == -999) return;
|
||||
if (return_flag) return;
|
||||
if (ax == -998) {
|
||||
ax = 0;
|
||||
pc = body_start;
|
||||
@@ -186,7 +186,7 @@ void statement() {
|
||||
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != ';') ax = expression();
|
||||
else ax = 0;
|
||||
match(';');
|
||||
ax = -999;
|
||||
return_flag = 1;
|
||||
}
|
||||
else if (tokens[pc].type == Break) {
|
||||
pc++;
|
||||
@@ -253,6 +253,7 @@ void scan_functions() {
|
||||
strncpy(f->name, name->text, name->val); f->name[name->val] = 0;
|
||||
|
||||
i += 3;
|
||||
f->params_start = i;
|
||||
int params = 0;
|
||||
while(i < MAX_TOK && i < tk_idx && tokens[i].type != ')') {
|
||||
if (tokens[i].type == Int || tokens[i].type == Char || tokens[i].type == Double) {
|
||||
|
||||
+34
-1
@@ -78,9 +78,9 @@ long factor() {
|
||||
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;
|
||||
int call_pc = pc;
|
||||
pc += 2;
|
||||
|
||||
int old_bp = bp;
|
||||
long args[10];
|
||||
int argc = 0;
|
||||
|
||||
@@ -95,25 +95,58 @@ long factor() {
|
||||
match(')');
|
||||
|
||||
int ret_pc = pc;
|
||||
int old_loc_cnt = loc_cnt;
|
||||
int old_bp = bp;
|
||||
|
||||
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;
|
||||
memory[sp++] = old_loc_cnt;
|
||||
|
||||
int param_base = sp;
|
||||
for(int i=0; i<argc; i++) {
|
||||
if (sp >= MEM_SIZE) break;
|
||||
memory[sp++] = args[i];
|
||||
}
|
||||
|
||||
int scan_pc = funcs[f_idx].params_start;
|
||||
int param_idx = 0;
|
||||
while (scan_pc < MAX_TOK && scan_pc < tk_idx && tokens[scan_pc].type != ')') {
|
||||
if (tokens[scan_pc].type == Int || tokens[scan_pc].type == Char || tokens[scan_pc].type == Double) {
|
||||
scan_pc++;
|
||||
while (scan_pc < MAX_TOK && tokens[scan_pc].type == '*') scan_pc++;
|
||||
if (scan_pc < MAX_TOK && tokens[scan_pc].type == Id && param_idx < argc && loc_cnt < VAR_MAX) {
|
||||
Token *param_name = &tokens[scan_pc];
|
||||
Symbol *sym = &locals[loc_cnt++];
|
||||
int name_len = param_name->val;
|
||||
if (name_len > 31) name_len = 31;
|
||||
strncpy(sym->name, param_name->text, name_len);
|
||||
sym->name[name_len] = 0;
|
||||
sym->type = Int;
|
||||
sym->addr = param_base + param_idx;
|
||||
sym->is_array = 0;
|
||||
param_idx++;
|
||||
}
|
||||
}
|
||||
scan_pc++;
|
||||
}
|
||||
|
||||
pc = funcs[f_idx].entry_point;
|
||||
return_flag = 0;
|
||||
statement();
|
||||
|
||||
val = ax;
|
||||
ax = 0;
|
||||
return_flag = 0;
|
||||
|
||||
loc_cnt = old_loc_cnt;
|
||||
if (bp < 0 || bp >= MEM_SIZE) return 0;
|
||||
sp = bp;
|
||||
if (sp < 0 || sp >= MEM_SIZE) return 0;
|
||||
bp = memory[sp];
|
||||
if (sp + 1 < MEM_SIZE) ret_pc = memory[sp + 1];
|
||||
pc = ret_pc;
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ typedef struct {
|
||||
char name[32];
|
||||
int entry_point;
|
||||
int param_count;
|
||||
int params_start;
|
||||
} Func;
|
||||
|
||||
typedef long (*NativeFunc)(long*, int);
|
||||
@@ -55,5 +56,6 @@ extern char *src_code;
|
||||
extern char str_pool[STR_POOL_SIZE];
|
||||
extern int str_pool_idx;
|
||||
extern long ax;
|
||||
extern int return_flag;
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user