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