Compare commits

..
43 Commits
Author SHA1 Message Date
retoor 2f0b6d9c92 Update.
Build and Test / build (push) Successful in 16s
2025-11-25 01:25:16 +01:00
retoor f310788168 Update.
Build and Test / build (push) Successful in 8s
2025-11-24 15:07:12 +01:00
retoor e17b235ecc Update. 2025-11-24 11:21:23 +01:00
retoor 4dc33c81b4 Update. 2025-11-24 11:12:34 +01:00
retoor c08fa0cc6a Improvements. 2025-11-24 11:09:55 +01:00
retoor 3252560f94 More robuust. 2025-11-24 10:42:54 +01:00
retoor ded2448ebd Update. 2025-11-24 10:26:12 +01:00
retoor fc05199a76 Update. 2025-11-24 10:21:23 +01:00
retoor 863434f9af Update.
Build and Test / build (push) Successful in 8s
2025-11-24 10:00:49 +01:00
retoor f61c15061d Update. 2025-11-24 09:08:13 +01:00
retoor e7b8f7f68c Update. 2025-11-24 08:55:17 +01:00
retoor cecbdc4053 Update. 2025-11-24 05:51:03 +01:00
retoor 1b57b479bb global var optimizations. 2025-11-24 03:47:07 +01:00
retoor b3b117d3a5 Fixed async. 2025-11-24 03:37:40 +01:00
retoor 6aa82a613e Update. 2025-11-24 02:56:47 +01:00
retoor dfba1c40c4 Robuustness. 2025-11-24 02:19:24 +01:00
retoor 46c18308b8 Error handling. 2025-11-24 02:09:13 +01:00
retoor 0474c958fe Error handling. 2025-11-24 02:09:02 +01:00
retoor d0fc94f0c0 Error handling. 2025-11-24 01:59:54 +01:00
retoor 2f20998f22 Added eval. 2025-11-24 01:46:47 +01:00
retoor 0db921cfa3 More robuust ness. 2025-11-24 01:30:16 +01:00
retoor a1eb00caff Unit test framework with new cases. 2025-11-24 00:50:23 +01:00
retoor 8f175b3563 Added unit test framework. 2025-11-23 23:46:02 +01:00
retoor eacf4f3e36 Working OOP. 2025-11-23 23:23:17 +01:00
retoor 3cbf684dad Structuring. 2025-11-23 23:03:19 +01:00
retoor e75ccec309 Professionalize. 2025-11-23 22:14:15 +01:00
retoor 97fc55f74d UPdate documentation. 2025-11-23 21:33:07 +01:00
retoor 327eeadca4 Implemented async better. 2025-11-23 20:30:37 +01:00
retoor e5f6f89764 Removed file.
Build and Test / build (push) Successful in 17s
2025-11-23 15:59:21 +01:00
retoor 2dae3f98e9 Added build file.
Build and Test / build (push) Successful in 28s
2025-11-23 15:45:39 +01:00
retoor 0ec0590ad0 Added include functionallity. 2025-11-23 15:23:59 +01:00
retoor 6c8a15272a Implemented tests. 2025-11-23 15:07:19 +01:00
retoor 5828aa8622 Async implementation. 2025-11-23 14:30:46 +01:00
retoor 050e85b72a Break loop. 2025-11-23 13:53:36 +01:00
retoor 63f9eb48a4 Update. 2025-11-23 00:19:52 +01:00
retoor 5e1901105a Update. 2025-11-23 00:17:01 +01:00
retoor f315874236 Added tutorial. 2025-11-22 23:28:28 +01:00
retoor bd8d9d819e Update. 2025-11-22 23:15:15 +01:00
retoor e6d75958c8 Update file names. 2025-11-22 22:30:55 +01:00
retoor d087be7ab3 Clean up. 2025-11-22 22:24:53 +01:00
retoor e691b109f2 Update. 2025-11-22 22:24:34 +01:00
retoor cb9b4e2941 Structuring. 2025-11-22 22:22:43 +01:00
retoor ab71aa9999 Working. 2025-11-22 16:53:39 +01:00
9 changed files with 300 additions and 466 deletions
-1
View File
@@ -23,7 +23,6 @@ SOURCES = $(SRC_DIR)/main.c \
$(SRC_DIR)/context.c \ $(SRC_DIR)/context.c \
$(SRC_DIR)/debug.c \ $(SRC_DIR)/debug.c \
$(SRC_DIR)/memory.c \ $(SRC_DIR)/memory.c \
$(SRC_DIR)/scope.c \
$(SRC_DIR)/stdlib/stdlib.c \ $(SRC_DIR)/stdlib/stdlib.c \
$(SRC_DIR)/stdlib/string/string_stdlib.c \ $(SRC_DIR)/stdlib/string/string_stdlib.c \
$(SRC_DIR)/stdlib/math/math_stdlib.c \ $(SRC_DIR)/stdlib/math/math_stdlib.c \
-1
View File
@@ -1,7 +1,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "types.h" #include "types.h"
#include "scope.h"
extern long memory[MEM_SIZE]; extern long memory[MEM_SIZE];
extern int sp; extern int sp;
-3
View File
@@ -11,13 +11,11 @@
#include "oop.h" #include "oop.h"
#include "debug.h" #include "debug.h"
#include "memory.h" #include "memory.h"
#include "scope.h"
int main(int argc, char **argv) { int main(int argc, char **argv) {
DEBUG_INIT(); DEBUG_INIT();
DEBUG_LOG("RC Interpreter starting"); DEBUG_LOG("RC Interpreter starting");
mem_init(); mem_init();
scope_init();
pthread_rwlock_init(&tokens_rwlock, NULL); pthread_rwlock_init(&tokens_rwlock, NULL);
pthread_mutex_init(&str_pool_mutex, NULL); pthread_mutex_init(&str_pool_mutex, NULL);
@@ -78,7 +76,6 @@ int main(int argc, char **argv) {
statement(); statement();
free(src_code); free(src_code);
scope_cleanup();
pthread_rwlock_destroy(&tokens_rwlock); pthread_rwlock_destroy(&tokens_rwlock);
pthread_mutex_destroy(&str_pool_mutex); pthread_mutex_destroy(&str_pool_mutex);
pthread_mutex_destroy(&memory_mutex); pthread_mutex_destroy(&memory_mutex);
+16 -8
View File
@@ -3,7 +3,6 @@
#include <string.h> #include <string.h>
#include "types.h" #include "types.h"
#include "interpreter.h" #include "interpreter.h"
#include "scope.h"
int find_class(char *name, int len) { int find_class(char *name, int len) {
if (!name || len <= 0 || len > 31) return -1; if (!name || len <= 0 || len > 31) return -1;
@@ -114,15 +113,23 @@ void call_destructor(long obj_ptr) {
int func_idx = cls->methods[i].func_idx; int func_idx = cls->methods[i].func_idx;
if (func_idx >= 0 && func_idx < func_cnt) { if (func_idx >= 0 && func_idx < func_cnt) {
int saved_pc = pc; int saved_pc = pc;
int saved_sp = sp;
int saved_bp = bp;
int saved_loc_cnt = loc_cnt;
long saved_ax = ax; long saved_ax = ax;
int saved_return_flag = return_flag; int saved_return_flag = return_flag;
scope_push(); if (sp >= MEM_SIZE || bp < 0 || bp >= MEM_SIZE) return;
int param_base = sp; memory[sp] = bp;
if (sp < MEM_SIZE) { bp = sp++;
if (sp >= MEM_SIZE) return;
memory[sp++] = 0;
memory[sp++] = saved_loc_cnt;
if (sp >= MEM_SIZE) return;
memory[sp++] = obj_ptr; memory[sp++] = obj_ptr;
}
int scan_pc = funcs[func_idx].params_start; int scan_pc = funcs[func_idx].params_start;
if (scan_pc < MAX_TOK && scan_pc < tk_idx && tokens[scan_pc].type != ')') { if (scan_pc < MAX_TOK && scan_pc < tk_idx && tokens[scan_pc].type != ')') {
@@ -135,7 +142,7 @@ void call_destructor(long obj_ptr) {
strncpy(sym->name, param_name->text, name_len); strncpy(sym->name, param_name->text, name_len);
sym->name[name_len] = 0; sym->name[name_len] = 0;
sym->type = Int; sym->type = Int;
sym->addr = param_base; sym->addr = sp - 1;
sym->is_array = 0; sym->is_array = 0;
} }
} }
@@ -147,9 +154,10 @@ void call_destructor(long obj_ptr) {
statement(); statement();
scope_pop();
pc = saved_pc; pc = saved_pc;
sp = saved_sp;
bp = saved_bp;
loc_cnt = saved_loc_cnt;
ax = saved_ax; ax = saved_ax;
return_flag = saved_return_flag; return_flag = saved_return_flag;
} }
+49 -18
View File
@@ -8,7 +8,6 @@
#include "error.h" #include "error.h"
#include "debug.h" #include "debug.h"
#include "memory.h" #include "memory.h"
#include "scope.h"
extern Token tokens[]; extern Token tokens[];
extern int pc; extern int pc;
@@ -178,20 +177,26 @@ long factor() {
} }
int ret_pc = pc; int ret_pc = pc;
int saved_return_flag = return_flag; int old_loc_cnt = loc_cnt;
int old_bp = bp;
int old_sp = sp;
mem_enter_call(funcs[f_idx].name); mem_enter_call(funcs[f_idx].name);
scope_push();
char call_ctx[128]; char call_ctx[128];
snprintf(call_ctx, sizeof(call_ctx), "call %s: push frame", funcs[f_idx].name); snprintf(call_ctx, sizeof(call_ctx), "call %s: push frame", funcs[f_idx].name);
if (!mem_check_sp(sp + 3 + argc, call_ctx)) return 0;
if (!mem_check_addr(bp, call_ctx)) return 0;
mem_write(sp, bp, call_ctx);
bp = sp++;
mem_write(sp++, ret_pc, call_ctx);
mem_write(sp++, old_loc_cnt, call_ctx);
int param_base = sp; int param_base = sp;
for(int i=0; i<argc; i++) { for(int i=0; i<argc; i++) {
if (sp < MEM_SIZE) { mem_write(sp++, args[i], call_ctx);
memory[sp++] = args[i];
}
} }
int scan_pc = funcs[f_idx].params_start; int scan_pc = funcs[f_idx].params_start;
@@ -201,7 +206,7 @@ long factor() {
scan_pc++; scan_pc++;
while (scan_pc < MAX_TOK && tokens[scan_pc].type == '*') 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) { if (scan_pc < MAX_TOK && tokens[scan_pc].type == Id && param_idx < argc) {
if (loc_cnt < VAR_MAX) { if (!mem_check_loc_cnt(loc_cnt + 1, call_ctx)) return 0;
Token *param_name = &tokens[scan_pc]; Token *param_name = &tokens[scan_pc];
Symbol *sym = &locals[loc_cnt++]; Symbol *sym = &locals[loc_cnt++];
int name_len = param_name->val; int name_len = param_name->val;
@@ -212,12 +217,18 @@ long factor() {
sym->addr = param_base + param_idx; sym->addr = param_base + param_idx;
sym->is_array = 0; sym->is_array = 0;
param_idx++; param_idx++;
if (loc_cnt > mem_stats.loc_cnt_high_water) {
mem_stats.loc_cnt_high_water = loc_cnt;
} }
} }
} }
scan_pc++; scan_pc++;
} }
if (sp > mem_stats.sp_high_water) {
mem_stats.sp_high_water = sp;
}
const char *func_filename = NULL; const char *func_filename = NULL;
int func_line = 0; int func_line = 0;
if (funcs[f_idx].entry_point < tk_idx) { if (funcs[f_idx].entry_point < tk_idx) {
@@ -237,10 +248,22 @@ long factor() {
pop_call_frame(); pop_call_frame();
mem_exit_call(funcs[f_idx].name); mem_exit_call(funcs[f_idx].name);
scope_pop(); snprintf(call_ctx, sizeof(call_ctx), "return from %s: restore frame", funcs[f_idx].name);
if (old_loc_cnt < 0 || old_loc_cnt > loc_cnt) {
char msg[256];
snprintf(msg, sizeof(msg), "loc_cnt corruption: old=%d, current=%d", old_loc_cnt, loc_cnt);
error(msg);
return 0;
}
loc_cnt = old_loc_cnt;
if (!mem_check_addr(bp, call_ctx)) return 0;
sp = bp;
if (!mem_check_addr(sp, call_ctx)) return 0;
bp = mem_read(sp, call_ctx);
ret_pc = mem_read(sp + 1, call_ctx);
pc = ret_pc; pc = ret_pc;
return_flag = saved_return_flag;
return val; return val;
} }
else { else {
@@ -429,16 +452,23 @@ long unary() {
match(')'); match(')');
int saved_pc = pc; int saved_pc = pc;
int saved_return_flag = return_flag; int saved_sp = sp;
int saved_bp = bp;
int saved_loc_cnt = loc_cnt;
scope_push(); if (sp >= MEM_SIZE || bp < 0 || bp >= MEM_SIZE) return 0;
memory[sp] = bp;
bp = sp++;
if (sp >= MEM_SIZE) return 0;
memory[sp++] = 0;
memory[sp++] = saved_loc_cnt;
int param_base = sp;
for (int i = 0; i < argc && i < 10; i++) { for (int i = 0; i < argc && i < 10; i++) {
if (sp < MEM_SIZE) { if (sp >= MEM_SIZE) break;
memory[sp++] = args[i]; memory[sp++] = args[i];
} }
}
int scan_pc = funcs[func_idx].params_start; int scan_pc = funcs[func_idx].params_start;
int param_idx = 0; int param_idx = 0;
@@ -455,7 +485,7 @@ long unary() {
strncpy(sym->name, param_name->text, name_len); strncpy(sym->name, param_name->text, name_len);
sym->name[name_len] = 0; sym->name[name_len] = 0;
sym->type = Int; sym->type = Int;
sym->addr = param_base + param_idx; sym->addr = saved_sp + 3 + param_idx;
sym->is_array = 0; sym->is_array = 0;
param_idx++; param_idx++;
} }
@@ -471,9 +501,10 @@ long unary() {
ax = 0; ax = 0;
return_flag = 0; return_flag = 0;
scope_pop();
pc = saved_pc; pc = saved_pc;
return_flag = saved_return_flag; sp = saved_sp;
bp = saved_bp;
loc_cnt = saved_loc_cnt;
} else { } else {
extern int find_class_field(int class_idx, char *name, int len); extern int find_class_field(int class_idx, char *name, int len);
int field_idx = find_class_field(class_idx, member->text, member->val); int field_idx = find_class_field(class_idx, member->text, member->val);
-363
View File
@@ -1,363 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "scope.h"
#include "types.h"
#include "interpreter.h"
Scope *current_scope = NULL;
Scope *root_scope = NULL;
Scope* scope_create(Scope *parent) {
Scope *scope = (Scope*)calloc(1, sizeof(Scope));
if (!scope) return NULL;
scope->parent = parent;
scope->mem_size = SCOPE_MEM_SIZE;
scope->loc_capacity = SCOPE_VAR_MAX;
scope->memory = (long*)calloc(SCOPE_MEM_SIZE, sizeof(long));
if (!scope->memory) {
free(scope);
return NULL;
}
scope->locals = (Symbol*)calloc(SCOPE_VAR_MAX, sizeof(Symbol));
if (!scope->locals) {
free(scope->memory);
free(scope);
return NULL;
}
scope->sp = 0;
scope->bp = 0;
scope->loc_cnt = 0;
scope->depth = parent ? parent->depth + 1 : 0;
return scope;
}
void scope_destroy(Scope *scope) {
if (!scope) return;
if (scope->memory) free(scope->memory);
if (scope->locals) free(scope->locals);
free(scope);
}
Scope* scope_push(void) {
extern long memory[];
extern Symbol locals[];
extern int sp, bp, loc_cnt;
if (current_scope) {
int copy_sp = sp < current_scope->mem_size ? sp : current_scope->mem_size;
for (int i = 0; i < copy_sp; i++) {
current_scope->memory[i] = memory[i];
}
int copy_loc = loc_cnt < current_scope->loc_capacity ? loc_cnt : current_scope->loc_capacity;
for (int i = 0; i < copy_loc; i++) {
current_scope->locals[i] = locals[i];
}
current_scope->sp = sp;
current_scope->bp = bp;
current_scope->loc_cnt = loc_cnt;
}
Scope *new_scope = scope_create(current_scope);
if (!new_scope) {
error("Failed to create new scope");
return NULL;
}
current_scope = new_scope;
sp = 0;
bp = 0;
loc_cnt = 0;
return new_scope;
}
Scope* scope_pop(void) {
extern long memory[];
extern Symbol locals[];
extern int sp, bp, loc_cnt;
if (!current_scope || !current_scope->parent) {
return current_scope;
}
Scope *old = current_scope;
current_scope = current_scope->parent;
scope_destroy(old);
if (current_scope) {
int copy_sp = current_scope->sp < MEM_SIZE ? current_scope->sp : MEM_SIZE;
for (int i = 0; i < copy_sp; i++) {
memory[i] = current_scope->memory[i];
}
int copy_loc = current_scope->loc_cnt < VAR_MAX ? current_scope->loc_cnt : VAR_MAX;
for (int i = 0; i < copy_loc; i++) {
locals[i] = current_scope->locals[i];
}
sp = current_scope->sp;
bp = current_scope->bp;
loc_cnt = current_scope->loc_cnt;
}
return current_scope;
}
int scope_find_local_current_only(const char *name, int len) {
if (!current_scope || !name || len <= 0 || len >= 32) return -1;
Scope *scope = current_scope;
for (int i = scope->loc_cnt - 1; i >= 0; i--) {
if (!strncmp(scope->locals[i].name, name, len) && scope->locals[i].name[len] == 0) {
return i;
}
}
return -1;
}
static int scope_find_local_in_scope(Scope *scope, const char *name, int len) {
if (!scope || !name || len <= 0 || len >= 32) return -1;
for (int i = scope->loc_cnt - 1; i >= 0; i--) {
if (!strncmp(scope->locals[i].name, name, len) && scope->locals[i].name[len] == 0) {
return i;
}
}
return -1;
}
int scope_find_local(const char *name, int len) {
if (!name || len <= 0 || len >= 32) return -1;
Scope *scope = current_scope;
while (scope) {
int idx = scope_find_local_in_scope(scope, name, len);
if (idx >= 0) {
return idx;
}
scope = scope->parent;
}
return -1;
}
Symbol* scope_get_local(int idx) {
if (!current_scope || idx < 0) return NULL;
Scope *scope = current_scope;
while (scope) {
if (idx < scope->loc_cnt) {
return &scope->locals[idx];
}
scope = scope->parent;
}
return NULL;
}
Symbol* scope_add_local(const char *name, int len, int type, int addr, int is_array) {
if (!current_scope) return NULL;
if (current_scope->loc_cnt >= current_scope->loc_capacity) {
error("Too many local variables in scope");
return NULL;
}
Symbol *sym = &current_scope->locals[current_scope->loc_cnt++];
int name_len = len > 31 ? 31 : len;
strncpy(sym->name, name, name_len);
sym->name[name_len] = 0;
sym->type = type;
sym->addr = addr;
sym->is_array = is_array;
return sym;
}
long scope_mem_read(int addr) {
if (!current_scope) return 0;
if (addr < 0) return 0;
Scope *scope = current_scope;
while (scope) {
if (addr < scope->mem_size && addr < scope->sp) {
return scope->memory[addr];
}
if (addr < scope->mem_size) {
return scope->memory[addr];
}
scope = scope->parent;
}
if (addr < current_scope->mem_size) {
return current_scope->memory[addr];
}
return 0;
}
void scope_mem_write(int addr, long value) {
if (!current_scope) return;
if (addr < 0 || addr >= current_scope->mem_size) return;
current_scope->memory[addr] = value;
}
int scope_mem_alloc(int size) {
if (!current_scope || size <= 0) return -1;
if (current_scope->sp + size > current_scope->mem_size) {
error("Scope stack overflow");
return -1;
}
int addr = current_scope->sp;
current_scope->sp += size;
return addr;
}
int scope_check_sp(int required) {
if (!current_scope) return 0;
return required >= 0 && required < current_scope->mem_size;
}
int scope_check_addr(int addr) {
if (!current_scope) return 0;
return addr >= 0 && addr < current_scope->mem_size;
}
void scope_init(void) {
extern int sp, bp, loc_cnt;
if (root_scope) {
scope_cleanup();
}
root_scope = scope_create(NULL);
current_scope = root_scope;
sp = 0;
bp = 0;
loc_cnt = 0;
}
void scope_cleanup(void) {
while (current_scope && current_scope != root_scope) {
scope_pop();
}
if (root_scope) {
scope_destroy(root_scope);
root_scope = NULL;
current_scope = NULL;
}
}
void scope_save_state(int *out_sp, int *out_bp, int *out_loc_cnt) {
if (!current_scope) {
*out_sp = 0;
*out_bp = 0;
*out_loc_cnt = 0;
return;
}
*out_sp = current_scope->sp;
*out_bp = current_scope->bp;
*out_loc_cnt = current_scope->loc_cnt;
}
void scope_restore_state(int saved_sp, int saved_bp, int saved_loc_cnt) {
if (!current_scope) return;
current_scope->sp = saved_sp;
current_scope->bp = saved_bp;
current_scope->loc_cnt = saved_loc_cnt;
}
void scope_sync_to_globals(void) {
if (!current_scope) return;
extern long memory[];
extern Symbol locals[];
extern int sp, bp, loc_cnt;
int copy_sp = current_scope->sp < MEM_SIZE ? current_scope->sp : MEM_SIZE;
for (int i = 0; i < copy_sp; i++) {
memory[i] = current_scope->memory[i];
}
int copy_loc = current_scope->loc_cnt < VAR_MAX ? current_scope->loc_cnt : VAR_MAX;
for (int i = 0; i < copy_loc; i++) {
locals[i] = current_scope->locals[i];
}
sp = current_scope->sp;
bp = current_scope->bp;
loc_cnt = current_scope->loc_cnt;
}
void scope_sync_from_globals(void) {
if (!current_scope) return;
extern long memory[];
extern Symbol locals[];
extern int sp, bp, loc_cnt;
int copy_sp = sp < current_scope->mem_size ? sp : current_scope->mem_size;
for (int i = 0; i < copy_sp; i++) {
current_scope->memory[i] = memory[i];
}
int copy_loc = loc_cnt < current_scope->loc_capacity ? loc_cnt : current_scope->loc_capacity;
for (int i = 0; i < copy_loc; i++) {
current_scope->locals[i] = locals[i];
}
current_scope->sp = sp;
current_scope->bp = bp;
current_scope->loc_cnt = loc_cnt;
}
Symbol* scope_find_local_symbol(const char *name, int len) {
if (!name || len <= 0 || len >= 32) return NULL;
Scope *scope = current_scope;
while (scope) {
for (int i = scope->loc_cnt - 1; i >= 0; i--) {
if (!strncmp(scope->locals[i].name, name, len) && scope->locals[i].name[len] == 0) {
return &scope->locals[i];
}
}
scope = scope->parent;
}
return NULL;
}
int scope_find_local_with_scope(const char *name, int len, Scope **out_scope) {
if (!name || len <= 0 || len >= 32) return -1;
Scope *scope = current_scope;
while (scope) {
for (int i = scope->loc_cnt - 1; i >= 0; i--) {
if (!strncmp(scope->locals[i].name, name, len) && scope->locals[i].name[len] == 0) {
if (out_scope) *out_scope = scope;
return i;
}
}
scope = scope->parent;
}
return -1;
}
long scope_read_var(const char *name, int len) {
Scope *scope = NULL;
int idx = scope_find_local_with_scope(name, len, &scope);
if (idx < 0 || !scope) return 0;
Symbol *sym = &scope->locals[idx];
if (sym->addr < 0 || sym->addr >= scope->mem_size) return 0;
return scope->memory[sym->addr];
}
void scope_write_var(const char *name, int len, long value) {
Scope *scope = NULL;
int idx = scope_find_local_with_scope(name, len, &scope);
if (idx < 0 || !scope) return;
Symbol *sym = &scope->locals[idx];
if (sym->addr < 0 || sym->addr >= scope->mem_size) return;
scope->memory[sym->addr] = value;
}
-54
View File
@@ -1,54 +0,0 @@
#ifndef SCOPE_H
#define SCOPE_H
#include "types.h"
#define SCOPE_MEM_SIZE 10000
#define SCOPE_VAR_MAX 500
typedef struct Scope {
struct Scope *parent;
long *memory;
int mem_size;
Symbol *locals;
int loc_capacity;
int sp;
int bp;
int loc_cnt;
int depth;
} Scope;
extern Scope *current_scope;
extern Scope *root_scope;
Scope* scope_create(Scope *parent);
void scope_destroy(Scope *scope);
Scope* scope_push(void);
Scope* scope_pop(void);
int scope_find_local(const char *name, int len);
int scope_find_local_current_only(const char *name, int len);
Symbol* scope_get_local(int idx);
Symbol* scope_add_local(const char *name, int len, int type, int addr, int is_array);
long scope_mem_read(int addr);
void scope_mem_write(int addr, long value);
int scope_mem_alloc(int size);
int scope_check_sp(int required);
int scope_check_addr(int addr);
void scope_init(void);
void scope_cleanup(void);
void scope_save_state(int *out_sp, int *out_bp, int *out_loc_cnt);
void scope_restore_state(int saved_sp, int saved_bp, int saved_loc_cnt);
void scope_sync_to_globals(void);
void scope_sync_from_globals(void);
Symbol* scope_find_local_symbol(const char *name, int len);
int scope_find_local_with_scope(const char *name, int len, Scope **out_scope);
long scope_read_var(const char *name, int len);
void scope_write_var(const char *name, int len, long value);
#endif
+206
View File
@@ -0,0 +1,206 @@
# RC Standard Library
The RC language standard library is organized into modular categories for easy maintenance and extensibility.
## Structure
```
src/stdlib/
├── stdlib.h # Main registration header
├── stdlib.c # Registers all stdlib modules
├── string/ # String manipulation functions
│ ├── string_stdlib.h
│ └── string_stdlib.c
├── math/ # Mathematical functions
│ ├── math_stdlib.h
│ └── math_stdlib.c
├── io/ # Input/Output operations
│ ├── file_stdlib.h
│ ├── file_stdlib.c # File I/O functions
│ ├── socket_stdlib.h
│ └── socket_stdlib.c # Network socket functions
├── async/ # Asynchronous operations
│ ├── async_stdlib.h
│ └── async_stdlib.c # Async I/O and coroutines
└── constants/ # System constants
├── constants_stdlib.h
└── constants_stdlib.c
```
## Available Functions
### String Functions (string/)
- `strlen(str)` - Get string length
- `strpos(haystack, needle)` - Find substring position
- `substr(str, start, length)` - Extract substring
- `upper(str)` - Convert to uppercase
- `lower(str)` - Convert to lowercase
- `strip(str)` - Trim whitespace
- `replace(str, old, new)` - Replace substring
- `startswith(str, prefix)` - Check if starts with prefix
- `endswith(str, suffix)` - Check if ends with suffix
### Math Functions (math/)
- `sqrt(x)` - Square root
- `pow(base, exp)` - Power function
- `sin(x)`, `cos(x)`, `tan(x)` - Trigonometric functions
- `abs(x)` - Absolute value
- `floor(x)`, `ceil(x)` - Rounding functions
- `int_to_double(x)` - Convert int to double
- `double_to_int(x)` - Convert double to int
- `double_add(a, b)`, `double_sub(a, b)`, `double_mul(a, b)`, `double_div(a, b)` - Double arithmetic
### File I/O Functions (io/file_stdlib.c)
- `fopen(filename, mode)` - Open file
- `fclose(file)` - Close file
- `fread(file, addr, size)` - Read from file
- `fwrite(file, buf, size)` - Write to file
- `fgets(file, max_size)` - Read line from file
- `fputs(file, str)` - Write string to file
- `feof(file)` - Check end of file
- `ftell(file)` - Get file position
- `fseek(file, offset, whence)` - Seek in file
- `fremove(filename)` - Delete file
- `frename(oldname, newname)` - Rename file
### Socket Functions (io/socket_stdlib.c)
- `socket(domain, type, protocol)` - Create socket
- `bind(sockfd, port)` - Bind socket to port
- `listen(sockfd, backlog)` - Listen for connections
- `accept(sockfd)` - Accept connection
- `recv(sockfd, addr, len, flags)` - Receive data
- `send(sockfd, buf, len, flags)` - Send data
- `close(fd)` - Close file descriptor
### Async Functions (async/)
- `async_fread(file, addr, size)` - Async file read
- `async_fwrite(file, buf, size)` - Async file write
- `async_recv(sockfd, addr, len, flags)` - Async socket receive
- `async_send(sockfd, buf, len, flags)` - Async socket send
- `async_wait(id)` - Wait for async operation
- `async_poll(id)` - Poll async operation status
- `async_result(id)` - Get async operation result
- `await(coroutine_id)` - Await coroutine completion
- `gather(coro1, coro2, ...)` - Wait for multiple coroutines
### Constants (constants/)
- `AF_INET()` - IPv4 address family
- `SOCK_STREAM()` - TCP socket type
- `SEEK_SET()` - Seek from beginning
- `SEEK_CUR()` - Seek from current position
- `SEEK_END()` - Seek from end
## Adding New Functions
### 1. Add to Existing Category
To add a new function to an existing category (e.g., a new math function):
1. Open the appropriate category file: `src/stdlib/math/math_stdlib.c`
2. Add your function implementation:
```c
long native_my_function(long *args, int argc) {
if (!args || argc < 1) {
return 0;
}
// Your implementation here
return result;
}
```
3. Register it in the category's registration function:
```c
void register_math_stdlib() {
// ... existing registrations ...
register_native_func("my_function", native_my_function);
}
```
4. Rebuild: `make clean && make`
### 2. Add New Category
To add a new category (e.g., `datetime`):
1. Create directory: `mkdir -p src/stdlib/datetime`
2. Create header file: `src/stdlib/datetime/datetime_stdlib.h`
```c
#ifndef DATETIME_STDLIB_H
#define DATETIME_STDLIB_H
void register_datetime_stdlib();
#endif
```
3. Create implementation: `src/stdlib/datetime/datetime_stdlib.c`
```c
#include <time.h>
#include "../../types.h"
#include "datetime_stdlib.h"
extern void register_native_func(char *name, NativeFunc func);
long native_time(long *args, int argc) {
return (long)time(NULL);
}
void register_datetime_stdlib() {
register_native_func("time", native_time);
}
```
4. Add to `src/stdlib/stdlib.c`:
```c
#include "datetime/datetime_stdlib.h"
void register_stdlib() {
// ... existing registrations ...
register_datetime_stdlib();
}
```
5. Add to Makefile SOURCES:
```makefile
SOURCES = ... \
$(SRC_DIR)/stdlib/datetime/datetime_stdlib.c
```
6. Create build directory in Makefile dirs target:
```makefile
dirs:
# ... existing directories ...
@mkdir -p $(BUILD_DIR)/stdlib/datetime
```
7. Rebuild: `make clean && make`
## Function Signature
All native functions must follow this signature:
```c
long native_function_name(long *args, int argc)
```
Where:
- `args` - Array of long arguments passed from RC code
- `argc` - Number of arguments
- Returns a `long` value
## Best Practices
1. Always validate arguments (check argc and args pointer)
2. Use appropriate error handling
3. Document your functions with comments
4. Test your functions thoroughly
5. Keep functions focused and single-purpose
6. Use the string pool for string allocations (str_pool)
7. Check bounds when accessing memory array
8. Follow the existing code style
## Testing
After making changes:
1. Build: `make clean && make`
2. Run all tests: `make test`
3. Run specific category tests (e.g., `make run-math-test`)
## Architecture Notes
- All stdlib modules are automatically registered when `register_stdlib()` is called from `src/native_functions.c`
- The registration happens during interpreter initialization in `src/main.c`
- Native functions are stored in the global `native_funcs` array
- Function lookup is performed by name during parsing
+17 -6
View File
@@ -5,7 +5,6 @@
#include <sys/socket.h> #include <sys/socket.h>
#include "../../types.h" #include "../../types.h"
#include "../../interpreter.h" #include "../../interpreter.h"
#include "../../scope.h"
#include "async_stdlib.h" #include "async_stdlib.h"
#include "../../debug.h" #include "../../debug.h"
@@ -565,11 +564,23 @@ static long execute_function_sync(int func_idx, long *args, int argc) {
return 0; return 0;
} }
int saved_sp = sp;
int saved_bp = bp;
int saved_pc = pc; int saved_pc = pc;
int saved_loc_cnt = loc_cnt;
long saved_ax = ax; long saved_ax = ax;
int saved_return_flag = return_flag;
scope_push(); if (sp >= MEM_SIZE) return 0;
memory[sp] = bp;
bp = sp++;
if (sp >= MEM_SIZE - 1) {
sp = saved_sp;
bp = saved_bp;
return 0;
}
memory[sp++] = 0;
memory[sp++] = 0;
int param_base = sp; int param_base = sp;
for (int i = 0; i < argc && i < 10 && sp < MEM_SIZE; i++) { for (int i = 0; i < argc && i < 10 && sp < MEM_SIZE; i++) {
@@ -610,11 +621,11 @@ static long execute_function_sync(int func_idx, long *args, int argc) {
long result = ax; long result = ax;
scope_pop(); sp = saved_sp;
bp = saved_bp;
pc = saved_pc; pc = saved_pc;
loc_cnt = saved_loc_cnt;
ax = saved_ax; ax = saved_ax;
return_flag = saved_return_flag;
return result; return result;
} }