diff --git a/examples/3sum.dst b/examples/3sum.dst index 0ab55d24..831c95a4 100644 --- a/examples/3sum.dst +++ b/examples/3sum.dst @@ -1,5 +1,4 @@ - -(import "examples/iterators.dst") +(import examples.iterators :as "") (defn sum3 "Solve the 3SUM problem in O(n^2) time." diff --git a/src/compiler/boot.dst b/src/compiler/boot.dst index b1791e8d..6bd5bf66 100644 --- a/src/compiler/boot.dst +++ b/src/compiler/boot.dst @@ -66,6 +66,9 @@ (def t (type x)) (if (= t :integer) true (= t :real))) (defn fiber? [x] (= (type x) :fiber)) +(defn string? [x] (= (type x) :string)) +(defn symbol? [x] (= (type x) :symbol)) +(defn buffer? [x] (= (type x) :buffer)) (defn function? [x] (= (type x) :function)) (defn cfunction? [x] (= (type x) :cfunction)) (defn abstract? [x] (= (type x) :abstract)) @@ -970,7 +973,29 @@ environment is needed, use run-context." (run-context *env* chunks (fn [x] (:= returnval x)) default-error-handler) returnval) -(def require (do +(def module.paths @[ + "./?.dst" + "./?/init.dst" + "./dst_modules/?.dst" + "./dst_modules/?/init.dst" + ]) + +(defn module.find + "Open a file given a module name." + [name] + (def normname (string.replace-all "." "/" name)) + (defn checkmodule + [f testpath] + (if f f (do + (def p (string.replace-all "?" normname testpath)) + (file.open p)))) + (reduce checkmodule nil module.paths)) + +(def require + "Require a module with the given name. Will search all of the paths in +module.paths, then the path as a raw file path. Returns the new environment +returned from compiling and running the file." + (do (def cache @{}) (def loading @{}) (fn [path] @@ -986,7 +1011,9 @@ environment is needed, use run-context." (def newenv (make-env)) (put cache path newenv) (put loading path true) - (def f (file.open path)) + (def f (or (module.find path) (file.open path))) + (if (not f) + (error (string "could not open file for module " path))) (defn chunks [buf] (file.read f 1024 buf)) (run-context newenv chunks identity default-error-handler) (file.close f) @@ -996,10 +1023,12 @@ environment is needed, use run-context." (defn import* [env path & args] (def newenv (require path)) (def { + :as as :prefix prefix } (apply1 table args)) (var k (next newenv nil)) - (def prefix (if prefix prefix "")) + (def {:meta meta} newenv) + (def prefix (or (and as (string as ".")) prefix (string path "."))) (while k (def v (get newenv k)) (when (not (get v :private)) @@ -1007,7 +1036,17 @@ environment is needed, use run-context." (:= k (next newenv k)))) (defmacro import [path & args] - (apply tuple import* '_env path args)) + "Import a module. First requires the module, and then merges its +symbols into the current environment, prepending a given prefix as needed. +(use the :as or :prefix option to set a prefix). If no prefix is provided, +use the name of the module as a prefix." + (def upath (string (ast.unwrap path))) + (def argm (map (fn [x] + (if (and (symbol? x) (= (get x 0) 58)) + x + (string x))) + (ast.unwrap args))) + (apply tuple import* '_env upath argm)) (defn repl [getchunk onvalue onerr] "Run a repl. The first parameter is an optional function to call to diff --git a/src/core/gc.c b/src/core/gc.c index 0759a457..03a77608 100644 --- a/src/core/gc.c +++ b/src/core/gc.c @@ -188,9 +188,7 @@ recur: return; dst_gc_mark(fiber); - /* Check if new fiber - all status bits sets indicate :new status */ - if ((fiber->flags & DST_FIBER_STATUS_MASK) == DST_FIBER_STATUS_MASK) - dst_mark_function(fiber->root); + dst_mark_function(fiber->root); i = fiber->frame; j = fiber->stackstart - DST_FRAME_SIZE; diff --git a/src/core/io.c b/src/core/io.c index 71b803cf..dfbbca2f 100644 --- a/src/core/io.c +++ b/src/core/io.c @@ -193,8 +193,7 @@ static int dst_io_fopen(DstArgs args) { DST_THROW(args, "invalid file mode"); } f = fopen((const char *)fname, (const char *)fmode); - if (!f) DST_THROW(args, "could not open file"); - DST_RETURN(args, makef(f, flags)); + DST_RETURN(args, f ? makef(f, flags) : dst_wrap_nil()); } /* Read a certain number of bytes into memory */ diff --git a/src/mainclient/init.dst b/src/mainclient/init.dst index 369b3b66..30493e33 100644 --- a/src/mainclient/init.dst +++ b/src/mainclient/init.dst @@ -40,7 +40,7 @@ (+= i (dohandler (string.slice arg 1 2) i)) (do (:= *no-file* false) - (import arg) + (import* _env arg) (++ i)))) (when (or *should-repl* *no-file*) diff --git a/test/suite0.dst b/test/suite0.dst index f5f0ee48..5f7b7862 100644 --- a/test/suite0.dst +++ b/test/suite0.dst @@ -18,7 +18,7 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -(import "test/helper.dst") +(import test.helper :prefix "") (start-suite 0) (assert (= 10 (+ 1 2 3 4)) "addition") diff --git a/test/suite1.dst b/test/suite1.dst index 631d2118..09596c16 100644 --- a/test/suite1.dst +++ b/test/suite1.dst @@ -18,7 +18,7 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -(import "test/helper.dst") +(import test.helper :prefix "") (start-suite 1) (assert (= 400.0 (sqrt 160000)) "sqrt(160000)=400")