application/octet-stream
•
2.98 KB
•
84 lines
;; Contains the module system
[def module/cache @[]]
[def module/loader #nil]
[defn module/add-loader [f]
[set! module/loader [cons f module/loader]]]
[defn module/save-state []
@[:cache module/cache :loader module/loader]]
[defn module/restore-state [c]
[set! module/cache [tree/ref c :cache]]
[set! module/loader [tree/ref c :loader]]]
[defn module/qualify-symbol [module-name symbol]
[string->symbol [cat [keyword->symbol module-name] "/" [string symbol]]]]
[defmacro module body
"Define a new module and return it"
[macroexpand [cons 'ω* [cons '[def exports @[]] body]]]]
[defmacro defmodule [name . body]
"Define a new named module"
`[module/insert ~name ~[cons module body]]]
[defmacro export [name value]
`[tree/set! exports '~name ~value]]
[defn require* [module env]
[def mod [module/load module]]
[def exports [resolve 'exports mod]]
[for-in [k [tree/keys exports]]
[def q [module/qualify-symbol module [keyword->symbol k]]]
[def expr `[def ~q [module/import ~mod '~[keyword->symbol k]]]]
[apply env [compile* expr env]]]]
[defmacro require [module]
`[require* ~module [current-closure]]]
[defmacro import* [local-symbol module module-symbol]
`[def ~local-symbol [module/import ~module '~module-symbol]]]
[defmacro import [names module]
[when-not [list? names]
[return `[import* ~names [module/load ~module] ~names]]]
[def ret #nil]
[while names
[if [== [cadr names] :as]
[do [set! ret [cons `[import* ~[caddr names] [module/load ~module] ~[car names]] ret]]
[set! names [cddr names]]]
[set! ret [cons `[import* ~[car names] [module/load ~module] ~[car names]] ret]]]
[cdr! names]]
[cons do [nreverse ret]]]
[defn module/load/external [name]
[for-in [loader module/loader]
[def mod [loader name]]
[when mod [return mod]]]
[return #nil]]
[defn module/insert [name module]
[tree/set! module/cache name module]]
[defn module/load [name]
[case [type-of name]
[:object name]
[:keyword [or [tree/ref module/cache name]
[do [def mod [module/load/external name]]
[when mod [tree/set! module/cache name mod]]
[return mod]]]]]]
[defn module/import-all [module symbol]
[def exports [resolve 'exports module]]
[typecheck/only exports :tree]
[return exports]]
[defn module/import [module symbol]
[def exports [module/import-all module symbol]]
[when-not [tree/has? exports symbol]
[exception :import-error [if [resolves? symbol module]
"That symbol was not exported"
"That symbol does not exist in that module"]]]
[tree/ref exports symbol]]