anonymous modules.

main
bog 2024-04-07 20:43:13 +02:00
parent b5f0713fee
commit 4d0edad298
22 changed files with 525 additions and 43 deletions

View File

@ -8,7 +8,7 @@ int main(int argc, char** argv)
{ {
errors_init(); errors_init();
struct module module; struct module module;
module_init(&module); module_init(&module, argv[1]);
module_load_source(&module, argv[1]); module_load_source(&module, argv[1]);
int status = module_compile(&module); int status = module_compile(&module);

View File

@ -9,6 +9,8 @@ EXPR ::=
| IF | IF
| return EXPR | return EXPR
| FUN_DECL | FUN_DECL
| MOD_ACCESS
MOD_ACCESS ::= EXPR mod_access ident
FUN_DECL ::= FUN_DECL ::=
| fun ident opar PARAMS cpar EXPR* end | fun ident opar PARAMS cpar EXPR* end
IF ::= if EXPR BLOCK (else (BLOCK | IF))? IF ::= if EXPR BLOCK (else (BLOCK | IF))?
@ -32,7 +34,10 @@ LITERAL ::=
| ident | ident
| FUN | FUN
| CALL | CALL
CALL ::= ident opar ARGS cpar | MODULE
MODULE ::= module EXPR* end
CALL ::=
| (ident|MOD_ACCESS) opar ARGS cpar
ARGS ::= (EXPR (comma EXPR)*)? ARGS ::= (EXPR (comma EXPR)*)?
FUN ::= fun opar PARAMS cpar EXPR* end FUN ::= fun opar PARAMS cpar EXPR* end
PARAMS ::= (EXPR (comma EXPR)*)? PARAMS ::= (EXPR (comma EXPR)*)?

12
features/mod.sk Normal file
View File

@ -0,0 +1,12 @@
var m = module
var x = 32
var y = "bim"
fun add(x, y)
return x + y
end
end
assert m::x eq 32
assert m::y eq "bim"
assert m::add(7, 2) eq 9

View File

@ -7,11 +7,18 @@
struct state; struct state;
struct mod
{
char* name;
struct module* module;
};
struct compiler struct compiler
{ {
struct vec var_names; struct vec var_names;
struct vec modules;
}; };
void mod_free(struct mod* self);
void compiler_init(struct compiler* self); void compiler_init(struct compiler* self);
void compiler_free(struct compiler* self); void compiler_free(struct compiler* self);

View File

@ -8,16 +8,18 @@
struct module struct module
{ {
char* name;
struct str source; struct str source;
struct prog prog; struct prog* prog;
struct sym sym; struct sym* sym;
struct state state; struct state* state;
}; };
void module_init(struct module* self); void module_init(struct module* self, char const* name);
struct module* module_new_clone(struct module* self);
void module_free(struct module* self); void module_free(struct module* self);
void module_load_source(struct module* self, void module_load_source(struct module* self,
char const* path); char const* path);
int module_compile(struct module* self); int module_compile(struct module* self);

View File

@ -15,7 +15,8 @@ G(NODE_LT), G(NODE_LE), G(NODE_GT), G(NODE_GE), \
G(NODE_EQUAL), G(NODE_NOT_EQUAL), G(NODE_VAR_DECL), \ G(NODE_EQUAL), G(NODE_NOT_EQUAL), G(NODE_VAR_DECL), \
G(NODE_CONST_DECL), G(NODE_IDENT), G(NODE_ASSIGN), \ G(NODE_CONST_DECL), G(NODE_IDENT), G(NODE_ASSIGN), \
G(NODE_BLOCK), G(NODE_IF), G(NODE_FUN), G(NODE_PARAMS), \ G(NODE_BLOCK), G(NODE_IF), G(NODE_FUN), G(NODE_PARAMS), \
G(NODE_RETURN), G(NODE_CALL), G(NODE_ARGS) G(NODE_RETURN), G(NODE_CALL), G(NODE_ARGS), G(NODE_MODULE), \
G(NODE_MOD_ACCESS)
SK_ENUM_H(NodeKind, NODE_KIND); SK_ENUM_H(NodeKind, NODE_KIND);

View File

@ -37,6 +37,8 @@ struct node* parser_try_usub(struct parser* self);
struct node* parser_try_not(struct parser* self); struct node* parser_try_not(struct parser* self);
struct node* parser_try_pow(struct parser* self); struct node* parser_try_pow(struct parser* self);
struct node* parser_try_literal(struct parser* self); struct node* parser_try_literal(struct parser* self);
struct node* parser_try_mod_access(struct parser* self);
struct node* parser_try_module(struct parser* self);
struct node* parser_try_call(struct parser* self); struct node* parser_try_call(struct parser* self);
struct node* parser_try_args(struct parser* self); struct node* parser_try_args(struct parser* self);
struct node* parser_try_fun(struct parser* self); struct node* parser_try_fun(struct parser* self);

View File

@ -15,7 +15,7 @@ G(OP_BR), G(OP_BRF), G(OP_LT), G(OP_GT), \
G(OP_EQUAL), G(OP_LOCAL_STORE), G(OP_LOCAL_LOAD), \ G(OP_EQUAL), G(OP_LOCAL_STORE), G(OP_LOCAL_LOAD), \
G(OP_CALL), G(OP_RET), G(OP_MAKE_REF), \ G(OP_CALL), G(OP_RET), G(OP_MAKE_REF), \
G(OP_CLOSURE_LOAD), G(OP_CLOSURE_STORE), \ G(OP_CLOSURE_LOAD), G(OP_CLOSURE_STORE), \
G(OP_GLOBAL_LOAD) G(OP_GLOBAL_LOAD), G(OP_MODULE_LOAD)
SK_ENUM_H(Opcode, OPCODE); SK_ENUM_H(Opcode, OPCODE);

View File

@ -50,9 +50,11 @@ void stack_value_init(struct stack_value* self,
void stack_value_free(struct stack_value* self); void stack_value_free(struct stack_value* self);
void frame_init(struct frame* self); void frame_init(struct frame* self);
struct frame* frame_new_clone(struct frame* self);
void frame_free(struct frame* self); void frame_free(struct frame* self);
void state_init(struct state* self); void state_init(struct state* self);
struct state* state_new_clone(struct state* self);
void state_free(struct state* self); void state_free(struct state* self);
SK state_make_ref(struct state* self); SK state_make_ref(struct state* self);
@ -79,6 +81,7 @@ SK state_push_float(struct state* self, double real, int line);
SK state_push_string(struct state* self, char const* str, int line); SK state_push_string(struct state* self, char const* str, int line);
SK state_push_fun(struct state* self, struct fun* fun, int line); SK state_push_fun(struct state* self, struct fun* fun, int line);
SK state_push_ref(struct state* self, size_t ref, int line); SK state_push_ref(struct state* self, size_t ref, int line);
SK state_push_mod(struct state* self, struct module* mod, int line);
struct local* state_try_get_local(struct state* self, int id); struct local* state_try_get_local(struct state* self, int id);
@ -97,6 +100,9 @@ void state_global_load(struct state* self,
void state_closure_load(struct state* self, void state_closure_load(struct state* self,
int id); int id);
void state_module_load(struct state* self,
int id);
TypeKind state_common_num_type(struct state* self, SK lhs, SK rhs); TypeKind state_common_num_type(struct state* self, SK lhs, SK rhs);
TypeKind state_type(struct state* self, SK value); TypeKind state_type(struct state* self, SK value);
double state_as_real(struct state* self, SK lhs); double state_as_real(struct state* self, SK lhs);

View File

@ -36,6 +36,7 @@ struct env* env_new_clone(struct env* self);
void env_free(struct env* self); void env_free(struct env* self);
struct symbol* env_try_get(struct env* self, char const* name); struct symbol* env_try_get(struct env* self, char const* name);
struct symbol* env_try_get_by_id(struct env* self, int id);
void symbol_init(struct symbol* self, void symbol_init(struct symbol* self,
int id, int id,
@ -57,5 +58,6 @@ void sym_open_scope(struct sym* self);
void sym_close_scope(struct sym* self); void sym_close_scope(struct sym* self);
struct symbol* sym_try_get(struct sym* self, char const* name); struct symbol* sym_try_get(struct sym* self, char const* name);
struct symbol* sym_try_get_by_id(struct sym* self, int id);
#endif #endif

View File

@ -16,7 +16,8 @@ G(TOKEN_LT), G(TOKEN_LE), G(TOKEN_GT), G(TOKEN_GE), \
G(TOKEN_EQUAL), G(TOKEN_NOT_EQUAL), G(TOKEN_VAR), \ G(TOKEN_EQUAL), G(TOKEN_NOT_EQUAL), G(TOKEN_VAR), \
G(TOKEN_CONST), G(TOKEN_ASSIGN), G(TOKEN_IDENT), \ G(TOKEN_CONST), G(TOKEN_ASSIGN), G(TOKEN_IDENT), \
G(TOKEN_BEGIN), G(TOKEN_END), G(TOKEN_IF), G(TOKEN_ELSE), \ G(TOKEN_BEGIN), G(TOKEN_END), G(TOKEN_IF), G(TOKEN_ELSE), \
G(TOKEN_FUN), G(TOKEN_RETURN), G(TOKEN_COMMA) G(TOKEN_FUN), G(TOKEN_RETURN), G(TOKEN_COMMA), G(TOKEN_MODULE), \
G(TOKEN_MOD_ACCESS)
SK_ENUM_H(TokenKind, TOKEN_KIND); SK_ENUM_H(TokenKind, TOKEN_KIND);

View File

@ -8,7 +8,7 @@
#define TYPE_KIND(G) \ #define TYPE_KIND(G) \
G(TYPE_INT), G(TYPE_BOOL), G(TYPE_FLOAT), \ G(TYPE_INT), G(TYPE_BOOL), G(TYPE_FLOAT), \
G(TYPE_STRING), G(TYPE_FUN), G(TYPE_REF), \ G(TYPE_STRING), G(TYPE_FUN), G(TYPE_REF), \
G(TYPE_NATIVE_FUN) G(TYPE_NATIVE_FUN), G(TYPE_MODULE)
SK_ENUM_H(TypeKind, TYPE_KIND); SK_ENUM_H(TypeKind, TYPE_KIND);
@ -21,6 +21,7 @@ union val
struct fun* fun; struct fun* fun;
struct nfun* nfun; struct nfun* nfun;
size_t ref; size_t ref;
struct module* mod;
}; };
struct value struct value

View File

@ -2,17 +2,26 @@
#include "token.h" #include "token.h"
#include "state.h" #include "state.h"
#include "natives.h" #include "natives.h"
#include "module.h"
void compiler_init(struct compiler* self) void compiler_init(struct compiler* self)
{ {
assert(self); assert(self);
vec_init(&self->var_names); vec_init(&self->var_names);
vec_init(&self->modules);
}
void mod_free(struct mod* self)
{
free(self->name);
} }
void compiler_free(struct compiler* self) void compiler_free(struct compiler* self)
{ {
assert(self); assert(self);
vec_free(&self->var_names); vec_free(&self->var_names);
vec_free_elements(&self->modules, (void*) mod_free);
vec_free(&self->modules);
} }
void compiler_compile(struct compiler* self, void compiler_compile(struct compiler* self,
@ -209,6 +218,89 @@ void compiler_compile(struct compiler* self,
prog_add_instr(prog, OP_RET, SK_NO_PARAM); prog_add_instr(prog, OP_RET, SK_NO_PARAM);
} break; } break;
case NODE_MODULE: {
char* name = "";
if (self->var_names.size > 0)
{
name = self->var_names.data[
self->var_names.size - 1
];
}
struct module* mod = malloc(sizeof(struct module));
module_init(mod, name);
for (size_t i=0; i<node->children.size; i++)
{
struct node* child = node->children.data[i];
compiler_compile(
self,
child,
mod->prog,
mod->sym,
mod->state
);
}
struct value* val = malloc(sizeof(struct value));
union val v;
v.mod = mod;
value_init(val, TYPE_MODULE, v, node->token->line);
int id = prog_add_constant(prog, val);
prog_add_instr(prog, OP_PUSH, id);
prog_add_instr(prog, OP_MAKE_REF, SK_NO_PARAM);
struct mod* mymod = malloc(sizeof(struct mod));
mymod->name = strdup(name);
mymod->module = mod;
vec_push(&self->modules, mymod);
} break;
case NODE_MOD_ACCESS: {
struct node* mod_name = node->children.data[0];
struct node* target = node->children.data[1];
struct mod* mod = NULL;
for (size_t i=0; i<self->modules.size; i++)
{
struct mod* m = self->modules.data[i];
if (strcmp(m->name, mod_name->token->value) == 0)
{
mod = m;
break;
}
}
if (!mod)
{
errors_push(node->token->line,
"unknown module '%s'.",
mod_name->token->value);
}
struct symbol* symbol = sym_try_get(
mod->module->sym,
target->token->value
);
assert(symbol);
compiler_compile(
self,
mod_name,
prog,
sym,
state
);
prog_add_instr(prog, OP_MODULE_LOAD, symbol->id);
} break;
case NODE_FUN: { case NODE_FUN: {
struct fun* fun = malloc(sizeof(struct fun)); struct fun* fun = malloc(sizeof(struct fun));
struct prog* p = malloc(sizeof(struct prog)); struct prog* p = malloc(sizeof(struct prog));

View File

@ -2,6 +2,7 @@
#include "sym.h" #include "sym.h"
#include "fun.h" #include "fun.h"
#include "nfun.h" #include "nfun.h"
#include "module.h"
void exec_init(struct exec* self) void exec_init(struct exec* self)
{ {
@ -55,6 +56,10 @@ void exec_execute(struct exec* self,
self->pc++; self->pc++;
} break; } break;
case OP_MODULE_LOAD: {
state_module_load(state, param);
self->pc++;
} break;
case OP_ASSERT_EQ: { case OP_ASSERT_EQ: {
SK rhs = state_pop(state); SK rhs = state_pop(state);
SK lhs = state_pop(state); SK lhs = state_pop(state);
@ -117,7 +122,6 @@ void exec_execute(struct exec* self,
state, state,
f->val.ref f->val.ref
); );
assert(val_fun); assert(val_fun);
if (val_fun->type == TYPE_NATIVE_FUN) if (val_fun->type == TYPE_NATIVE_FUN)
@ -224,6 +228,24 @@ void exec_execute(struct exec* self,
); );
} break; } break;
case TYPE_MODULE: {
struct module* mod =
constant->val.mod;
struct exec exec;
exec_init(&exec);
exec_execute(&exec, mod->state, mod->prog);
exec_free(&exec);
state_push_mod(
state,
mod,
constant->line
);
} break;
case TYPE_INT: { case TYPE_INT: {
state_push_int( state_push_int(
state, state,

View File

@ -90,7 +90,8 @@ bool lexer_is_sep(struct lexer* self, size_t index)
|| c == '<' || c == '<'
|| c == '>' || c == '>'
|| c == ',' || c == ','
|| c == '='; || c == '='
|| c == ':';
} }
bool lexer_next_nth_is(struct lexer* self, TokenKind kind, int nth) bool lexer_next_nth_is(struct lexer* self, TokenKind kind, int nth)
@ -179,6 +180,7 @@ struct token* lexer_try_new_next(struct lexer* self)
{ {
return tok; return tok;
} }
SK_SCAN_TEXT("::", TOKEN_MOD_ACCESS);
SK_SCAN_TEXT("<=", TOKEN_LE); SK_SCAN_TEXT("<=", TOKEN_LE);
SK_SCAN_TEXT(">=", TOKEN_GE); SK_SCAN_TEXT(">=", TOKEN_GE);
SK_SCAN_TEXT("==", TOKEN_EQUAL); SK_SCAN_TEXT("==", TOKEN_EQUAL);
@ -199,6 +201,7 @@ struct token* lexer_try_new_next(struct lexer* self)
SK_SCAN_KEYWORD("return", TOKEN_RETURN, NULL); SK_SCAN_KEYWORD("return", TOKEN_RETURN, NULL);
SK_SCAN_KEYWORD("if", TOKEN_IF, NULL); SK_SCAN_KEYWORD("if", TOKEN_IF, NULL);
SK_SCAN_KEYWORD("else", TOKEN_ELSE, NULL); SK_SCAN_KEYWORD("else", TOKEN_ELSE, NULL);
SK_SCAN_KEYWORD("module", TOKEN_MODULE, NULL);
SK_SCAN_KEYWORD("begin", TOKEN_BEGIN, NULL); SK_SCAN_KEYWORD("begin", TOKEN_BEGIN, NULL);
SK_SCAN_KEYWORD("end", TOKEN_END, NULL); SK_SCAN_KEYWORD("end", TOKEN_END, NULL);
SK_SCAN_KEYWORD("var", TOKEN_VAR, NULL); SK_SCAN_KEYWORD("var", TOKEN_VAR, NULL);

View File

@ -5,24 +5,63 @@
#include "exec.h" #include "exec.h"
#include "natives.h" #include "natives.h"
void module_init(struct module* self) void module_init(struct module* self, char const* name)
{ {
assert(self); assert(self);
self->name = strdup(name);
str_init(&self->source); str_init(&self->source);
prog_init(&self->prog);
state_init(&self->state);
sym_init(&self->sym);
natives_populate(&self->state, &self->sym); self->prog = malloc(sizeof(struct prog));
prog_init(self->prog);
self->state = malloc(sizeof(struct state));
state_init(self->state);
self->sym = malloc(sizeof(struct sym));
sym_init(self->sym);
natives_populate(self->state, self->sym);
}
struct module* module_new_clone(struct module* self)
{
assert(self);
struct module* clone = malloc(sizeof(struct module));
module_init(clone, self->name);
prog_free(clone->prog);
free(clone->prog);
state_free(clone->state);
free(clone->state);
sym_free(clone->sym);
free(clone->sym);
// struct str source;
if (self->source.value)
{
str_extend(&clone->source, self->source.value);
}
// struct prog prog;
clone->prog = prog_new_clone(self->prog);
// struct sym sym;
clone->sym = sym_new_clone(self->sym);
// struct state state;
clone->state = state_new_clone(self->state);
return clone;
} }
void module_free(struct module* self) void module_free(struct module* self)
{ {
assert(self); assert(self);
str_free(&self->source); str_free(&self->source);
prog_free(&self->prog); prog_free(self->prog);
sym_free(&self->sym); free(self->prog);
state_free(&self->state); sym_free(self->sym);
free(self->sym);
state_free(self->state);
free(self->state);
free(self->name);
} }
void module_load_source(struct module* self, void module_load_source(struct module* self,
@ -59,13 +98,13 @@ int module_compile(struct module* self)
struct compiler compiler; struct compiler compiler;
compiler_init(&compiler); compiler_init(&compiler);
compiler_compile(&compiler, root, &self->prog, &self->sym, compiler_compile(&compiler, root, self->prog, self->sym,
&self->state); self->state);
struct exec exec; struct exec exec;
exec_init(&exec); exec_init(&exec);
exec_execute(&exec, &self->state, &self->prog); exec_execute(&exec, self->state, self->prog);
if (!errors_ok()) if (!errors_ok())
{ {
@ -82,6 +121,5 @@ free_node:
free(root); free(root);
parser_free(&parser); parser_free(&parser);
return errors_ok() ? EXIT_SUCCESS : EXIT_FAILURE; return errors_ok() ? EXIT_SUCCESS : EXIT_FAILURE;
} }

View File

@ -116,10 +116,10 @@ struct node* parser_try_expr(struct parser* self)
return SK_TRY(parser_try_const_decl); return SK_TRY(parser_try_const_decl);
} }
if (lexer_next_is(&self->lexer, TOKEN_IDENT) // ASSIGN
&& lexer_next_nth_is(&self->lexer, TOKEN_ASSIGN, 1))
{ {
return SK_TRY(parser_try_assign); struct node* n = SK_TRY(parser_try_assign);
if (n) { return n; }
} }
if (lexer_next_is(&self->lexer, TOKEN_VAR)) if (lexer_next_is(&self->lexer, TOKEN_VAR))
@ -356,15 +356,11 @@ struct node* parser_try_if(struct parser* self)
struct node* parser_try_assign(struct parser* self) struct node* parser_try_assign(struct parser* self)
{ {
assert(self); assert(self);
struct node* ident = SK_TRY(parser_try_or);
if (!lexer_next_is(&self->lexer, TOKEN_IDENT)) if (!ident)
{ {
return NULL; return NULL;
} }
struct node* ident = malloc(sizeof(struct node));
node_init(ident, NODE_IDENT, lexer_try_new_next(&self->lexer));
if (!lexer_next_is(&self->lexer, TOKEN_ASSIGN)) if (!lexer_next_is(&self->lexer, TOKEN_ASSIGN))
{ {
node_free(ident); free(ident); node_free(ident); free(ident);
@ -886,6 +882,11 @@ struct node* parser_try_literal(struct parser* self)
{ {
assert(self); assert(self);
{
struct node* node = SK_TRY(parser_try_call);
if (node) { return node; }
}
if (lexer_next_is(&self->lexer, TOKEN_OPAR)) if (lexer_next_is(&self->lexer, TOKEN_OPAR))
{ {
lexer_consume_next(&self->lexer); lexer_consume_next(&self->lexer);
@ -908,10 +909,10 @@ struct node* parser_try_literal(struct parser* self)
return node; return node;
} }
if (lexer_next_is(&self->lexer, TOKEN_IDENT)
&& lexer_next_nth_is(&self->lexer, TOKEN_OPAR, 1)) if (lexer_next_nth_is(&self->lexer, TOKEN_MOD_ACCESS, 1))
{ {
return SK_TRY(parser_try_call); return SK_TRY(parser_try_mod_access);
} }
if (lexer_next_is(&self->lexer, TOKEN_IDENT)) if (lexer_next_is(&self->lexer, TOKEN_IDENT))
@ -930,10 +931,15 @@ struct node* parser_try_literal(struct parser* self)
return SK_TRY(parser_try_fun); return SK_TRY(parser_try_fun);
} }
if (lexer_next_is(&self->lexer, TOKEN_MODULE))
{
return SK_TRY(parser_try_module);
}
return SK_TRY(parser_try_builtin); return SK_TRY(parser_try_builtin);
} }
struct node* parser_try_call(struct parser* self) struct node* parser_try_mod_access(struct parser* self)
{ {
assert(self); assert(self);
@ -942,8 +948,109 @@ struct node* parser_try_call(struct parser* self)
return NULL; return NULL;
} }
struct node* ident = malloc(sizeof(struct node)); struct token* lhs_tok = lexer_try_new_next(&self->lexer);
node_init(ident, NODE_IDENT, lexer_try_new_next(&self->lexer)); struct node* lhs = malloc(sizeof(struct node));
node_init(lhs, NODE_IDENT, lhs_tok);
if (!lhs)
{
token_free(lhs_tok);
free(lhs_tok);
return NULL;
}
if (!lexer_next_is(&self->lexer, TOKEN_MOD_ACCESS))
{
node_free(lhs);
free(lhs);
return NULL;
}
struct token* access_tok = lexer_try_new_next(&self->lexer);
if (!lexer_next_is(&self->lexer, TOKEN_IDENT))
{
node_free(lhs);
free(lhs);
token_free(access_tok);
free(access_tok);
return NULL;
}
struct token* rhs_tok = lexer_try_new_next(&self->lexer);
struct node* rhs = malloc(sizeof(struct node));
node_init(rhs, NODE_IDENT, rhs_tok);
struct node* node = malloc(sizeof(struct node));
node_init(node, NODE_MOD_ACCESS, access_tok);
node_push_new_child(node, lhs);
node_push_new_child(node, rhs);
return node;
}
struct node* parser_try_module(struct parser* self)
{
assert(self);
if (!lexer_next_is(&self->lexer, TOKEN_MODULE))
{
return NULL;
}
struct node* node = malloc(sizeof(struct node));
node_init(node, NODE_MODULE, lexer_try_new_next(&self->lexer));
struct node* expr = NULL;
do
{
expr = SK_TRY(parser_try_expr);
if (expr)
{
node_push_new_child(node, expr);
}
}
while (expr);
if (!lexer_next_is(&self->lexer, TOKEN_END))
{
node_free(node);
free(node);
return NULL;
}
lexer_consume_next(&self->lexer);
return node;
}
struct node* parser_try_call(struct parser* self)
{
assert(self);
struct node* lhs = NULL;
if (lexer_next_is(&self->lexer, TOKEN_IDENT)
&& !lexer_next_nth_is(&self->lexer, TOKEN_MOD_ACCESS, 1))
{
struct node* ident = malloc(sizeof(struct node));
node_init(ident, NODE_IDENT,
lexer_try_new_next(&self->lexer));
if (!ident)
{
return NULL;
}
lhs = ident;
}
else
{
lhs = SK_TRY(parser_try_mod_access);
if (!lhs)
{
return NULL;
}
}
struct token* tok = malloc(sizeof(struct token)); struct token* tok = malloc(sizeof(struct token));
token_init(tok, TOKEN_BEGIN, "", self->lexer.context.line); token_init(tok, TOKEN_BEGIN, "", self->lexer.context.line);
@ -951,7 +1058,7 @@ struct node* parser_try_call(struct parser* self)
struct node* node = malloc(sizeof(struct node)); struct node* node = malloc(sizeof(struct node));
node_init(node, NODE_CALL, tok); node_init(node, NODE_CALL, tok);
node_push_new_child(node, ident); node_push_new_child(node, lhs);
if (!lexer_next_is(&self->lexer, TOKEN_OPAR)) if (!lexer_next_is(&self->lexer, TOKEN_OPAR))
{ {

View File

@ -1,4 +1,5 @@
#include "state.h" #include "state.h"
#include "module.h"
#include "nfun.h" #include "nfun.h"
void stack_value_init(struct stack_value* self, void stack_value_init(struct stack_value* self,
@ -27,6 +28,43 @@ void frame_init(struct frame* self)
self->fun = NULL; self->fun = NULL;
} }
struct frame* frame_new_clone(struct frame* self)
{
struct frame* clone = malloc(sizeof(struct frame));
frame_init(clone);
// struct vec stack_values;
for (size_t i=0; i<self->stack_values.size; i++)
{
struct stack_value* sv = self->stack_values.data[i];
struct stack_value* val = malloc(sizeof(struct stack_value));
stack_value_init(val, sv->addr,
value_new_clone(sv->value));
vec_push(&clone->stack_values, val);
}
// struct vec locals;
for (size_t i=0; i<self->locals.size; i++)
{
struct local const* loc = self->locals.data[i];
struct local* local = malloc(sizeof(struct local));
local->id = loc->id;
local->addr = loc->addr;
vec_push(&clone->locals, local);
}
// struct vec stack;
for (size_t i=0; i<self->stack.size; i++)
{
vec_push(&clone->stack, self->stack.data[i]);
}
// struct fun* fun;
clone->fun = self->fun;
return clone;
}
void frame_free(struct frame* self) void frame_free(struct frame* self)
{ {
vec_free_elements(&self->stack_values, (void*) stack_value_free); vec_free_elements(&self->stack_values, (void*) stack_value_free);
@ -47,6 +85,42 @@ void state_init(struct state* self)
vec_init(&self->globals); vec_init(&self->globals);
} }
struct state* state_new_clone(struct state* self)
{
assert(self);
struct state* clone = malloc(sizeof(struct state));
state_init(clone);
for (size_t i=0; i<self->frames.size; i++)
{
struct frame* frame = self->frames.data[i];
vec_push(&clone->frames, frame_new_clone(frame));
}
// size_t addr;
clone->addr = self->addr;
// int global_id;
clone->global_id = self->global_id;
// struct vec globals;
for (size_t i=0; i<self->globals.size; i++)
{
struct global const* glob = self->globals.data[i];
struct global* global = malloc(sizeof(struct global));
global->id = glob->id;
global->addr = glob->id;
vec_push(&clone->globals, global);
}
// struct vec global_values;
for (size_t i=0; i<self->global_values.size; i++)
{
struct value* val = self->global_values.data[i];
struct value* value = value_new_clone(val);
vec_push(&clone->global_values, value);
}
return clone;
}
void state_free(struct state* self) void state_free(struct state* self)
{ {
assert(self); assert(self);
@ -243,6 +317,14 @@ SK state_push_ref(struct state* self,size_t ref, int line)
return state_push(self, TYPE_REF, val, line); return state_push(self, TYPE_REF, val, line);
} }
SK state_push_mod(struct state* self, struct module* mod, int line)
{
assert(self);
union val val;
val.mod = module_new_clone(mod);
return state_push(self, TYPE_MODULE, val, line);
}
struct local* state_try_get_local(struct state* self, int id) struct local* state_try_get_local(struct state* self, int id)
{ {
struct frame* frame = state_frame(self); struct frame* frame = state_frame(self);
@ -357,6 +439,39 @@ void state_closure_load(struct state* self,
fprintf(stderr, "cannot load closure %d\n", id); fprintf(stderr, "cannot load closure %d\n", id);
abort(); abort();
} }
void state_module_load(struct state* self,
int id)
{
assert(self);
SK mod = state_pop(self);
struct value* ref_val = state_try_get_value(self, mod);
struct value* mod_value = state_try_deref(self, ref_val->val.ref);
struct module* module = mod_value->val.mod;
struct symbol* symbol = sym_try_get_by_id(
module->sym,
id
);
struct value* value
= value_new_clone(state_try_get_value(module->state, symbol->id));
if (value->type == TYPE_FUN)
{
state_push_ref(self,
state_add_global(self, value),
value->line);
}
else
{
state_push(self, value->type, value->val, value->line);
free(value);
}
}
TypeKind state_common_num_type(struct state* self, SK lhs, SK rhs) TypeKind state_common_num_type(struct state* self, SK lhs, SK rhs)
{ {
assert(self); assert(self);
@ -762,7 +877,7 @@ int state_add_global(struct state* self,
vec_push(&self->global_values, value); vec_push(&self->global_values, value);
size_t addr = self->global_values.size - 1; size_t addr = self->global_values.size - 1;
struct global* global = malloc(sizeof(struct global)); struct global* global = malloc(sizeof(struct global));
global->id = self->global_id; global->id = self->global_id;
self->global_id++; self->global_id++;
global->addr = addr; global->addr = addr;

View File

@ -62,6 +62,28 @@ struct symbol* env_try_get(struct env* self, char const* name)
return NULL; return NULL;
} }
struct symbol* env_try_get_by_id(struct env* self, int id)
{
assert(self);
for (size_t i=0; i<self->symbols.size; i++)
{
struct symbol* symbol = self->symbols.data[i];
if (symbol->id == id)
{
return symbol;
}
}
if (self->parent)
{
return env_try_get_by_id(self->parent, id);
}
return NULL;
}
void symbol_init(struct symbol* self, void symbol_init(struct symbol* self,
int id, int id,
char const* name, char const* name,
@ -191,3 +213,8 @@ struct symbol* sym_try_get(struct sym* self, char const* name)
{ {
return env_try_get(self->env, name); return env_try_get(self->env, name);
} }
struct symbol* sym_try_get_by_id(struct sym* self, int id)
{
return env_try_get_by_id(self->env, id);
}

View File

@ -1,5 +1,6 @@
#include "value.h" #include "value.h"
#include "nfun.h" #include "nfun.h"
#include "module.h"
SK_ENUM_C(TypeKind, TYPE_KIND); SK_ENUM_C(TypeKind, TYPE_KIND);
@ -34,6 +35,12 @@ void value_free(struct value* self)
nfun_free(self->val.nfun); nfun_free(self->val.nfun);
free(self->val.nfun); free(self->val.nfun);
} }
if (self->type == TYPE_MODULE)
{
module_free(self->val.mod);
free(self->val.mod);
}
} }
struct value* value_new_clone(struct value* self) struct value* value_new_clone(struct value* self)
@ -81,6 +88,12 @@ struct value* value_new_clone(struct value* self)
return clone; return clone;
} break; } break;
case TYPE_MODULE: {
val.mod = module_new_clone(self->val.mod);
value_init(clone, TYPE_MODULE, val, self->line);
return clone;
} break;
case TYPE_NATIVE_FUN: { case TYPE_NATIVE_FUN: {
val.nfun = malloc(sizeof(struct nfun)); val.nfun = malloc(sizeof(struct nfun));
val.nfun->body = self->val.nfun->body; val.nfun->body = self->val.nfun->body;
@ -122,6 +135,10 @@ void value_str(struct value* self, struct str* dest)
switch (self->type) switch (self->type)
{ {
case TYPE_MODULE: {
str_format(dest, "<mod:%p>", self->val.mod);
} break;
case TYPE_FUN: { case TYPE_FUN: {
str_format(dest, "<fun:%p>", self->val.fun); str_format(dest, "<fun:%p>", self->val.fun);
} break; } break;

View File

@ -144,6 +144,13 @@ static void test_lexer_function()
); );
} }
static void test_lexer_module()
{
test_lexer("module :: ", 2,
"MODULE",
"MOD_ACCESS"
);
}
void register_lexer() void register_lexer()
{ {
CU_pSuite suite = CU_add_suite("Lexer", 0, 0); CU_pSuite suite = CU_add_suite("Lexer", 0, 0);
@ -157,6 +164,7 @@ void register_lexer()
CU_add_test(suite, "Blocks", test_lexer_block); CU_add_test(suite, "Blocks", test_lexer_block);
CU_add_test(suite, "Conditionnals", test_lexer_cond); CU_add_test(suite, "Conditionnals", test_lexer_cond);
CU_add_test(suite, "Functions", test_lexer_function); CU_add_test(suite, "Functions", test_lexer_function);
CU_add_test(suite, "Modules", test_lexer_module);
} }
#endif #endif

View File

@ -152,6 +152,19 @@ static void test_parser_function()
"hello(x, 2)"); "hello(x, 2)");
} }
static void test_parser_module()
{
test_parser("ROOT(MODULE(INT[4],STRING[5],BOOL[true]))",
"module 4 \"5\" true end");
test_parser("ROOT(ASSIGN(MOD_ACCESS(IDENT[x],IDENT[hello])"
",INT[3]))",
"x::hello = 3");
test_parser("ROOT(CALL(MOD_ACCESS(IDENT[x],IDENT[hello]),ARGS))",
"x::hello()");
}
void register_parser() void register_parser()
{ {
CU_pSuite suite = CU_add_suite("Parser", 0, 0); CU_pSuite suite = CU_add_suite("Parser", 0, 0);
@ -165,6 +178,7 @@ void register_parser()
CU_add_test(suite, "Blocks", test_parser_block); CU_add_test(suite, "Blocks", test_parser_block);
CU_add_test(suite, "IfExpression", test_parser_if); CU_add_test(suite, "IfExpression", test_parser_if);
CU_add_test(suite, "Functions", test_parser_function); CU_add_test(suite, "Functions", test_parser_function);
CU_add_test(suite, "Modules", test_parser_module);
} }
#endif #endif