Skip to content

Commit ca4e879

Browse files
committed
v0.5.0 - module system
Signed-off-by: Nick Wanninger <[email protected]>
1 parent 36b67d6 commit ca4e879

21 files changed

+206
-96
lines changed

core/core.cdr renamed to core/main.cdr

Lines changed: 17 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@
146146
(str self other))))
147147

148148

149+
(. Module (add-field 'str (fn (self) (str "<Module " self.*name* ">"))))
150+
(. Module (add-field 'repr (fn (self) (str "<Module " self.*name* ">"))))
151+
149152
(defmacro catch (id expr body)
150153
(list 'catch* (list 'fn nil expr) (list 'fn (list id) body)))
151154

@@ -518,11 +521,18 @@
518521

519522

520523

524+
(def (import-opt-expand name opts)
525+
(when opts
526+
(let [opt (first opts)
527+
t (type (first opts))]
528+
(cons (cond (= Vector t) (cons 'do (map (fn (x) `(def ~x (. ~name ~x)))
529+
opt))
530+
true 1)
531+
(import-opt-expand name (rest opts))))))
521532

522-
523-
(defmacro case (dispatch & cases)
524-
(let []))
525-
533+
(defmacro import (name & opts)
534+
`(do (def ~name (require ~(str name)))
535+
~@(import-opt-expand name opts)))
526536

527537

528538
(defmacro while (test & body)
@@ -670,28 +680,6 @@
670680

671681

672682

673-
;; the Module type that represents the current module
674-
;; and what gets returned from (import)
675-
(deftype Module)
676-
677-
678-
(def *imported* {})
679-
680-
(def (import path)
681-
(let (qualified (path-resolve path *file*)
682-
*old-file* *file*
683-
*old-module* nil
684-
*new-module* nil)
685-
(if (not (get *imported* qualified false))
686-
(do (eval-file-in-module qualified *new-module*)
687-
(set *imported* qualified *new-module*)
688-
(def *file* *old-file*)
689-
*new-module*)
690-
(get *imported* qualified))))
691-
692-
693-
694-
695683

696684
(defmacro do-global (& globs)
697685
(let [old-mod-name (gensym)
@@ -704,10 +692,6 @@
704692
~return-sym)))
705693

706694

707-
708-
709-
710-
711695
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
712696

713697
;; Base Exceptions
@@ -930,10 +914,12 @@
930914
(def (unlock! m) (. m (unlock!)))
931915

932916

917+
918+
(import _mutex)
933919
;; define an event-loop safe wrapper around a kernel mutex
934920
(deftype Mutex
935921
(def (new self)
936-
(. self _mut := (KernelMutex)))
922+
(. self _mut := (_mutex.KernelMutex)))
937923
(def (locked? self)
938924
(locked? self._mut))
939925
(def (lock! self)
@@ -965,4 +951,3 @@
965951
(join files " ")))))
966952

967953

968-

example/main.cdr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353

5454

5555

56+
5657
(def (vrange n)
5758
(let (i 0
5859
v [])

include/cedar/builtin_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,7 @@ BUILTIN_TYPE(dict, "Dict")
2222
BUILTIN_TYPE(symbol, "Symbol")
2323
BUILTIN_TYPE(keyword, "Keyword")
2424
BUILTIN_TYPE(fiber, "Fiber")
25+
BUILTIN_TYPE(module, "Module")
26+
2527

2628
#endif

include/cedar/globals.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333

3434
namespace cedar {
3535

36+
class module;
37+
38+
extern module *core_mod;
39+
3640
void def_global(int, ref);
3741
void def_global(ref, ref);
3842
void def_global(runes, ref);

include/cedar/modules.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,17 @@
3030
#define _MODULES_H
3131

3232
#include <string>
33+
#include <cedar/runes.h>
34+
#include <cedar/ref.h>
3335

3436
namespace cedar {
3537
class module;
3638
// primary module require system
3739
module *require(std::string);
40+
41+
void define_builtin_module(std::string, module*);
42+
43+
ref eval_string_in_module(cedar::runes, module*);
3844
};
3945

4046
#endif

include/cedar/object/module.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,12 @@ namespace cedar {
3131

3232
class module : public object {
3333
public:
34-
module();
34+
module(void);
35+
module(std::string);
3536
~module(void);
37+
38+
void def(std::string, ref);
39+
void def(std::string, bound_function);
3640
};
3741

3842
} // namespace cedar

include/cedar/ref.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ namespace cedar {
7474
f64 m_flt;
7575
object *m_obj;
7676
void *m_ptr;
77-
7877
fractional m_frac;
7978
};
8079

include/cedar/version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@
2222
* SOFTWARE.
2323
*/
2424

25-
#define CEDAR_VERSION "0.4.1"
25+
#define CEDAR_VERSION "0.5.0"

include/cedar/vm/opcode.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#define OP_DEF_MACRO 0x19
3333
#define OP_EVAL 0x1a
3434
#define OP_SLEEP 0x1b
35+
#define OP_GET_MODULE 0x1c
3536

3637
/* Instruction opcode foreach macro for code generation */
3738
/* Arg order: (name, bytecode, type, stack effect */
@@ -63,6 +64,7 @@
6364
V(SET_ATTR, OP_SET_ATTR, imm_int, 0) \
6465
V(DEF_MACRO, OP_DEF_MACRO, imm_int, 0) \
6566
V(EVAL, OP_EVAL, no_arg, 0) \
66-
V(SLEEP, OP_SLEEP, no_arg, -1)
67+
V(SLEEP, OP_SLEEP, no_arg, -1) \
68+
V(GET_MODULE, OP_GET_MODULE, no_arg, 1)
6769

6870
#endif

src/cedar/bindings/mutex.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424

2525
#include <cedar/globals.h>
2626
#include <cedar/objtype.h>
27+
#include <cedar/modules.h>
28+
#include <cedar/object/string.h>
29+
#include <cedar/object/module.h>
2730
#include <cedar/vm/binding.h>
2831
#include <stdio.h>
2932
#include <mutex>
@@ -40,6 +43,11 @@ class mutex_obj : public object {
4043

4144

4245
void bind_mutex(void) {
46+
47+
48+
module *mod = new module("_mutex");
49+
50+
4351
mutex_type = new type("KernelMutex");
4452
type_init_default_bindings(mutex_type);
4553

@@ -70,4 +78,7 @@ void bind_mutex(void) {
7078
});
7179

7280
def_global(new symbol("KernelMutex"), mutex_type);
81+
82+
mod->def("KernelMutex", mutex_type);
83+
define_builtin_module("_mutex", mod);
7384
}

src/cedar/bindings/os.cpp

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include <cedar/object/keyword.h>
2828
#include <cedar/object/string.h>
2929
#include <cedar/object/vector.h>
30+
#include <cedar/object/module.h>
31+
#include <cedar/modules.h>
3032
#include <cedar/objtype.h>
3133
#include <cedar/vm/binding.h>
3234
#include <dirent.h>
@@ -57,10 +59,10 @@ static cedar_binding(os_which) {
5759
static cedar_binding(os_fork) { return fork(); }
5860

5961
static cedar_binding(os_shell) {
60-
if (argc != 1) throw cedar::make_exception("os/shell requires 1 argument");
62+
if (argc != 1) throw cedar::make_exception("os.shell requires 1 argument");
6163

6264
if (argv[0].get_type() != string_type) {
63-
throw cedar::make_exception("os/shell requires a string as an argument");
65+
throw cedar::make_exception("os.shell requires a string as an argument");
6466
}
6567

6668
std::string cmd = argv[0].to_string(true);
@@ -71,9 +73,9 @@ static cedar_binding(os_shell) {
7173

7274

7375
static cedar_binding(os_stat) {
74-
if (argc != 1) throw cedar::make_exception("os/stat requires 1 argument");
76+
if (argc != 1) throw cedar::make_exception("os.stat requires 1 argument");
7577
if (argv[0].get_type() != string_type) {
76-
throw cedar::make_exception("os/stat requires a string path as an argument");
78+
throw cedar::make_exception("os.stat requires a string path as an argument");
7779
}
7880
std::string path = argv[0].to_string(true);
7981
struct stat s;
@@ -115,7 +117,7 @@ static cedar_binding(os_listdir) {
115117

116118
if (argc == 1) {
117119
if (argv[0].get_type() != string_type) {
118-
throw cedar::make_exception("os/listdir requires a string path as an argument");
120+
throw cedar::make_exception("os.listdir requires a string path as an argument");
119121
}
120122
path = argv[0].to_string(true);
121123
}
@@ -135,9 +137,9 @@ static cedar_binding(os_listdir) {
135137
static cedar_binding(os_rm) {
136138
static ref _true = new symbol("true");
137139
static ref _false = new symbol("false");
138-
if (argc != 1) throw cedar::make_exception("os/rm requires 1 argument");
140+
if (argc != 1) throw cedar::make_exception("os.rm requires 1 argument");
139141
if (argv[0].get_type() != string_type) {
140-
throw cedar::make_exception("os/rm requires a string path as an argument");
142+
throw cedar::make_exception("os.rm requires a string path as an argument");
141143
}
142144
std::string path = argv[0].to_string(true);
143145
return remove(path.c_str()) == 0 ? _true : _false;
@@ -147,10 +149,10 @@ static cedar_binding(os_rm) {
147149

148150
typedef void(init_func)(void);
149151
static cedar_binding(os_import_so) {
150-
if (argc != 1) throw cedar::make_exception("os/import-so requires 1 argument");
152+
if (argc != 1) throw cedar::make_exception("os.import-so requires 1 argument");
151153

152154
if (argv[0].get_type() != string_type) {
153-
throw cedar::make_exception("os/import-so requires a string as an argument");
155+
throw cedar::make_exception("os.import-so requires a string as an argument");
154156
}
155157

156158
std::string path = argv[0].to_string(true);
@@ -180,13 +182,19 @@ static cedar_binding(os_getppid) {
180182
}
181183

182184
void bind_os(void) {
183-
def_global("os/shell", os_shell);
184-
def_global("os/fork", os_fork);
185-
def_global("os/import-so", os_import_so);
186-
def_global("os/which", os_which);
187-
def_global("os/listdir", os_listdir);
188-
def_global("os/stat", os_stat);
189-
def_global("os/rm", os_rm);
190-
def_global("os/getpid", os_getpid);
191-
def_global("os/getppid", os_getppid);
185+
module *mod = new module("os");
186+
187+
mod->def("shell", os_shell);
188+
mod->def("fork", os_fork);
189+
mod->def("shell", os_shell);
190+
mod->def("fork", os_fork);
191+
mod->def("import-so", os_import_so);
192+
mod->def("which", os_which);
193+
mod->def("listdir", os_listdir);
194+
mod->def("stat", os_stat);
195+
mod->def("rm", os_rm);
196+
mod->def("getpid", os_getpid);
197+
mod->def("getppid", os_getppid);
198+
199+
define_builtin_module("os", mod);
192200
}

src/cedar/globals.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ static std::mutex g_lock;
3737
static std::unordered_map<int, ref> globals;
3838

3939

40+
41+
module *cedar::core_mod = nullptr;
42+
43+
4044
void cedar::def_global(int id, ref val) {
4145
g_lock.lock();
4246
globals[id] = val;

src/cedar/modules.cpp

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include <cedar/vm/compiler.h>
2828
#include <cedar/object/lambda.h>
2929
#include <cedar/object/module.h>
30+
#include <cedar/object/string.h>
31+
#include <cedar/object/symbol.h>
3032
#include <unordered_map>
3133
#include <mutex>
3234
#include <stdio.h>
@@ -67,22 +69,13 @@ static module *require_file(apathy::Path p) {
6769
cedar::runes src = util::read_file(path.c_str());
6870

6971

70-
module *mod = new module();
72+
module *mod = new module(path);
7173

72-
reader reader;
73-
reader.lex_source(src);
7474

75-
vm::compiler c;
76-
bool valid = true;
75+
static int file_id = get_symbol_intern_id("*file*");
76+
mod->setattr_fast(file_id, new string(path));
7777

78-
while (true) {
79-
ref obj = reader.read_one(&valid);
80-
if (!valid) break;
81-
ref compiled_lambda = c.compile(obj, nullptr);
82-
lambda *raw_program = ref_cast<cedar::lambda>(compiled_lambda);
83-
raw_program->mod = mod;
84-
ref val = eval_lambda(raw_program);
85-
}
78+
eval_string_in_module(src, mod);
8679

8780
modules[path] = mod;
8881

@@ -92,8 +85,10 @@ static module *require_file(apathy::Path p) {
9285

9386

9487
module *cedar::require(std::string name) {
88+
if (modules.count(name) != 0) {
89+
return modules.at(name);
90+
}
9591
auto path = get_path();
96-
static std::string dir_file_name = "main.cdr";
9792

9893
for (std::string p : path) {
9994
apathy::Path f = p;
@@ -115,4 +110,29 @@ module *cedar::require(std::string name) {
115110
return nullptr;
116111
}
117112

113+
// simple function to allow modules to be added externally
114+
void cedar::define_builtin_module(std::string name, module *mod) {
115+
modules[name] = mod;
116+
}
117+
118+
118119

120+
ref cedar::eval_string_in_module(cedar::runes src, module *mod) {
121+
reader reader;
122+
reader.lex_source(src);
123+
124+
vm::compiler c;
125+
bool valid = true;
126+
127+
ref val;
128+
while (true) {
129+
ref obj = reader.read_one(&valid);
130+
if (!valid) break;
131+
ref compiled_lambda = c.compile(obj, nullptr);
132+
lambda *raw_program = ref_cast<cedar::lambda>(compiled_lambda);
133+
raw_program->mod = mod;
134+
val = eval_lambda(raw_program);
135+
}
136+
137+
return val;
138+
}

0 commit comments

Comments
 (0)