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();
struct module module;
module_init(&module);
module_init(&module, argv[1]);
module_load_source(&module, argv[1]);
int status = module_compile(&module);

View File

@ -9,6 +9,8 @@ EXPR ::=
| IF
| return EXPR
| FUN_DECL
| MOD_ACCESS
MOD_ACCESS ::= EXPR mod_access ident
FUN_DECL ::=
| fun ident opar PARAMS cpar EXPR* end
IF ::= if EXPR BLOCK (else (BLOCK | IF))?
@ -32,7 +34,10 @@ LITERAL ::=
| ident
| FUN
| CALL
CALL ::= ident opar ARGS cpar
| MODULE
MODULE ::= module EXPR* end
CALL ::=
| (ident|MOD_ACCESS) opar ARGS cpar
ARGS ::= (EXPR (comma EXPR)*)?
FUN ::= fun opar PARAMS cpar EXPR* end
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 mod
{
char* name;
struct module* module;
};
struct compiler
{
struct vec var_names;
struct vec modules;
};
void mod_free(struct mod* self);
void compiler_init(struct compiler* self);
void compiler_free(struct compiler* self);

View File

@ -8,16 +8,18 @@
struct module
{
char* name;
struct str source;
struct prog prog;
struct sym sym;
struct state state;
struct prog* prog;
struct sym* sym;
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_load_source(struct module* self,
void module_load_source(struct module* self,
char const* path);
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_CONST_DECL), G(NODE_IDENT), G(NODE_ASSIGN), \
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);

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_pow(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_args(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_CALL), G(OP_RET), G(OP_MAKE_REF), \
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);

View File

@ -50,9 +50,11 @@ void stack_value_init(struct stack_value* self,
void stack_value_free(struct stack_value* self);
void frame_init(struct frame* self);
struct frame* frame_new_clone(struct frame* self);
void frame_free(struct frame* self);
void state_init(struct state* self);
struct state* state_new_clone(struct state* self);
void state_free(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_fun(struct state* self, struct fun* fun, 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);
@ -97,6 +100,9 @@ void state_global_load(struct state* self,
void state_closure_load(struct state* self,
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_type(struct state* self, SK value);
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);
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,
int id,
@ -57,5 +58,6 @@ void sym_open_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_by_id(struct sym* self, int id);
#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_CONST), G(TOKEN_ASSIGN), G(TOKEN_IDENT), \
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);

View File

@ -8,7 +8,7 @@
#define TYPE_KIND(G) \
G(TYPE_INT), G(TYPE_BOOL), G(TYPE_FLOAT), \
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);
@ -21,6 +21,7 @@ union val
struct fun* fun;
struct nfun* nfun;
size_t ref;
struct module* mod;
};
struct value

View File

@ -2,17 +2,26 @@
#include "token.h"
#include "state.h"
#include "natives.h"
#include "module.h"
void compiler_init(struct compiler* self)
{
assert(self);
vec_init(&self->var_names);
vec_init(&self->modules);
}
void mod_free(struct mod* self)
{
free(self->name);
}
void compiler_free(struct compiler* self)
{
assert(self);
vec_free(&self->var_names);
vec_free_elements(&self->modules, (void*) mod_free);
vec_free(&self->modules);
}
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);
} 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: {
struct fun* fun = malloc(sizeof(struct fun));
struct prog* p = malloc(sizeof(struct prog));

View File

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

View File

@ -90,7 +90,8 @@ bool lexer_is_sep(struct lexer* self, size_t index)
|| c == '<'
|| c == '>'
|| c == ','
|| c == '=';
|| c == '='
|| c == ':';
}
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;
}
SK_SCAN_TEXT("::", TOKEN_MOD_ACCESS);
SK_SCAN_TEXT("<=", TOKEN_LE);
SK_SCAN_TEXT(">=", TOKEN_GE);
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("if", TOKEN_IF, 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("end", TOKEN_END, NULL);
SK_SCAN_KEYWORD("var", TOKEN_VAR, NULL);

View File

@ -5,24 +5,63 @@
#include "exec.h"
#include "natives.h"
void module_init(struct module* self)
void module_init(struct module* self, char const* name)
{
assert(self);
self->name = strdup(name);
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)
{
assert(self);
str_free(&self->source);
prog_free(&self->prog);
sym_free(&self->sym);
state_free(&self->state);
prog_free(self->prog);
free(self->prog);
sym_free(self->sym);
free(self->sym);
state_free(self->state);
free(self->state);
free(self->name);
}
void module_load_source(struct module* self,
@ -59,13 +98,13 @@ int module_compile(struct module* self)
struct compiler compiler;
compiler_init(&compiler);
compiler_compile(&compiler, root, &self->prog, &self->sym,
&self->state);
compiler_compile(&compiler, root, self->prog, self->sym,
self->state);
struct exec exec;
exec_init(&exec);
exec_execute(&exec, &self->state, &self->prog);
exec_execute(&exec, self->state, self->prog);
if (!errors_ok())
{
@ -82,6 +121,5 @@ free_node:
free(root);
parser_free(&parser);
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);
}
if (lexer_next_is(&self->lexer, TOKEN_IDENT)
&& lexer_next_nth_is(&self->lexer, TOKEN_ASSIGN, 1))
// ASSIGN
{
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))
@ -356,15 +356,11 @@ struct node* parser_try_if(struct parser* self)
struct node* parser_try_assign(struct parser* self)
{
assert(self);
if (!lexer_next_is(&self->lexer, TOKEN_IDENT))
struct node* ident = SK_TRY(parser_try_or);
if (!ident)
{
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))
{
node_free(ident); free(ident);
@ -886,6 +882,11 @@ struct node* parser_try_literal(struct parser* self)
{
assert(self);
{
struct node* node = SK_TRY(parser_try_call);
if (node) { return node; }
}
if (lexer_next_is(&self->lexer, TOKEN_OPAR))
{
lexer_consume_next(&self->lexer);
@ -908,10 +909,10 @@ struct node* parser_try_literal(struct parser* self)
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))
@ -930,10 +931,15 @@ struct node* parser_try_literal(struct parser* self)
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);
}
struct node* parser_try_call(struct parser* self)
struct node* parser_try_mod_access(struct parser* self)
{
assert(self);
@ -942,8 +948,109 @@ struct node* parser_try_call(struct parser* self)
return NULL;
}
struct node* ident = malloc(sizeof(struct node));
node_init(ident, NODE_IDENT, lexer_try_new_next(&self->lexer));
struct token* lhs_tok = 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));
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));
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))
{

View File

@ -1,4 +1,5 @@
#include "state.h"
#include "module.h"
#include "nfun.h"
void stack_value_init(struct stack_value* self,
@ -27,6 +28,43 @@ void frame_init(struct frame* self)
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)
{
vec_free_elements(&self->stack_values, (void*) stack_value_free);
@ -47,6 +85,42 @@ void state_init(struct state* self)
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)
{
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);
}
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 frame* frame = state_frame(self);
@ -357,6 +439,39 @@ void state_closure_load(struct state* self,
fprintf(stderr, "cannot load closure %d\n", id);
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)
{
assert(self);
@ -762,7 +877,7 @@ int state_add_global(struct state* self,
vec_push(&self->global_values, value);
size_t addr = self->global_values.size - 1;
struct global* global = malloc(sizeof(struct global));
global->id = self->global_id;
global->id = self->global_id;
self->global_id++;
global->addr = addr;

View File

@ -62,6 +62,28 @@ struct symbol* env_try_get(struct env* self, char const* name)
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,
int id,
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);
}
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 "nfun.h"
#include "module.h"
SK_ENUM_C(TypeKind, TYPE_KIND);
@ -34,6 +35,12 @@ void value_free(struct value* self)
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)
@ -81,6 +88,12 @@ struct value* value_new_clone(struct value* self)
return clone;
} 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: {
val.nfun = malloc(sizeof(struct nfun));
val.nfun->body = self->val.nfun->body;
@ -122,6 +135,10 @@ void value_str(struct value* self, struct str* dest)
switch (self->type)
{
case TYPE_MODULE: {
str_format(dest, "<mod:%p>", self->val.mod);
} break;
case TYPE_FUN: {
str_format(dest, "<fun:%p>", self->val.fun);
} 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()
{
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, "Conditionnals", test_lexer_cond);
CU_add_test(suite, "Functions", test_lexer_function);
CU_add_test(suite, "Modules", test_lexer_module);
}
#endif

View File

@ -152,6 +152,19 @@ static void test_parser_function()
"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()
{
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, "IfExpression", test_parser_if);
CU_add_test(suite, "Functions", test_parser_function);
CU_add_test(suite, "Modules", test_parser_module);
}
#endif