UPdate documentation.
This commit is contained in:
@@ -19,3 +19,7 @@ long ax = 0;
|
||||
int return_flag = 0;
|
||||
Coroutine coroutines[MAX_COROUTINES];
|
||||
int coroutine_count = 0;
|
||||
ClassDef classes[MAX_CLASSES];
|
||||
int class_count = 0;
|
||||
Object objects[MAX_OBJECTS];
|
||||
int object_count = 0;
|
||||
|
||||
+80
-3
@@ -69,6 +69,25 @@ void statement() {
|
||||
if (pc >= MAX_TOK || pc >= tk_idx) {
|
||||
error("Token index out of bounds in statement");
|
||||
}
|
||||
if (tokens[pc].type == Class) {
|
||||
pc++;
|
||||
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != Id) pc++;
|
||||
if (pc < MAX_TOK) pc++;
|
||||
if (pc < MAX_TOK && tokens[pc].type == ':') {
|
||||
pc++;
|
||||
while (pc < MAX_TOK && tokens[pc].type != '{') pc++;
|
||||
}
|
||||
if (pc < MAX_TOK && tokens[pc].type == '{') {
|
||||
int brace = 1;
|
||||
pc++;
|
||||
while (brace > 0 && pc < MAX_TOK && pc < tk_idx) {
|
||||
if (tokens[pc].type == '{') brace++;
|
||||
if (tokens[pc].type == '}') brace--;
|
||||
pc++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (tokens[pc].type == '{') {
|
||||
pc++;
|
||||
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != '}' && tokens[pc].type != 0) {
|
||||
@@ -85,7 +104,8 @@ void statement() {
|
||||
}
|
||||
match('}');
|
||||
}
|
||||
else if (tokens[pc].type == Int || tokens[pc].type == Char || tokens[pc].type == Double) {
|
||||
else if (tokens[pc].type == Int || tokens[pc].type == Char || tokens[pc].type == Double ||
|
||||
(tokens[pc].type == Id && find_class(tokens[pc].text, tokens[pc].val) >= 0)) {
|
||||
int var_type = tokens[pc].type;
|
||||
pc++;
|
||||
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != ';') {
|
||||
@@ -239,8 +259,39 @@ void statement() {
|
||||
}
|
||||
|
||||
void scan_functions() {
|
||||
char current_class[32] = "";
|
||||
int in_class = 0;
|
||||
|
||||
int i = 0;
|
||||
while (i < MAX_TOK && i < tk_idx && tokens[i].type != 0) {
|
||||
if (tokens[i].type == Class) {
|
||||
i++;
|
||||
if (i < MAX_TOK && tokens[i].type == Id) {
|
||||
Token *class_name = &tokens[i];
|
||||
int name_len = class_name->val;
|
||||
if (name_len > 31) name_len = 31;
|
||||
strncpy(current_class, class_name->text, name_len);
|
||||
current_class[name_len] = 0;
|
||||
i++;
|
||||
}
|
||||
if (i < MAX_TOK && tokens[i].type == ':') {
|
||||
i++;
|
||||
if (i < MAX_TOK && tokens[i].type == Id) i++;
|
||||
}
|
||||
if (i < MAX_TOK && tokens[i].type == '{') {
|
||||
in_class = 1;
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_class && tokens[i].type == '}') {
|
||||
in_class = 0;
|
||||
current_class[0] = 0;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
int is_async = 0;
|
||||
int offset = 0;
|
||||
if (tokens[i].type == Async) {
|
||||
@@ -248,8 +299,25 @@ void scan_functions() {
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
int is_static = 0;
|
||||
if (tokens[i + offset].type == Static) {
|
||||
is_static = 1;
|
||||
offset++;
|
||||
}
|
||||
|
||||
int is_constructor = 0;
|
||||
int is_destructor = 0;
|
||||
if (tokens[i + offset].type == Constructor) {
|
||||
is_constructor = 1;
|
||||
offset++;
|
||||
} else if (tokens[i + offset].type == Destructor) {
|
||||
is_destructor = 1;
|
||||
offset++;
|
||||
}
|
||||
|
||||
if (i + 2 + offset < MAX_TOK && i + 2 + offset < tk_idx &&
|
||||
(tokens[i+offset].type == Int || tokens[i+offset].type == Char || tokens[i+offset].type == Double) &&
|
||||
(tokens[i+offset].type == Int || tokens[i+offset].type == Char ||
|
||||
tokens[i+offset].type == Double || tokens[i+offset].type == Void) &&
|
||||
tokens[i+1+offset].type == Id && tokens[i+2+offset].type == '(') {
|
||||
|
||||
if (func_cnt >= 100) {
|
||||
@@ -257,7 +325,16 @@ void scan_functions() {
|
||||
}
|
||||
Func *f = &funcs[func_cnt++];
|
||||
Token *name = &tokens[i+1+offset];
|
||||
strncpy(f->name, name->text, name->val); f->name[name->val] = 0;
|
||||
|
||||
if (in_class && current_class[0] != 0 && !is_constructor && !is_destructor) {
|
||||
snprintf(f->name, 31, "%s_%.*s", current_class, name->val, name->text);
|
||||
} else if (in_class && (is_constructor || is_destructor)) {
|
||||
snprintf(f->name, 31, "%s_%s", current_class,
|
||||
is_constructor ? "constructor" : "destructor");
|
||||
} else {
|
||||
strncpy(f->name, name->text, name->val);
|
||||
f->name[name->val] = 0;
|
||||
}
|
||||
f->is_async = is_async;
|
||||
|
||||
i += 3 + offset;
|
||||
|
||||
@@ -9,5 +9,12 @@ int find_native_func(char *name, int len);
|
||||
void statement();
|
||||
void skip_block();
|
||||
void scan_functions();
|
||||
void scan_classes();
|
||||
int find_class(char *name, int len);
|
||||
int find_class_field(int class_idx, char *name, int len);
|
||||
int find_class_method(int class_idx, char *name, int len);
|
||||
long allocate_object(int class_idx);
|
||||
void free_object(long obj_ptr);
|
||||
void call_destructor(long obj_ptr);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "interpreter.h"
|
||||
#include "native_functions.h"
|
||||
#include "preprocessor.h"
|
||||
#include "oop.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 2) {
|
||||
@@ -32,7 +33,9 @@ int main(int argc, char **argv) {
|
||||
register_native_functions();
|
||||
|
||||
tokenize(src_code);
|
||||
scan_classes();
|
||||
scan_functions();
|
||||
link_class_methods();
|
||||
|
||||
int main_idx = find_func("main", 4);
|
||||
if (main_idx == -1 || main_idx >= func_cnt) {
|
||||
|
||||
@@ -0,0 +1,402 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "types.h"
|
||||
#include "interpreter.h"
|
||||
|
||||
int find_class(char *name, int len) {
|
||||
if (!name || len <= 0 || len > 31) return -1;
|
||||
|
||||
for (int i = 0; i < class_count && i < MAX_CLASSES; i++) {
|
||||
if (strlen(classes[i].name) == (size_t)len &&
|
||||
strncmp(classes[i].name, name, len) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int find_class_field(int class_idx, char *name, int len) {
|
||||
if (class_idx < 0 || class_idx >= class_count || class_idx >= MAX_CLASSES) return -1;
|
||||
if (!name || len <= 0 || len > 31) return -1;
|
||||
|
||||
ClassDef *cls = &classes[class_idx];
|
||||
|
||||
for (int i = 0; i < cls->field_count && i < MAX_CLASS_FIELDS; i++) {
|
||||
if (strlen(cls->fields[i].name) == (size_t)len &&
|
||||
strncmp(cls->fields[i].name, name, len) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (cls->parent_class_idx >= 0 && cls->parent_class_idx < class_count) {
|
||||
return find_class_field(cls->parent_class_idx, name, len);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int find_class_method(int class_idx, char *name, int len) {
|
||||
if (class_idx < 0 || class_idx >= class_count || class_idx >= MAX_CLASSES) return -1;
|
||||
if (!name || len <= 0 || len > 31) return -1;
|
||||
|
||||
ClassDef *cls = &classes[class_idx];
|
||||
|
||||
for (int i = 0; i < cls->method_count && i < MAX_CLASS_METHODS; i++) {
|
||||
if (strlen(cls->methods[i].name) == (size_t)len &&
|
||||
strncmp(cls->methods[i].name, name, len) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (cls->parent_class_idx >= 0 && cls->parent_class_idx < class_count) {
|
||||
return find_class_method(cls->parent_class_idx, name, len);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
long allocate_object(int class_idx) {
|
||||
if (class_idx < 0 || class_idx >= class_count || class_idx >= MAX_CLASSES) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (object_count >= MAX_OBJECTS) {
|
||||
error("Maximum number of objects reached");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ClassDef *cls = &classes[class_idx];
|
||||
|
||||
Object *obj = &objects[object_count];
|
||||
obj->class_idx = class_idx;
|
||||
obj->ref_count = 1;
|
||||
obj->marked_for_deletion = 0;
|
||||
|
||||
obj->field_data = (long*)malloc(cls->size * sizeof(long));
|
||||
if (!obj->field_data) {
|
||||
error("Failed to allocate object memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < cls->field_count && i < MAX_CLASS_FIELDS; i++) {
|
||||
obj->field_data[cls->fields[i].offset] = cls->fields[i].default_value;
|
||||
}
|
||||
|
||||
if (cls->parent_class_idx >= 0 && cls->parent_class_idx < class_count) {
|
||||
ClassDef *parent = &classes[cls->parent_class_idx];
|
||||
for (int i = 0; i < parent->field_count && i < MAX_CLASS_FIELDS; i++) {
|
||||
obj->field_data[parent->fields[i].offset] = parent->fields[i].default_value;
|
||||
}
|
||||
}
|
||||
|
||||
object_count++;
|
||||
return (long)obj;
|
||||
}
|
||||
|
||||
void call_destructor(long obj_ptr) {
|
||||
if (obj_ptr == 0) return;
|
||||
|
||||
Object *obj = (Object*)obj_ptr;
|
||||
if (obj < objects || obj >= objects + MAX_OBJECTS) return;
|
||||
if (obj->marked_for_deletion) return;
|
||||
|
||||
obj->marked_for_deletion = 1;
|
||||
|
||||
int class_idx = obj->class_idx;
|
||||
if (class_idx < 0 || class_idx >= class_count || class_idx >= MAX_CLASSES) return;
|
||||
|
||||
ClassDef *cls = &classes[class_idx];
|
||||
|
||||
for (int i = 0; i < cls->method_count && i < MAX_CLASS_METHODS; i++) {
|
||||
if (cls->methods[i].is_destructor) {
|
||||
int func_idx = cls->methods[i].func_idx;
|
||||
if (func_idx >= 0 && func_idx < func_cnt) {
|
||||
int saved_pc = pc;
|
||||
int saved_sp = sp;
|
||||
int saved_bp = bp;
|
||||
int saved_loc_cnt = loc_cnt;
|
||||
long saved_ax = ax;
|
||||
int saved_return_flag = return_flag;
|
||||
|
||||
if (sp >= MEM_SIZE || bp < 0 || bp >= MEM_SIZE) return;
|
||||
|
||||
memory[sp] = bp;
|
||||
bp = sp++;
|
||||
if (sp >= MEM_SIZE) return;
|
||||
|
||||
memory[sp++] = 0;
|
||||
memory[sp++] = saved_loc_cnt;
|
||||
|
||||
if (sp >= MEM_SIZE) return;
|
||||
memory[sp++] = obj_ptr;
|
||||
|
||||
int scan_pc = funcs[func_idx].params_start;
|
||||
if (scan_pc < MAX_TOK && scan_pc < tk_idx && tokens[scan_pc].type != ')') {
|
||||
if (tokens[scan_pc].type == Id) {
|
||||
Token *param_name = &tokens[scan_pc];
|
||||
if (loc_cnt < VAR_MAX) {
|
||||
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 = sp - 1;
|
||||
sym->is_array = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pc = funcs[func_idx].entry_point;
|
||||
return_flag = 0;
|
||||
ax = 0;
|
||||
|
||||
statement();
|
||||
|
||||
pc = saved_pc;
|
||||
sp = saved_sp;
|
||||
bp = saved_bp;
|
||||
loc_cnt = saved_loc_cnt;
|
||||
ax = saved_ax;
|
||||
return_flag = saved_return_flag;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void free_object(long obj_ptr) {
|
||||
if (obj_ptr == 0) return;
|
||||
|
||||
Object *obj = (Object*)obj_ptr;
|
||||
if (obj < objects || obj >= objects + MAX_OBJECTS) return;
|
||||
|
||||
call_destructor(obj_ptr);
|
||||
|
||||
if (obj->field_data) {
|
||||
free(obj->field_data);
|
||||
obj->field_data = NULL;
|
||||
}
|
||||
|
||||
obj->class_idx = -1;
|
||||
obj->ref_count = 0;
|
||||
obj->marked_for_deletion = 0;
|
||||
}
|
||||
|
||||
void link_class_methods() {
|
||||
for (int c = 0; c < class_count && c < MAX_CLASSES; c++) {
|
||||
ClassDef *cls = &classes[c];
|
||||
for (int m = 0; m < cls->method_count && m < MAX_CLASS_METHODS; m++) {
|
||||
ClassMethod *method = &cls->methods[m];
|
||||
|
||||
char full_name[64];
|
||||
snprintf(full_name, 63, "%s_%s", cls->name, method->name);
|
||||
|
||||
extern int find_func(char *name, int len);
|
||||
int func_idx = find_func(full_name, strlen(full_name));
|
||||
if (func_idx >= 0) {
|
||||
method->func_idx = func_idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scan_classes() {
|
||||
int i = 0;
|
||||
while (i < MAX_TOK && i < tk_idx && tokens[i].type != 0) {
|
||||
if (tokens[i].type == Class) {
|
||||
i++;
|
||||
if (i >= MAX_TOK || i >= tk_idx || tokens[i].type != Id) {
|
||||
error("Expected class name");
|
||||
return;
|
||||
}
|
||||
|
||||
if (class_count >= MAX_CLASSES) {
|
||||
error("Too many classes defined");
|
||||
return;
|
||||
}
|
||||
|
||||
ClassDef *cls = &classes[class_count];
|
||||
Token *name = &tokens[i];
|
||||
int name_len = name->val;
|
||||
if (name_len > 31) name_len = 31;
|
||||
strncpy(cls->name, name->text, name_len);
|
||||
cls->name[name_len] = 0;
|
||||
cls->parent_class_idx = -1;
|
||||
cls->field_count = 0;
|
||||
cls->method_count = 0;
|
||||
cls->size = 0;
|
||||
cls->token_start = i + 1;
|
||||
|
||||
i++;
|
||||
|
||||
if (i < MAX_TOK && i < tk_idx && tokens[i].type == ':') {
|
||||
i++;
|
||||
if (i >= MAX_TOK || i >= tk_idx || tokens[i].type != Id) {
|
||||
error("Expected parent class name");
|
||||
return;
|
||||
}
|
||||
|
||||
Token *parent_name = &tokens[i];
|
||||
int parent_idx = find_class(parent_name->text, parent_name->val);
|
||||
if (parent_idx < 0) {
|
||||
error("Parent class not found");
|
||||
return;
|
||||
}
|
||||
cls->parent_class_idx = parent_idx;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i >= MAX_TOK || i >= tk_idx || tokens[i].type != '{') {
|
||||
error("Expected '{' after class name");
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
|
||||
int field_offset = 0;
|
||||
if (cls->parent_class_idx >= 0) {
|
||||
field_offset = classes[cls->parent_class_idx].size;
|
||||
}
|
||||
|
||||
while (i < MAX_TOK && i < tk_idx && tokens[i].type != '}') {
|
||||
int is_static = 0;
|
||||
if (tokens[i].type == Static) {
|
||||
is_static = 1;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (tokens[i].type == Constructor || tokens[i].type == Destructor) {
|
||||
int is_constructor = (tokens[i].type == Constructor);
|
||||
int is_destructor = (tokens[i].type == Destructor);
|
||||
i++;
|
||||
|
||||
if (i >= MAX_TOK || i >= tk_idx || tokens[i].type != '(') {
|
||||
error("Expected '(' after constructor/destructor");
|
||||
return;
|
||||
}
|
||||
|
||||
int func_start = i - 1;
|
||||
|
||||
int brace_count = 0;
|
||||
while (i < MAX_TOK && i < tk_idx) {
|
||||
if (tokens[i].type == '{') brace_count++;
|
||||
if (tokens[i].type == '}') {
|
||||
brace_count--;
|
||||
if (brace_count == 0) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (cls->method_count < MAX_CLASS_METHODS) {
|
||||
ClassMethod *method = &cls->methods[cls->method_count];
|
||||
if (is_constructor) {
|
||||
strncpy(method->name, "constructor", 31);
|
||||
} else {
|
||||
strncpy(method->name, "destructor", 31);
|
||||
}
|
||||
method->func_idx = -1;
|
||||
method->is_static = 0;
|
||||
method->is_constructor = is_constructor;
|
||||
method->is_destructor = is_destructor;
|
||||
cls->method_count++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
int type = tokens[i].type;
|
||||
if (type != Int && type != Char && type != Double && type != Void) {
|
||||
int class_type_idx = find_class(tokens[i].text, tokens[i].val);
|
||||
if (class_type_idx >= 0) {
|
||||
type = Class;
|
||||
} else {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
while (i < MAX_TOK && i < tk_idx && tokens[i].type == '*') i++;
|
||||
|
||||
if (i >= MAX_TOK || i >= tk_idx || tokens[i].type != Id) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
Token *member_name = &tokens[i];
|
||||
i++;
|
||||
|
||||
if (i < MAX_TOK && i < tk_idx && tokens[i].type == '(') {
|
||||
if (cls->method_count < MAX_CLASS_METHODS) {
|
||||
ClassMethod *method = &cls->methods[cls->method_count];
|
||||
int name_len = member_name->val;
|
||||
if (name_len > 31) name_len = 31;
|
||||
strncpy(method->name, member_name->text, name_len);
|
||||
method->name[name_len] = 0;
|
||||
method->func_idx = -1;
|
||||
method->is_static = is_static;
|
||||
method->is_constructor = 0;
|
||||
method->is_destructor = 0;
|
||||
cls->method_count++;
|
||||
}
|
||||
|
||||
int brace_count = 0;
|
||||
while (i < MAX_TOK && i < tk_idx) {
|
||||
if (tokens[i].type == '{') brace_count++;
|
||||
if (tokens[i].type == '}') {
|
||||
brace_count--;
|
||||
if (brace_count == 0) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
if (cls->field_count < MAX_CLASS_FIELDS) {
|
||||
ClassField *field = &cls->fields[cls->field_count];
|
||||
int name_len = member_name->val;
|
||||
if (name_len > 31) name_len = 31;
|
||||
strncpy(field->name, member_name->text, name_len);
|
||||
field->name[name_len] = 0;
|
||||
field->type = type;
|
||||
field->default_value = 0;
|
||||
field->offset = field_offset++;
|
||||
|
||||
if (i < MAX_TOK && i < tk_idx && tokens[i].type == '=') {
|
||||
i++;
|
||||
if (i < MAX_TOK && i < tk_idx) {
|
||||
if (tokens[i].type == Num) {
|
||||
field->default_value = tokens[i].val;
|
||||
i++;
|
||||
} else if (tokens[i].type == Null) {
|
||||
field->default_value = 0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cls->field_count++;
|
||||
}
|
||||
|
||||
if (i < MAX_TOK && i < tk_idx && tokens[i].type == ';') {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cls->size = field_offset;
|
||||
|
||||
if (i < MAX_TOK && i < tk_idx && tokens[i].type == '}') {
|
||||
i++;
|
||||
}
|
||||
|
||||
class_count++;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef OOP_H
|
||||
#define OOP_H
|
||||
|
||||
int find_class(char *name, int len);
|
||||
int find_class_field(int class_idx, char *name, int len);
|
||||
int find_class_method(int class_idx, char *name, int len);
|
||||
long allocate_object(int class_idx);
|
||||
void free_object(long obj_ptr);
|
||||
void call_destructor(long obj_ptr);
|
||||
void scan_classes();
|
||||
void link_class_methods();
|
||||
|
||||
#endif
|
||||
+184
-2
@@ -31,7 +31,59 @@ long factor() {
|
||||
Token *t = &tokens[pc];
|
||||
long val = 0;
|
||||
|
||||
if (t->type == Await) {
|
||||
if (t->type == Null) {
|
||||
pc++;
|
||||
return 0;
|
||||
}
|
||||
else if (t->type == This) {
|
||||
pc++;
|
||||
Symbol *sym = find_local("this", 4) >= 0 ? &locals[find_local("this", 4)] : NULL;
|
||||
if (sym) {
|
||||
return memory[sym->addr];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (t->type == New) {
|
||||
pc++;
|
||||
if (pc >= MAX_TOK || tokens[pc].type != Id) {
|
||||
error("Expected class name after 'new'");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Token *class_name = &tokens[pc];
|
||||
pc++;
|
||||
|
||||
extern int find_class(char *name, int len);
|
||||
int class_idx = find_class(class_name->text, class_name->val);
|
||||
if (class_idx < 0) {
|
||||
error("Unknown class");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pc >= MAX_TOK || tokens[pc].type != '(') {
|
||||
error("Expected '(' after class name");
|
||||
return 0;
|
||||
}
|
||||
pc++;
|
||||
|
||||
if (pc < MAX_TOK && tokens[pc].type != ')') {
|
||||
do {
|
||||
expression();
|
||||
if (pc >= MAX_TOK) return 0;
|
||||
} while (tokens[pc].type == ',' && pc++);
|
||||
}
|
||||
match(')');
|
||||
|
||||
extern long allocate_object(int class_idx);
|
||||
long obj_ptr = allocate_object(class_idx);
|
||||
if (obj_ptr == 0) {
|
||||
error("Failed to allocate object");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return obj_ptr;
|
||||
}
|
||||
else if (t->type == Await) {
|
||||
pc++;
|
||||
match('(');
|
||||
long coro_id = expression();
|
||||
@@ -263,7 +315,137 @@ long unary() {
|
||||
pc++;
|
||||
return -unary();
|
||||
}
|
||||
return factor();
|
||||
|
||||
long val = factor();
|
||||
|
||||
while (pc < MAX_TOK && tokens[pc].type == '.') {
|
||||
pc++;
|
||||
if (pc >= MAX_TOK || tokens[pc].type != Id) {
|
||||
error("Expected field or method name after '.'");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Token *member = &tokens[pc];
|
||||
pc++;
|
||||
|
||||
if (val == 0) {
|
||||
error("Null pointer dereference");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Object *obj = (Object*)val;
|
||||
if (obj < objects || obj >= objects + MAX_OBJECTS) {
|
||||
error("Invalid object pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int class_idx = obj->class_idx;
|
||||
if (class_idx < 0 || class_idx >= class_count) {
|
||||
error("Invalid class index");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pc < MAX_TOK && tokens[pc].type == '(') {
|
||||
extern int find_class_method(int class_idx, char *name, int len);
|
||||
int method_idx = find_class_method(class_idx, member->text, member->val);
|
||||
if (method_idx < 0) {
|
||||
error("Unknown method");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int func_idx = classes[class_idx].methods[method_idx].func_idx;
|
||||
if (func_idx < 0 || func_idx >= func_cnt) {
|
||||
error("Invalid method function index");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pc++;
|
||||
long args[10];
|
||||
int argc = 0;
|
||||
args[argc++] = val;
|
||||
|
||||
if (pc < MAX_TOK && tokens[pc].type != ')') {
|
||||
do {
|
||||
if (argc >= 10) break;
|
||||
args[argc++] = expression();
|
||||
if (pc >= MAX_TOK) return 0;
|
||||
} while (tokens[pc].type == ',' && pc++);
|
||||
}
|
||||
match(')');
|
||||
|
||||
int saved_pc = pc;
|
||||
int saved_sp = sp;
|
||||
int saved_bp = bp;
|
||||
int saved_loc_cnt = loc_cnt;
|
||||
|
||||
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;
|
||||
|
||||
for (int i = 0; i < argc && i < 10; i++) {
|
||||
if (sp >= MEM_SIZE) break;
|
||||
memory[sp++] = args[i];
|
||||
}
|
||||
|
||||
int scan_pc = funcs[func_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 || tokens[scan_pc].type == Id) {
|
||||
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 = saved_sp + 3 + param_idx;
|
||||
sym->is_array = 0;
|
||||
param_idx++;
|
||||
}
|
||||
}
|
||||
scan_pc++;
|
||||
}
|
||||
|
||||
pc = funcs[func_idx].entry_point;
|
||||
return_flag = 0;
|
||||
statement();
|
||||
|
||||
val = ax;
|
||||
ax = 0;
|
||||
return_flag = 0;
|
||||
|
||||
pc = saved_pc;
|
||||
sp = saved_sp;
|
||||
bp = saved_bp;
|
||||
loc_cnt = saved_loc_cnt;
|
||||
} else {
|
||||
extern int find_class_field(int class_idx, char *name, int len);
|
||||
int field_idx = find_class_field(class_idx, member->text, member->val);
|
||||
if (field_idx < 0) {
|
||||
error("Unknown field");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int offset = classes[class_idx].fields[field_idx].offset;
|
||||
if (offset < 0 || offset >= classes[class_idx].size) {
|
||||
error("Invalid field offset");
|
||||
return 0;
|
||||
}
|
||||
|
||||
val = obj->field_data[offset];
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
long term() {
|
||||
|
||||
@@ -44,6 +44,15 @@ void tokenize(char *src) {
|
||||
else if (!strcmp(buf, "continue")) t->type = Continue;
|
||||
else if (!strcmp(buf, "async")) t->type = Async;
|
||||
else if (!strcmp(buf, "await")) t->type = Await;
|
||||
else if (!strcmp(buf, "class")) t->type = Class;
|
||||
else if (!strcmp(buf, "new")) t->type = New;
|
||||
else if (!strcmp(buf, "constructor")) t->type = Constructor;
|
||||
else if (!strcmp(buf, "destructor")) t->type = Destructor;
|
||||
else if (!strcmp(buf, "static")) t->type = Static;
|
||||
else if (!strcmp(buf, "super")) t->type = Super;
|
||||
else if (!strcmp(buf, "this")) t->type = This;
|
||||
else if (!strcmp(buf, "void")) t->type = Void;
|
||||
else if (!strcmp(buf, "null")) t->type = Null;
|
||||
else t->type = Id;
|
||||
|
||||
t->val = len;
|
||||
|
||||
+44
-1
@@ -9,7 +9,8 @@
|
||||
|
||||
enum {
|
||||
Num = 128, Dbl, Str, Id, Int, Char, Double, Else, If, While, Return, Printf,
|
||||
Assign, Eq, Ne, Lt, Gt, Le, Ge, Or, And, Inc, Dec, Break, Continue, Async, Await
|
||||
Assign, Eq, Ne, Lt, Gt, Le, Ge, Or, And, Inc, Dec, Break, Continue, Async, Await,
|
||||
Class, New, Constructor, Destructor, Static, Super, This, Void, Null
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@@ -59,6 +60,44 @@ typedef struct Coroutine {
|
||||
long memory_saved[MEM_SIZE];
|
||||
} Coroutine;
|
||||
|
||||
#define MAX_CLASSES 100
|
||||
#define MAX_CLASS_FIELDS 50
|
||||
#define MAX_CLASS_METHODS 50
|
||||
#define MAX_OBJECTS 1000
|
||||
|
||||
typedef struct {
|
||||
char name[32];
|
||||
int type;
|
||||
long default_value;
|
||||
int offset;
|
||||
} ClassField;
|
||||
|
||||
typedef struct {
|
||||
char name[32];
|
||||
int func_idx;
|
||||
int is_static;
|
||||
int is_constructor;
|
||||
int is_destructor;
|
||||
} ClassMethod;
|
||||
|
||||
typedef struct {
|
||||
char name[32];
|
||||
int parent_class_idx;
|
||||
ClassField fields[MAX_CLASS_FIELDS];
|
||||
int field_count;
|
||||
ClassMethod methods[MAX_CLASS_METHODS];
|
||||
int method_count;
|
||||
int size;
|
||||
int token_start;
|
||||
} ClassDef;
|
||||
|
||||
typedef struct {
|
||||
int class_idx;
|
||||
long *field_data;
|
||||
int ref_count;
|
||||
int marked_for_deletion;
|
||||
} Object;
|
||||
|
||||
extern Token tokens[MAX_TOK];
|
||||
extern int tk_idx;
|
||||
extern int pc;
|
||||
@@ -78,5 +117,9 @@ extern long ax;
|
||||
extern int return_flag;
|
||||
extern Coroutine coroutines[MAX_COROUTINES];
|
||||
extern int coroutine_count;
|
||||
extern ClassDef classes[MAX_CLASSES];
|
||||
extern int class_count;
|
||||
extern Object objects[MAX_OBJECTS];
|
||||
extern int object_count;
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user