1 #include "ml_module.h"
2 #include "ml_macros.h"
3 #include <gc/gc.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include "ml_runtime.h"
7
8 typedef struct {
9 ml_module_t Base;
10 int Flags;
11 } ml_mini_module_t;
12
13 ML_TYPE(MLMiniModuleT, (MLModuleT), "module");
14
15 ML_METHODX("::", MLMiniModuleT, MLStringT) {
16 ml_mini_module_t *Module = (ml_mini_module_t *)Args[0];
17 const char *Name = ml_string_value(Args[1]);
18 ml_value_t **Slot = (ml_value_t **)stringmap_slot(Module->Base.Exports, Name);
19 if (!Slot[0]) Slot[0] = ml_uninitialized(Name);
20 ML_RETURN(Slot[0]);
21 }
22
ml_export(ml_state_t * Caller,ml_mini_module_t * Module,int Count,ml_value_t ** Args)23 static void ml_export(ml_state_t *Caller, ml_mini_module_t *Module, int Count, ml_value_t **Args) {
24 ML_CHECKX_ARG_COUNT(1);
25 ML_CHECKX_ARG_TYPE(0, MLNamesT);
26 int Index = 0;
27 ml_value_t *Value = MLNil;
28 ML_NAMES_FOREACH(Args[0], Iter) {
29 const char *Name = ml_string_value(Iter->Value);
30 Value = Args[++Index];
31 ml_value_t **Slot = (ml_value_t **)stringmap_slot(Module->Base.Exports, Name);
32 if (Module->Flags & MLMF_USE_GLOBALS) {
33 if (Slot[0]) {
34 if (ml_typeof(Slot[0]) == MLGlobalT) {
35 } else if (ml_typeof(Slot[0]) == MLUninitializedT) {
36 ml_value_t *Global = ml_global(Name);
37 ml_uninitialized_set(Slot[0], Global);
38 Slot[0] = Global;
39 } else {
40 ML_RETURN(ml_error("ExportError", "Duplicate export %s", Name));
41 }
42 } else {
43 Slot[0] = ml_global(Name);
44 }
45 ml_global_set(Slot[0], Value);
46 } else {
47 if (Slot[0]) {
48 if (ml_typeof(Slot[0]) != MLUninitializedT) {
49 ML_RETURN(ml_error("ExportError", "Duplicate export %s", Name));
50 }
51 ml_uninitialized_set(Slot[0], Value);
52 }
53 Slot[0] = Value;
54 }
55 }
56 ML_RETURN(Value);
57 }
58
59 typedef struct ml_module_state_t {
60 ml_state_t Base;
61 ml_value_t *Module;
62 ml_value_t *Args[1];
63 } ml_module_state_t;
64
65 ML_TYPE(MLModuleStateT, (), "module-state");
66
ml_module_done_run(ml_module_state_t * State,ml_value_t * Value)67 static void ml_module_done_run(ml_module_state_t *State, ml_value_t *Value) {
68 ML_CONTINUE(State->Base.Caller, State->Module);
69 }
70
ml_module_init_run(ml_module_state_t * State,ml_value_t * Value)71 static void ml_module_init_run(ml_module_state_t *State, ml_value_t *Value) {
72 if (ml_is_error(Value)) ML_CONTINUE(State->Base.Caller, Value);
73 State->Base.run = (ml_state_fn)ml_module_done_run;
74 return ml_call(State, Value, 1, State->Args);
75 }
76
ml_module_compile2(ml_state_t * Caller,ml_parser_t * Parser,ml_compiler_t * Compiler,ml_value_t ** Slot,int Flags)77 void ml_module_compile2(ml_state_t *Caller, ml_parser_t *Parser, ml_compiler_t *Compiler, ml_value_t **Slot, int Flags) {
78 static const char *Parameters[] = {"export", NULL};
79 ml_mini_module_t *Module;
80 if ((Flags & MLMF_USE_GLOBALS) && Slot[0] && ml_typeof(Slot[0]) == MLMiniModuleT) {
81 Module = (ml_mini_module_t *)Slot[0];
82 } else {
83 Module = new(ml_mini_module_t);
84 Module->Base.Type = MLMiniModuleT;
85 Module->Base.Path = ml_parser_name(Parser);
86 Module->Flags = Flags;
87 Slot[0] = (ml_value_t *)Module;
88 }
89 ml_context_t *Context = ml_context_new(Caller->Context);
90 ml_context_set(Context, ML_MODULE_PATH_INDEX, (void *)ml_parser_name(Parser));
91 ml_module_state_t *State = new(ml_module_state_t);
92 State->Base.Type = MLModuleStateT;
93 State->Base.run = (void *)ml_module_init_run;
94 State->Base.Context = Context;
95 State->Base.Caller = Caller;
96 State->Module = (ml_value_t *)Module;
97 State->Args[0] = ml_cfunctionz(Module, (ml_callbackx_t)ml_export);
98 mlc_expr_t *Expr = ml_accept_file(Parser);
99 if (!Expr) ML_RETURN(ml_parser_value(Parser));
100 ml_function_compile((ml_state_t *)State, Expr, Compiler, Parameters);
101 }
102
103
ml_module_compile(ml_state_t * Caller,ml_parser_t * Parser,ml_compiler_t * Compiler,ml_value_t ** Slot)104 void ml_module_compile(ml_state_t *Caller, ml_parser_t *Parser, ml_compiler_t *Compiler, ml_value_t **Slot) {
105 return ml_module_compile2(Caller, Parser, Compiler, Slot, 0);
106 }
107
ml_module_load_file(ml_state_t * Caller,const char * FileName,ml_getter_t GlobalGet,void * Globals,ml_value_t ** Slot)108 void ml_module_load_file(ml_state_t *Caller, const char *FileName, ml_getter_t GlobalGet, void *Globals, ml_value_t **Slot) {
109 static const char *Parameters[] = {"export", NULL};
110 ml_mini_module_t *Module = new(ml_mini_module_t);
111 Module->Base.Type = MLMiniModuleT;
112 Module->Base.Path = FileName;
113 Slot[0] = (ml_value_t *)Module;
114 ml_module_state_t *State = new(ml_module_state_t);
115 State->Base.Type = MLModuleStateT;
116 State->Base.run = (void *)ml_module_init_run;
117 State->Base.Context = Caller->Context;
118 State->Base.Caller = Caller;
119 State->Module = (ml_value_t *)Module;
120 State->Args[0] = ml_cfunctionz(Module, (ml_callbackx_t)ml_export);
121 return ml_load_file((ml_state_t *)State, GlobalGet, Globals, FileName, Parameters);
122 }
123
ml_module_init(stringmap_t * _Globals)124 void ml_module_init(stringmap_t *_Globals) {
125 #include "ml_module_init.c"
126 }
127