Compare commits

..

No commits in common. "2f73e3a0cac1f21f430fae38415cb44dde90d883" and "4d0edad298df38195aa0d7e2c0ce486abe559279" have entirely different histories.

32 changed files with 141 additions and 756 deletions

View File

@ -10,8 +10,6 @@ EXPR ::=
| return EXPR | return EXPR
| FUN_DECL | FUN_DECL
| MOD_ACCESS | MOD_ACCESS
| IMPORT
IMPORT ::= import string
MOD_ACCESS ::= EXPR mod_access ident MOD_ACCESS ::= EXPR mod_access ident
FUN_DECL ::= FUN_DECL ::=
| fun ident opar PARAMS cpar EXPR* end | fun ident opar PARAMS cpar EXPR* end
@ -47,4 +45,4 @@ BUILTIN ::=
| int | int
| bool | bool
| float | float
| stri | string

View File

@ -10,8 +10,3 @@ end
assert m::x eq 32 assert m::x eq 32
assert m::y eq "bim" assert m::y eq "bim"
assert m::add(7, 2) eq 9 assert m::add(7, 2) eq 9
import "./other_mod"
assert other_mod::my_value eq 42
assert other_mod::f(3) eq 21

View File

@ -1,18 +0,0 @@
import "./third_mod"
var my_value = 42
fun f(n)
return n * 7
end
fun x()
fun y()
third_mod::x + 2
end
y()
end
assert x() eq 39

View File

@ -1 +0,0 @@
var x = 37

View File

@ -28,8 +28,6 @@ add_library(skopy-lib SHARED
src/nfun.c src/nfun.c
src/natives.c src/natives.c
src/path.c
) )
file(GLOB_RECURSE file(GLOB_RECURSE

View File

@ -17,7 +17,6 @@ struct compiler
{ {
struct vec var_names; struct vec var_names;
struct vec modules; struct vec modules;
struct vec funs;
}; };
void mod_free(struct mod* self); void mod_free(struct mod* self);
void compiler_init(struct compiler* self); void compiler_init(struct compiler* self);
@ -59,16 +58,5 @@ void compiler_compile_if(struct compiler* self,
struct sym* sym, struct sym* sym,
struct state* state, struct state* state,
struct vec* to_end); struct vec* to_end);
struct symbol* compiler_find(struct compiler* self,
char* name,
struct sym* sym,
struct node* node);
void compiler_compile_fun(struct compiler* self,
struct node* node,
struct prog* prog,
struct sym* sym,
struct state* state);
#endif #endif

View File

@ -16,10 +16,10 @@ void exec_free(struct exec* self);
void exec_execute(struct exec* self, void exec_execute(struct exec* self,
struct state* state, struct state* state,
struct sym* sym,
struct prog* prog); struct prog* prog);
void exec_capture_env(struct exec* self, void exec_capture_env(struct exec* self,
struct state* state, struct state* state,
struct fun* fun); struct fun* fun,
struct env* env);
#endif #endif

View File

@ -3,8 +3,6 @@
#include "commons.h" #include "commons.h"
extern int FunId;
struct closure struct closure
{ {
int id; int id;
@ -13,8 +11,6 @@ struct closure
struct fun struct fun
{ {
int id;
int base;
struct prog* prog; struct prog* prog;
struct sym* sym; struct sym* sym;
struct vec closures; struct vec closures;
@ -24,7 +20,7 @@ void closure_init(struct closure* self, int id, struct value* value);
struct closure* closure_new_clone(struct closure* self); struct closure* closure_new_clone(struct closure* self);
void closure_free(struct closure* self); void closure_free(struct closure* self);
void fun_init(struct fun* self, struct prog* new_prog, int base); void fun_init(struct fun* self, struct prog* new_prog);
void fun_free(struct fun* self); void fun_free(struct fun* self);
struct fun* fun_new_clone(struct fun* self); struct fun* fun_new_clone(struct fun* self);

View File

@ -12,9 +12,6 @@ void natives_decl(struct state* state,
nfun_body fun, nfun_body fun,
int arity); int arity);
SK native_println(struct state* state, struct sym* sym, SK native_println(struct state* state, struct vec* args);
struct vec* args);
SK native_import(struct state* state, struct sym* sym,
struct vec* args);
#endif #endif

View File

@ -4,7 +4,7 @@
#include "commons.h" #include "commons.h"
#include "state.h" #include "state.h"
typedef SK (*nfun_body)(struct state*, struct sym*, struct vec*); typedef SK (*nfun_body)(struct state*, struct vec*);
struct nfun struct nfun
{ {
@ -17,6 +17,5 @@ void nfun_free(struct nfun* self);
SK nfun_call(struct nfun* self, SK nfun_call(struct nfun* self,
struct state* state, struct state* state,
struct sym* sym,
struct vec* args); struct vec* args);
#endif #endif

View File

@ -16,7 +16,7 @@ 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_MODULE), \ G(NODE_RETURN), G(NODE_CALL), G(NODE_ARGS), G(NODE_MODULE), \
G(NODE_MOD_ACCESS), G(NODE_IMPORT) G(NODE_MOD_ACCESS)
SK_ENUM_H(NodeKind, NODE_KIND); SK_ENUM_H(NodeKind, NODE_KIND);

View File

@ -19,7 +19,6 @@ struct node* parser_try(struct parser* self,
struct node* parser_try_parse(struct parser* self); struct node* parser_try_parse(struct parser* self);
struct node* parser_try_root(struct parser* self); struct node* parser_try_root(struct parser* self);
struct node* parser_try_expr(struct parser* self); struct node* parser_try_expr(struct parser* self);
struct node* parser_try_import(struct parser* self);
struct node* parser_try_fun_decl(struct parser* self); struct node* parser_try_fun_decl(struct parser* self);
struct node* parser_try_block(struct parser* self); struct node* parser_try_block(struct parser* self);
struct node* parser_try_inner_block(struct parser* self); struct node* parser_try_inner_block(struct parser* self);

View File

@ -1,19 +0,0 @@
#ifndef SK_PATH_H
#define SK_PATH_H
#include "commons.h"
struct path
{
struct str* str;
};
void path_init(struct path* self, char const* path_text);
void path_free(struct path* self);
bool path_is_relative(struct path* self);
void path_set_ext(struct path* self, char const* ext);
ssize_t path_try_find_ext(struct path* self);
void path_extract_name(struct path* self, struct str* dest);
#endif

View File

@ -6,7 +6,7 @@
#define SK_NO_PARAM (-1) #define SK_NO_PARAM (-1)
#define OPCODE(G) \ #define OPCODE(G) \
G(OP_PUSH), G(OP_POP), \ G(OP_PUSH), \
G(OP_ADD), G(OP_SUB), G(OP_MUL), \ G(OP_ADD), G(OP_SUB), G(OP_MUL), \
G(OP_DIV), G(OP_MOD), G(OP_POW), \ G(OP_DIV), G(OP_MOD), G(OP_POW), \
G(OP_USUB), G(OP_ASSERT_EQ), \ G(OP_USUB), G(OP_ASSERT_EQ), \

View File

@ -24,7 +24,6 @@ struct frame
struct vec locals; struct vec locals;
struct vec stack; struct vec stack;
struct fun* fun; struct fun* fun;
struct frame* parent;
}; };
struct global struct global
@ -42,7 +41,7 @@ struct state
struct vec global_values; struct vec global_values;
}; };
typedef SK (*nfun_body)(struct state*, struct sym*, struct vec*); typedef SK (*nfun_body)(struct state*, struct vec*);
void stack_value_init(struct stack_value* self, void stack_value_init(struct stack_value* self,
size_t addr, size_t addr,
@ -64,8 +63,6 @@ struct value* state_try_deref(struct state* self, size_t ref);
struct frame* state_frame(struct state* self); struct frame* state_frame(struct state* self);
void state_push_frame(struct state* self); void state_push_frame(struct state* self);
void state_pop_frame(struct state* self); void state_pop_frame(struct state* self);
struct value* frame_try_get_value(struct frame* self, SK value);
struct local* frame_try_get_local_by_id(struct frame* self, int id);
SK state_top(struct state* self); SK state_top(struct state* self);
struct value* state_try_get_value(struct state* self, SK value); struct value* state_try_get_value(struct state* self, SK value);

View File

@ -4,10 +4,6 @@
#include "commons.h" #include "commons.h"
#define SK_NO_CLOSURE (-1) #define SK_NO_CLOSURE (-1)
#define SK_NO_NATIVE (-1) #define SK_NO_NATIVE (-1)
#include "value.h"
extern int IdCounter;
struct symbol struct symbol
{ {
@ -18,8 +14,6 @@ struct symbol
bool is_const; bool is_const;
bool is_global; bool is_global;
struct env* env; struct env* env;
struct node* node;
struct fun* fun;
}; };
struct env struct env
@ -30,7 +24,8 @@ struct env
struct sym struct sym
{ {
struct sym* parent; int id_counter;
int closure_counter;
int native_counter; int native_counter;
int global_counter; int global_counter;
struct env* env; struct env* env;
@ -46,7 +41,6 @@ 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,
char const* name, char const* name,
struct node* node,
struct env* env); struct env* env);
void symbol_free(struct symbol* self); void symbol_free(struct symbol* self);
@ -55,14 +49,10 @@ void sym_init(struct sym* self);
struct sym* sym_new_clone(struct sym* self); struct sym* sym_new_clone(struct sym* self);
void sym_free(struct sym* self); void sym_free(struct sym* self);
int sym_decl_var(struct sym* self, char const* name, int sym_decl_var(struct sym* self, char const* name);
struct node* node); int sym_decl_const(struct sym* self, char const* name);
int sym_decl_const(struct sym* self, char const* name, int sym_decl_closure(struct sym* self, int id, char const* name);
struct node* node); int sym_decl_global(struct sym* self, int id, char const* name);
int sym_decl_closure(struct sym* self, int id, char const* name,
struct node* node, struct fun* fun);
int sym_decl_global(struct sym* self, int id, char const* name,
struct node* node);
void sym_open_scope(struct sym* self); void sym_open_scope(struct sym* self);
void sym_close_scope(struct sym* self); void sym_close_scope(struct sym* self);

View File

@ -17,7 +17,7 @@ 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_MODULE), \ G(TOKEN_FUN), G(TOKEN_RETURN), G(TOKEN_COMMA), G(TOKEN_MODULE), \
G(TOKEN_MOD_ACCESS), G(TOKEN_IMPORT) G(TOKEN_MOD_ACCESS)
SK_ENUM_H(TokenKind, TOKEN_KIND); SK_ENUM_H(TokenKind, TOKEN_KIND);

View File

@ -1,5 +1,4 @@
#include "compiler.h" #include "compiler.h"
#include "path.h"
#include "token.h" #include "token.h"
#include "state.h" #include "state.h"
#include "natives.h" #include "natives.h"
@ -10,7 +9,6 @@ void compiler_init(struct compiler* self)
assert(self); assert(self);
vec_init(&self->var_names); vec_init(&self->var_names);
vec_init(&self->modules); vec_init(&self->modules);
vec_init(&self->funs);
} }
void mod_free(struct mod* self) void mod_free(struct mod* self)
@ -24,7 +22,6 @@ void compiler_free(struct compiler* self)
vec_free(&self->var_names); vec_free(&self->var_names);
vec_free_elements(&self->modules, (void*) mod_free); vec_free_elements(&self->modules, (void*) mod_free);
vec_free(&self->modules); vec_free(&self->modules);
vec_free(&self->funs);
} }
void compiler_compile(struct compiler* self, void compiler_compile(struct compiler* self,
@ -47,48 +44,6 @@ void compiler_compile(struct compiler* self,
} }
} break; } break;
case NODE_IMPORT: {
struct node* name_node = node->children.data[0];
struct path path;
path_init(&path, name_node->token->value);
struct str name;
str_init(&name);
path_set_ext(&path, "sk");
path_extract_name(&path, &name);
struct module* module = malloc(sizeof(struct module));
module_init(module, name.value);
module_load_source(module, path.str->value);
module_compile(module);
struct value* value = malloc(sizeof(struct value));
union val v;
v.mod = module;
value_init(value, TYPE_MODULE, v, node->token->line);
struct str mod_name;
str_init(&mod_name);
path_set_ext(&path, "");
path_extract_name(&path, &mod_name);
int id = prog_add_constant(prog, value);
prog_add_instr(prog, OP_PUSH, id);
prog_add_instr(prog, OP_MAKE_REF, SK_NO_PARAM);
int addr = sym_decl_const(sym, mod_name.value, node);
prog_add_instr(prog, OP_LOCAL_STORE, addr);
struct mod* mymod = malloc(sizeof(struct mod));
mymod->name = strdup(mod_name.value);
mymod->module = module;
vec_push(&self->modules, mymod);
str_free(&mod_name);
str_free(&name);
path_free(&path);
} break;
case NODE_BLOCK: { case NODE_BLOCK: {
sym_open_scope(sym); sym_open_scope(sym);
for (size_t i=0; i<node->children.size; i++) for (size_t i=0; i<node->children.size; i++)
@ -163,8 +118,7 @@ void compiler_compile(struct compiler* self,
struct node* expr = node->children.data[1]; struct node* expr = node->children.data[1];
compiler_compile(self, expr, prog, sym, state); compiler_compile(self, expr, prog, sym, state);
int id = sym_decl_var(sym, ident->token->value, int id = sym_decl_var(sym, ident->token->value);
expr);
prog_add_instr(prog, OP_LOCAL_STORE, id); prog_add_instr(prog, OP_LOCAL_STORE, id);
char* name = vec_pop(&self->var_names); char* name = vec_pop(&self->var_names);
@ -182,8 +136,7 @@ void compiler_compile(struct compiler* self,
} }
struct node* expr = node->children.data[1]; struct node* expr = node->children.data[1];
compiler_compile(self, expr, prog, sym, state); compiler_compile(self, expr, prog, sym, state);
int id = sym_decl_const(sym, ident->token->value, int id = sym_decl_const(sym, ident->token->value);
expr);
prog_add_instr(prog, OP_LOCAL_STORE, id); prog_add_instr(prog, OP_LOCAL_STORE, id);
char* name = vec_pop(&self->var_names); char* name = vec_pop(&self->var_names);
free(name); free(name);
@ -192,12 +145,7 @@ void compiler_compile(struct compiler* self,
case NODE_ASSIGN: { case NODE_ASSIGN: {
struct node* ident = node->children.data[0]; struct node* ident = node->children.data[0];
struct node* expr = node->children.data[1]; struct node* expr = node->children.data[1];
struct symbol* symbol = compiler_find( struct symbol* symbol = sym_try_get(sym, ident->token->value);
self,
ident->token->value,
sym,
node
);
if (!symbol) if (!symbol)
{ {
@ -226,26 +174,19 @@ void compiler_compile(struct compiler* self,
} break; } break;
case NODE_IDENT: { case NODE_IDENT: {
char* name = node->token->value; struct symbol* symbol = sym_try_get(sym,
node->token->value);
struct symbol* symbol = compiler_find(self,
name,
sym,
node);
if (!symbol) if (!symbol)
{ {
errors_push(node->token->line, errors_push(node->token->line,
"unknown identifier '%s'.", "unknown identifier '%s'.",
name); node->token->value);
break; break;
} }
struct env* itr = sym->env->parent; struct env* itr = sym->env->parent;
int const max_depth = 1;
int i = 0;
while (i <= max_depth && itr) while (itr)
{ {
struct symbol const* s = env_try_get(itr, symbol->name); struct symbol const* s = env_try_get(itr, symbol->name);
@ -255,7 +196,6 @@ void compiler_compile(struct compiler* self,
} }
itr = itr->parent; itr = itr->parent;
i++;
} }
if (symbol->is_global) if (symbol->is_global)
@ -341,7 +281,6 @@ void compiler_compile(struct compiler* self,
errors_push(node->token->line, errors_push(node->token->line,
"unknown module '%s'.", "unknown module '%s'.",
mod_name->token->value); mod_name->token->value);
break;
} }
struct symbol* symbol = sym_try_get( struct symbol* symbol = sym_try_get(
@ -367,11 +306,9 @@ void compiler_compile(struct compiler* self,
struct prog* p = malloc(sizeof(struct prog)); struct prog* p = malloc(sizeof(struct prog));
prog_init(p); prog_init(p);
fun_init(fun, p, IdCounter); fun_init(fun, p);
natives_populate(state, fun->sym); natives_populate(state, fun->sym);
// Self value
// ----------
struct node* params = node->children.data[0]; struct node* params = node->children.data[0];
struct node* body = node->children.data[1]; struct node* body = node->children.data[1];
@ -380,25 +317,43 @@ void compiler_compile(struct compiler* self,
self->var_names.data[self->var_names.size - 1] self->var_names.data[self->var_names.size - 1]
: NULL; : NULL;
// Parameters
// ----------
for (size_t i=0; i<params->children.size; i++) for (size_t i=0; i<params->children.size; i++)
{ {
struct node* child = params->children.data[i]; struct node* child = params->children.data[i];
char* name = child->token->value; char* name = child->token->value;
sym_decl_var(fun->sym, name, child); sym_decl_var(fun->sym, name);
} }
if (var_name) if (var_name)
{ {
sym_decl_var(fun->sym, var_name, node); sym_decl_var(fun->sym, var_name);
} }
fun->sym->parent = sym; // Closure
{
for (size_t i=0; i<sym->env->symbols.size; i++)
{
struct symbol* s = sym->env->symbols.data[i];
sym_decl_closure(fun->sym, s->id, s->name);
}
vec_push(&self->funs, fun); if (sym->env->parent)
compiler_compile_fun(self, body, p, fun->sym, state); {
vec_pop(&self->funs); for (
size_t i=0;
i<sym->env->parent->symbols.size;
i++
)
{
struct symbol* s =
sym->env->parent->symbols.data[i];
sym_decl_closure(fun->sym, s->id, s->name);
}
}
}
compiler_compile(self, body, p, fun->sym, state);
union val val; union val val;
val.fun = fun; val.fun = fun;
@ -406,7 +361,6 @@ void compiler_compile(struct compiler* self,
val); val);
prog_add_instr(prog, OP_MAKE_REF, SK_NO_PARAM); prog_add_instr(prog, OP_MAKE_REF, SK_NO_PARAM);
} break; } break;
case NODE_BOOL: { case NODE_BOOL: {
union val val; union val val;
val.boolean = val.boolean =
@ -665,77 +619,3 @@ void compiler_compile_if(struct compiler* self,
} }
} }
} }
struct symbol* compiler_find(struct compiler* self,
char* name,
struct sym* sym,
struct node* node)
{
struct symbol* symbol = NULL;
struct sym* itr = sym->parent;
symbol = sym_try_get(sym, name);
if (symbol)
{
return symbol;
}
while (itr)
{
symbol = sym_try_get(itr, name);
if (symbol)
{
if (self->funs.size > 0)
{
struct fun* fun =
self->funs.data[
self->funs.size - 1
];
sym_decl_closure(
fun->sym,
symbol->id,
symbol->name,
node,
fun
);
struct symbol* s = sym_try_get(
fun->sym,
symbol->name
);
if (s->closure_id != SK_NO_CLOSURE)
{
symbol = s;
}
}
}
if (symbol) { break; }
itr = itr->parent;
}
return symbol;
}
void compiler_compile_fun(struct compiler* self,
struct node* node,
struct prog* prog,
struct sym* sym,
struct state* state)
{
if (node->kind == NODE_BLOCK)
{
for (size_t i=0; i<node->children.size; i++)
{
compiler_compile(self, node->children.data[i],
prog, sym, state);
}
}
else
{
compiler_compile(self, node, prog, sym, state);
}
}

View File

@ -17,7 +17,6 @@ void exec_free(struct exec* self)
void exec_execute(struct exec* self, void exec_execute(struct exec* self,
struct state* state, struct state* state,
struct sym* sym,
struct prog* prog) struct prog* prog)
{ {
while (self->pc < prog->opcodes.size) while (self->pc < prog->opcodes.size)
@ -119,7 +118,6 @@ void exec_execute(struct exec* self,
struct value* f = value_new_clone(state_try_get_value(state, function)); struct value* f = value_new_clone(state_try_get_value(state, function));
assert(f->type == TYPE_REF);
struct value* val_fun = state_try_deref( struct value* val_fun = state_try_deref(
state, state,
f->val.ref f->val.ref
@ -138,7 +136,6 @@ void exec_execute(struct exec* self,
} }
SK res = nfun_call(val_fun->val.nfun, SK res = nfun_call(val_fun->val.nfun,
state, state,
sym,
&ordered); &ordered);
struct value* value = struct value* value =
state_try_get_value(state, res); state_try_get_value(state, res);
@ -170,20 +167,18 @@ void exec_execute(struct exec* self,
} }
struct fun* fun = val_fun->val.fun; struct fun* fun = val_fun->val.fun;
state_call(state, fun);
// Params state_call(state, fun);
// ------
for (size_t i=0; i<params.size; i++) for (size_t i=0; i<params.size; i++)
{ {
size_t k = params.size - 1 - i; size_t k = params.size - 1 - i;
struct value* val = params.data[k]; struct value* val = params.data[k];
state_push(state, val->type, val->val, val->line); state_push(state, val->type, val->val, val->line);
state_local_store(state, fun->base + i); state_local_store(state, i+1);
} }
state_push(state, f->type, f->val, f->line); state_push(state, f->type, f->val, f->line);
state_local_store(state, fun->base + params.size); state_local_store(state, params.size + 1);
vec_free_elements(&params, NULL); vec_free_elements(&params, NULL);
vec_free(&params); vec_free(&params);
@ -196,8 +191,7 @@ void exec_execute(struct exec* self,
struct value* fun_val = struct value* fun_val =
state_try_deref(state, f->val.ref); state_try_deref(state, f->val.ref);
exec_execute(&ex, state, sym, exec_execute(&ex, state, fun_val->val.fun->prog);
fun_val->val.fun->prog);
struct value* res = value_new_clone(state_try_get_value( struct value* res = value_new_clone(state_try_get_value(
state, state,
@ -217,19 +211,15 @@ void exec_execute(struct exec* self,
self->pc++; self->pc++;
} break; } break;
case OP_POP: {
state_pop(state);
self->pc++;
} break;
case OP_PUSH: { case OP_PUSH: {
struct value* constant = prog->constants.data[param]; struct value* constant = prog->constants.data[param];
switch (constant->type) switch (constant->type)
{ {
case TYPE_FUN: { case TYPE_FUN: {
struct fun* fun =
fun_new_clone(constant->val.fun); struct fun* fun = fun_new_clone(constant->val.fun);
exec_capture_env(self, state, fun); struct sym* s = fun->sym;
exec_capture_env(self, state, fun, s->env);
state_push_fun( state_push_fun(
state, state,
@ -245,8 +235,7 @@ void exec_execute(struct exec* self,
struct exec exec; struct exec exec;
exec_init(&exec); exec_init(&exec);
exec_execute(&exec, mod->state, exec_execute(&exec, mod->state, mod->prog);
sym, mod->prog);
exec_free(&exec); exec_free(&exec);
@ -402,123 +391,59 @@ void exec_execute(struct exec* self,
void exec_capture_env(struct exec* self, void exec_capture_env(struct exec* self,
struct state* state, struct state* state,
struct fun* fun) struct fun* fun,
struct env* env)
{ {
(void) self; (void) self;
struct env* itr = fun->sym->env; if (env->parent)
while (itr)
{ {
for (size_t i=0; i<itr->symbols.size; i++) for (size_t i=0; i<env->parent->symbols.size; i++)
{ {
struct symbol* symbol = itr->symbols.data[i]; struct symbol* symbol = env->parent->symbols.data[i];
for (size_t j=0; j<state->frames.size; j++) if (symbol->closure_id != SK_NO_CLOSURE)
{ {
size_t k = state->frames.size - j - 1; struct local* loc =
struct frame* frame = state->frames.data[k]; state_try_get_local_by_id(
state,
symbol->closure_id
);
if (symbol->closure_id != SK_NO_CLOSURE) if(!loc) { continue; }
{
struct local* loc =
frame_try_get_local_by_id(
frame,
symbol->closure_id
);
if (loc) struct value* val =
{ state_try_get_value(
struct value* val = frame_try_get_value( state,
frame, loc->addr
loc->addr );
);
fun_capture(fun, symbol->id, val); fun_capture(fun, symbol->id, val);
break; }
} }
} }
if (env)
{
for (size_t i=0; i<env->symbols.size; i++)
{
struct symbol* symbol = env->symbols.data[i];
if (symbol->closure_id != SK_NO_CLOSURE)
{
struct local* loc =
state_try_get_local_by_id(
state,
symbol->closure_id
);
if(!loc) { continue; }
struct value* val =
state_try_get_value(
state,
loc->addr
);
fun_capture(fun, symbol->id, val);
} }
} }
itr = itr->parent;
} }
// struct env* itr = env;
//
// if (itr)
// {
// for (size_t i=0; i<itr->symbols.size; i++)
// {
// struct symbol* symbol = itr->symbols.data[i];
// if (symbol->closure_id != SK_NO_CLOSURE)
// {
// struct local* loc =
// state_try_get_local_by_id(
// state,
// symbol->closure_id
// );
//
// if(!loc) { continue; }
//
// struct value* val =
// state_try_get_value(
// state,
// loc->addr
// );
//
// fun_capture(fun, symbol->id, val);
// }
// }
//
// itr = itr->parent;
// }
// if (env->parent)
// {
// for (size_t i=0; i<env->parent->symbols.size; i++)
// {
// struct symbol* symbol = env->parent->symbols.data[i];
// if (symbol->closure_id != SK_NO_CLOSURE)
// {
// struct local* loc =
// state_try_get_local_by_id(
// state,
// symbol->closure_id
// );
//
// if(!loc) { continue; }
//
// struct value* val =
// state_try_get_value(
// state,
// loc->addr
// );
//
// fun_capture(fun, symbol->id, val);
// }
// }
// }
// if (env)
// {
// for (size_t i=0; i<env->symbols.size; i++)
// {
// struct symbol* symbol = env->symbols.data[i];
// if (symbol->closure_id != SK_NO_CLOSURE)
// {
// struct local* loc =
// state_try_get_local_by_id(
// state,
// symbol->closure_id
// );
//
// if(!loc) { continue; }
//
// struct value* val =
// state_try_get_value(
// state,
// loc->addr
// );
//
// fun_capture(fun, symbol->id, val);
// }
// }
// }
} }

View File

@ -1,7 +1,6 @@
#include "fun.h" #include "fun.h"
#include "prog.h" #include "prog.h"
#include "sym.h" #include "sym.h"
int FunId = 0;
void closure_init(struct closure* self, int id, struct value* value) void closure_init(struct closure* self, int id, struct value* value)
{ {
@ -27,12 +26,9 @@ void closure_free(struct closure* self)
free(self->value); free(self->value);
} }
void fun_init(struct fun* self, struct prog* new_prog, int base) void fun_init(struct fun* self, struct prog* new_prog)
{ {
assert(self); assert(self);
self->id = FunId;
self->base = base;
FunId++;
self->prog = new_prog; self->prog = new_prog;
self->sym = malloc(sizeof(struct sym)); self->sym = malloc(sizeof(struct sym));
sym_init(self->sym); sym_init(self->sym);
@ -55,13 +51,11 @@ struct fun* fun_new_clone(struct fun* self)
{ {
(void) self; (void) self;
struct fun* clone = malloc(sizeof(struct fun)); struct fun* clone = malloc(sizeof(struct fun));
fun_init(clone, prog_new_clone(self->prog), self->base); fun_init(clone, prog_new_clone(self->prog));
sym_free(clone->sym); sym_free(clone->sym);
free(clone->sym); free(clone->sym);
clone->sym = sym_new_clone(self->sym); clone->sym = sym_new_clone(self->sym);
clone->id = self->id;
for (size_t i=0; i<self->closures.size; i++) for (size_t i=0; i<self->closures.size; i++)
{ {
struct closure* closure = self->closures.data[i]; struct closure* closure = self->closures.data[i];

View File

@ -198,7 +198,6 @@ struct token* lexer_try_new_next(struct lexer* self)
SK_SCAN_TEXT("=", TOKEN_ASSIGN); SK_SCAN_TEXT("=", TOKEN_ASSIGN);
SK_SCAN_TEXT(",", TOKEN_COMMA); SK_SCAN_TEXT(",", TOKEN_COMMA);
SK_SCAN_KEYWORD("fun", TOKEN_FUN, NULL); SK_SCAN_KEYWORD("fun", TOKEN_FUN, NULL);
SK_SCAN_KEYWORD("import", TOKEN_IMPORT, NULL);
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);

View File

@ -104,7 +104,7 @@ int module_compile(struct module* self)
struct exec exec; struct exec exec;
exec_init(&exec); exec_init(&exec);
exec_execute(&exec, self->state, self->sym, self->prog); exec_execute(&exec, self->state, self->prog);
if (!errors_ok()) if (!errors_ok())
{ {

View File

@ -1,6 +1,4 @@
#include "natives.h" #include "natives.h"
#include "path.h"
#include "module.h"
void natives_populate(struct state* state, struct sym* sym) void natives_populate(struct state* state, struct sym* sym)
{ {
@ -8,7 +6,6 @@ void natives_populate(struct state* state, struct sym* sym)
assert(sym); assert(sym);
natives_decl(state, sym, "println", native_println, -1); natives_decl(state, sym, "println", native_println, -1);
natives_decl(state, sym, "import", native_import, 1);
} }
void natives_decl(struct state* state, void natives_decl(struct state* state,
@ -19,16 +16,12 @@ void natives_decl(struct state* state,
{ {
assert(state); assert(state);
assert(sym); assert(sym);
sym_decl_global(sym, state->global_id, name, NULL); sym_decl_global(sym, state->global_id, name);
state_add_nfun(state, fun, arity); state_add_nfun(state, fun, arity);
} }
SK native_println(struct state* state, SK native_println(struct state* state, struct vec* args)
struct sym* sym,
struct vec* args)
{ {
(void) sym;
for (size_t i=0; i<args->size; i++) for (size_t i=0; i<args->size; i++)
{ {
struct value* arg struct value* arg
@ -44,38 +37,3 @@ SK native_println(struct state* state,
printf("\n"); printf("\n");
return state_push_bool(state, true, 0); return state_push_bool(state, true, 0);
} }
SK native_import(struct state* state,
struct sym* sym,
struct vec* args)
{
struct value* filename_val =
state_try_get_value(state, (SK) args->data[0]);
assert(filename_val);
char* filename_str = filename_val->val.str;
struct path path;
path_init(&path, filename_str);
struct str filename;
str_init(&filename);
path_extract_name(&path, &filename);
struct module* module = malloc(sizeof(struct module));
path_set_ext(&path, "");
module_init(module, path.str->value);
module_load_source(module, filename.value);
module_compile(module);
struct value* value = malloc(sizeof(struct value));
union val v;
v.mod = module;
value_init(value, TYPE_MODULE, v, 0);
int id = state_add_global(state, value);
sym_decl_global(sym, id, "po", NULL);
str_free(&filename);
return state_push_ref(state, id, 0);
}

View File

@ -14,7 +14,6 @@ void nfun_free(struct nfun* self)
SK nfun_call(struct nfun* self, SK nfun_call(struct nfun* self,
struct state* state, struct state* state,
struct sym* sym,
struct vec* args) struct vec* args)
{ {
assert(self); assert(self);
@ -34,7 +33,7 @@ SK nfun_call(struct nfun* self,
return state_push_bool(state, false, line); return state_push_bool(state, false, line);
} }
SK result = (*self->body)(state, sym, args); SK result = (*self->body)(state, args);
return result; return result;
} }

View File

@ -143,42 +143,9 @@ struct node* parser_try_expr(struct parser* self)
return SK_TRY(parser_try_fun_decl); return SK_TRY(parser_try_fun_decl);
} }
if (lexer_next_is(&self->lexer, TOKEN_IMPORT))
{
return SK_TRY(parser_try_import);
}
return SK_TRY(parser_try_or); return SK_TRY(parser_try_or);
} }
struct node* parser_try_import(struct parser* self)
{
assert(self);
if (!lexer_next_is(&self->lexer, TOKEN_IMPORT))
{
return NULL;
}
struct token* tok = lexer_try_new_next(&self->lexer);
if (!lexer_next_is(&self->lexer, TOKEN_STRING))
{
token_free(tok);
free(tok);
return NULL;
}
struct node* string = malloc(sizeof(struct node));
node_init(string, NODE_STRING,
lexer_try_new_next(&self->lexer));
struct node* node = malloc(sizeof(struct node));
node_init(node, NODE_IMPORT, tok);
node_push_new_child(node, string);
return node;
}
struct node* parser_try_fun_decl(struct parser* self) struct node* parser_try_fun_decl(struct parser* self)
{ {
if (!lexer_next_is(&self->lexer, TOKEN_FUN)) if (!lexer_next_is(&self->lexer, TOKEN_FUN))

View File

@ -1,95 +0,0 @@
#include "path.h"
void path_init(struct path* self, char const* path_text)
{
assert(self);
self->str = malloc(sizeof(struct str));
str_init(self->str);
str_extend(self->str, (char*) path_text);
}
void path_free(struct path* self)
{
assert(self);
str_free(self->str);
free(self->str);
}
bool path_is_relative(struct path* self)
{
assert(self);
return self->str->size > 0 && self->str->value[0] == '.';
return false;
}
void path_set_ext(struct path* self, char const* ext)
{
assert(self);
assert(ext);
ssize_t idx = path_try_find_ext(self);
if (idx < 0)
{
if (strlen(ext) > 0)
{
str_push(self->str, '.');
}
str_extend(self->str, (char*) ext);
}
else
{
struct str* str = malloc(sizeof(struct str));
str_init(str);
for (ssize_t i=0; i<idx; i++)
{
str_push(str, self->str->value[i]);
}
if (strlen(ext) > 0)
{
str_push(str, '.');
str_extend(str, (char*) ext);
}
str_free(self->str);
free(self->str);
self->str = str;
}
}
ssize_t path_try_find_ext(struct path* self)
{
assert(self);
for (size_t i=0; i<self->str->size; i++)
{
size_t k = self->str->size - i - 1;
if (k > 0 && self->str->value[k] == '.'
&& isalnum(self->str->value[k - 1]))
{
return k;
}
}
return -1;
}
void path_extract_name(struct path* self, struct str* dest)
{
assert(self);
assert(dest);
if (path_is_relative(self))
{
str_extend(dest, self->str->value + 2);
}
else
{
str_extend(dest, self->str->value);
}
}

View File

@ -26,14 +26,13 @@ void frame_init(struct frame* self)
vec_init(&self->locals); vec_init(&self->locals);
vec_init(&self->stack); vec_init(&self->stack);
self->fun = NULL; self->fun = NULL;
self->parent = NULL;
} }
struct frame* frame_new_clone(struct frame* self) struct frame* frame_new_clone(struct frame* self)
{ {
struct frame* clone = malloc(sizeof(struct frame)); struct frame* clone = malloc(sizeof(struct frame));
frame_init(clone); frame_init(clone);
// struct vec stack_values; // struct vec stack_values;
for (size_t i=0; i<self->stack_values.size; i++) for (size_t i=0; i<self->stack_values.size; i++)
{ {
@ -62,7 +61,7 @@ struct frame* frame_new_clone(struct frame* self)
// struct fun* fun; // struct fun* fun;
clone->fun = self->fun; clone->fun = self->fun;
clone->parent = self->parent;
return clone; return clone;
} }
@ -108,10 +107,9 @@ struct state* state_new_clone(struct state* self)
struct global const* glob = self->globals.data[i]; struct global const* glob = self->globals.data[i];
struct global* global = malloc(sizeof(struct global)); struct global* global = malloc(sizeof(struct global));
global->id = glob->id; global->id = glob->id;
global->addr = glob->addr; global->addr = glob->id;
vec_push(&clone->globals, global); vec_push(&clone->globals, global);
} }
// struct vec global_values; // struct vec global_values;
for (size_t i=0; i<self->global_values.size; i++) for (size_t i=0; i<self->global_values.size; i++)
{ {
@ -181,10 +179,7 @@ void state_push_frame(struct state* self)
assert(self); assert(self);
struct frame* frame = malloc(sizeof(struct frame)); struct frame* frame = malloc(sizeof(struct frame));
frame_init(frame); frame_init(frame);
if (self->frames.size > 1)
{
frame->parent = self->frames.data[self->frames.size - 1];
}
vec_push(&self->frames, frame); vec_push(&self->frames, frame);
} }
@ -196,38 +191,6 @@ void state_pop_frame(struct state* self)
free(frame); free(frame);
} }
struct value* frame_try_get_value(struct frame* self, SK value)
{
assert(self);
for (size_t i=0; i<self->stack_values.size; i++)
{
struct stack_value* stack_value = self->stack_values.data[i];
if (stack_value->addr == value)
{
return stack_value->value;
}
}
return NULL;
}
struct local* frame_try_get_local_by_id(struct frame* self, int id)
{
for (size_t i=0; i<self->locals.size; i++)
{
struct local* loc = self->locals.data[i];
if (loc->id == id)
{
return loc;
}
}
return NULL;
}
SK state_top(struct state* self) SK state_top(struct state* self)
{ {
assert(self); assert(self);
@ -487,25 +450,16 @@ void state_module_load(struct state* self,
struct value* mod_value = state_try_deref(self, ref_val->val.ref); struct value* mod_value = state_try_deref(self, ref_val->val.ref);
struct module* module = mod_value->val.mod; struct module* module = mod_value->val.mod;
struct symbol const* symbol = sym_try_get_by_id( struct symbol* symbol = sym_try_get_by_id(
module->sym, module->sym,
id id
); );
struct local* loca = state_try_get_local_by_id(module->state, symbol->id); struct value* value
struct value* value = value_new_clone(state_try_get_value(module->state, symbol->id));
= state_try_get_value(module->state, loca->addr);
if (value->type == TYPE_REF)
{ if (value->type == TYPE_FUN)
struct value* v = state_try_deref(module->state,
value->val.ref);
v = value_new_clone(v);
state_push_ref(self,
state_add_global(self, v),
value->line);
}
else if (value->type == TYPE_FUN)
{ {
state_push_ref(self, state_push_ref(self,
state_add_global(self, value), state_add_global(self, value),
@ -514,6 +468,7 @@ void state_module_load(struct state* self,
else else
{ {
state_push(self, value->type, value->val, value->line); state_push(self, value->type, value->val, value->line);
free(value);
} }
} }

View File

@ -1,7 +1,5 @@
#include "sym.h" #include "sym.h"
int IdCounter = 0;
void env_init(struct env* self) void env_init(struct env* self)
{ {
assert(self); assert(self);
@ -25,13 +23,11 @@ struct env* env_new_clone(struct env* self)
new_symbol->closure_id = symbol->closure_id; new_symbol->closure_id = symbol->closure_id;
new_symbol->native_id = symbol->native_id; new_symbol->native_id = symbol->native_id;
new_symbol->env = clone; new_symbol->env = clone;
new_symbol->node = symbol->node;
new_symbol->fun = symbol->fun;
vec_push(&clone->symbols, new_symbol); vec_push(&clone->symbols, new_symbol);
} }
clone->parent = self->parent ? self->parent : NULL; clone->parent = self->parent ? env_new_clone(self->parent) : NULL;
return clone; return clone;
} }
@ -91,7 +87,6 @@ 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,
char const* name, char const* name,
struct node* node,
struct env* env) struct env* env)
{ {
assert(self); assert(self);
@ -102,8 +97,6 @@ void symbol_init(struct symbol* self,
self->closure_id = SK_NO_CLOSURE; self->closure_id = SK_NO_CLOSURE;
self->native_id = SK_NO_NATIVE; self->native_id = SK_NO_NATIVE;
self->env = env; self->env = env;
self->node = node;
self->fun = NULL;
} }
void symbol_free(struct symbol* self) void symbol_free(struct symbol* self)
@ -115,7 +108,8 @@ void symbol_free(struct symbol* self)
void sym_init(struct sym* self) void sym_init(struct sym* self)
{ {
assert(self); assert(self);
self->parent = NULL; self->id_counter = 1;
self->closure_counter = 1;
self->native_counter = 1; self->native_counter = 1;
self->global_counter = 1; self->global_counter = 1;
self->env = malloc(sizeof(struct env)); self->env = malloc(sizeof(struct env));
@ -127,10 +121,11 @@ struct sym* sym_new_clone(struct sym* self)
assert(self); assert(self);
struct sym* clone = malloc(sizeof(struct sym)); struct sym* clone = malloc(sizeof(struct sym));
sym_init(clone); sym_init(clone);
clone->id_counter = self->id_counter;
clone->closure_counter = self->closure_counter;
env_free(clone->env); env_free(clone->env);
free(clone->env); free(clone->env);
clone->parent = self->parent;
clone->env = self->env ? env_new_clone(self->env) : NULL; clone->env = self->env ? env_new_clone(self->env) : NULL;
return clone; return clone;
@ -144,60 +139,53 @@ void sym_free(struct sym* self)
self->env = NULL; self->env = NULL;
} }
int sym_decl_var(struct sym* self, char const* name, int sym_decl_var(struct sym* self, char const* name)
struct node* node)
{ {
assert(self); assert(self);
assert(name); assert(name);
struct symbol* symbol = malloc(sizeof(struct symbol)); struct symbol* symbol = malloc(sizeof(struct symbol));
symbol_init(symbol, IdCounter, name, node, self->env); symbol_init(symbol, self->id_counter, name, self->env);
IdCounter++;
vec_push(&self->env->symbols, symbol); vec_push(&self->env->symbols, symbol);
return symbol->id; self->id_counter++;
return self->id_counter - 1;
} }
int sym_decl_const(struct sym* self, char const* name, int sym_decl_const(struct sym* self, char const* name)
struct node* node)
{ {
assert(self); assert(self);
assert(name); assert(name);
struct symbol* symbol = malloc(sizeof(struct symbol)); struct symbol* symbol = malloc(sizeof(struct symbol));
symbol_init(symbol, IdCounter, name, node, self->env); symbol_init(symbol, self->id_counter, name, self->env);
IdCounter++;
symbol->is_const = true; symbol->is_const = true;
vec_push(&self->env->symbols, symbol); vec_push(&self->env->symbols, symbol);
return symbol->id; self->id_counter++;
return self->id_counter - 1;
} }
int sym_decl_closure(struct sym* self, int id, char const* name, int sym_decl_closure(struct sym* self, int id, char const* name)
struct node* node, struct fun* fun)
{ {
assert(self); assert(self);
assert(name); assert(name);
struct symbol* symbol = malloc(sizeof(struct symbol)); struct symbol* symbol = malloc(sizeof(struct symbol));
symbol_init(symbol, IdCounter, name, node, symbol_init(symbol, self->closure_counter, name, self->env);
self->env);
IdCounter++;
symbol->is_const = false; symbol->is_const = false;
symbol->closure_id = id; symbol->closure_id = id;
symbol->fun = fun;
vec_push(&self->env->symbols, symbol); vec_push(&self->env->symbols, symbol);
return symbol->id; self->closure_counter++;
return self->closure_counter - 1;
} }
int sym_decl_global(struct sym* self, int sym_decl_global(struct sym* self, int id, char const* name)
int id,
char const* name,
struct node* node)
{ {
assert(self); assert(self);
assert(name); assert(name);
struct symbol* symbol = malloc(sizeof(struct symbol)); struct symbol* symbol = malloc(sizeof(struct symbol));
symbol_init(symbol, id, name, node, self->env); symbol_init(symbol, id, name, self->env);
symbol->is_global = true; symbol->is_global = true;
vec_push(&self->env->symbols, symbol); vec_push(&self->env->symbols, symbol);
return id; return id;

View File

@ -146,10 +146,9 @@ static void test_lexer_function()
static void test_lexer_module() static void test_lexer_module()
{ {
test_lexer("module :: import", 3, test_lexer("module :: ", 2,
"MODULE", "MODULE",
"MOD_ACCESS", "MOD_ACCESS"
"IMPORT"
); );
} }
void register_lexer() void register_lexer()

View File

@ -2,7 +2,6 @@
#include <CUnit/Basic.h> #include <CUnit/Basic.h>
#include "lexer.h" #include "lexer.h"
#include "parser.h" #include "parser.h"
#include "path.h"
int main() int main()
{ {
@ -11,7 +10,6 @@ int main()
register_lexer(); register_lexer();
register_parser(); register_parser();
register_path();
CU_basic_set_mode(CU_BRM_VERBOSE); CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests(); CU_basic_run_tests();

View File

@ -165,12 +165,6 @@ static void test_parser_module()
"x::hello()"); "x::hello()");
} }
static void test_parser_import()
{
test_parser("ROOT(IMPORT(STRING[./hello]))",
"import \"./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);
@ -185,7 +179,6 @@ void register_parser()
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); CU_add_test(suite, "Modules", test_parser_module);
CU_add_test(suite, "Imports", test_parser_import);
} }
#endif #endif

View File

@ -1,94 +0,0 @@
#ifndef SK_TEST_PATH_H
#define SK_TEST_PATH_H
#include <CUnit/CUnit.h>
#include <path.h>
static void test_is_relative(bool oracle, char const* text)
{
struct path path;
path_init(&path, text);
CU_ASSERT_FATAL(path_is_relative(&path) == oracle);
path_free(&path);
}
static void test_path_relative()
{
test_is_relative(true, "./module.sk");
test_is_relative(false, "module.sk");
test_is_relative(false, "/home/module.sk");
test_is_relative(false, "");
}
static void test_path_set_ext(char const* oracle,
char const* text,
char const* ext)
{
struct path path;
path_init(&path, text);
path_set_ext(&path, ext);
if (strcmp(path.str->value, oracle) != 0)
{
fprintf(stderr, "\n%s + %s", text, ext);
fprintf(stderr, "\n%s <> %s\n", oracle, path.str->value);
}
CU_ASSERT_STRING_EQUAL_FATAL(path.str->value, oracle);
path_free(&path);
}
static void test_path_ext()
{
test_path_set_ext("./hello/world",
"./hello/world", "");
test_path_set_ext("./hello/world",
"./hello/world.sk", "");
test_path_set_ext("./hello/world.sk",
"./hello/world", "sk");
test_path_set_ext("./hello/world.sk",
"./hello/world.sk", "sk");
test_path_set_ext("./hello/world.sk",
"./hello/world.com", "sk");
}
static void test_path_extract_name(char const* text,
char const* oracle)
{
struct path path;
path_init(&path, text);
struct str s;
str_init(&s);
path_extract_name(&path, &s);
if (strcmp(s.value, oracle) != 0)
{
fprintf(stderr, "\n%s <> %s\n", oracle, s.value);
}
CU_ASSERT_STRING_EQUAL_FATAL(s.value, oracle);
str_free(&s);
path_free(&path);
}
static void test_path_extract()
{
test_path_extract_name("world.sk", "world.sk");
test_path_extract_name("./world.sk", "world.sk");
test_path_extract_name("./../world.sk", "../world.sk");
test_path_extract_name("./world", "world");
test_path_extract_name("./hello/world", "hello/world");
}
void register_path()
{
CU_pSuite suite = CU_add_suite("Path", 0, 0);
CU_add_test(suite, "Relative paths", test_path_relative);
CU_add_test(suite, "Extensions", test_path_ext);
CU_add_test(suite, "Extract name", test_path_extract);
}
#endif