diff options
Diffstat (limited to '')
-rw-r--r-- | stdlib/source/lux/lang/compiler/analysis/reference.lux | 44 | ||||
-rw-r--r-- | stdlib/source/lux/macro.lux | 6 | ||||
-rw-r--r-- | stdlib/test/test/lux/lang/compiler/analysis/reference.lux | 74 |
3 files changed, 94 insertions, 30 deletions
diff --git a/stdlib/source/lux/lang/compiler/analysis/reference.lux b/stdlib/source/lux/lang/compiler/analysis/reference.lux index 6f4908f9d..5652e21fc 100644 --- a/stdlib/source/lux/lang/compiler/analysis/reference.lux +++ b/stdlib/source/lux/lang/compiler/analysis/reference.lux @@ -1,29 +1,49 @@ (.module: lux - (lux (control monad) + (lux (control monad + ["ex" exception #+ exception:]) [macro] (macro [code]) - (lang (type ["tc" check]))) + (lang (type ["tc" check])) + (data [text "text/" Eq<Text>] + text/format)) [///] [// #+ Analysis Operation] [//type] [////reference] [////scope]) +(exception: #export (foreign-module-has-not-been-imported {current Text} {foreign Text}) + (ex.report ["Current" current] + ["Foreign" foreign])) + +(exception: #export (definition-has-not-been-expored {definition Ident}) + (ex.report ["Definition" (%ident definition)])) + ## [Analysers] (def: (definition def-name) (-> Ident (Operation Analysis)) - (do ///.Monad<Operation> - [[actualT def-anns _] (macro.find-def def-name)] - (case (macro.get-symbol-ann (ident-for #.alias) def-anns) - (#.Some real-def-name) - (definition real-def-name) + (with-expansions [<return> (wrap (|> def-name ////reference.constant #//.Reference))] + (do ///.Monad<Operation> + [[actualT def-anns _] (macro.find-def def-name)] + (case (macro.get-symbol-ann (ident-for #.alias) def-anns) + (#.Some real-def-name) + (definition real-def-name) - _ - (do @ - [_ (//type.infer actualT)] - (:: @ map (|>> ////reference.constant #//.Reference) - (macro.normalize def-name)))))) + _ + (do @ + [_ (//type.infer actualT) + (^@ def-name [::module ::name]) (macro.normalize def-name) + current macro.current-module-name] + (if (text/= current ::module) + <return> + (if (macro.export? def-anns) + (do @ + [imported! (macro.imported-by? ::module current)] + (if imported! + <return> + (///.throw foreign-module-has-not-been-imported [current ::module]))) + (///.throw definition-has-not-been-expored def-name)))))))) (def: (variable var-name) (-> Text (Operation (Maybe Analysis))) diff --git a/stdlib/source/lux/macro.lux b/stdlib/source/lux/macro.lux index 9e26a49e4..404d76b32 100644 --- a/stdlib/source/lux/macro.lux +++ b/stdlib/source/lux/macro.lux @@ -721,7 +721,7 @@ #.None (fail ($_ text/compose "Wrong syntax for " <desc> "."))))] - [log-expand expand "log-expand"] - [log-expand-all expand-all "log-expand-all"] - [log-expand-once expand-once "log-expand-once"] + [log-expand! expand "log-expand!"] + [log-expand-all! expand-all "log-expand-all!"] + [log-expand-once! expand-once "log-expand-once!"] ) diff --git a/stdlib/test/test/lux/lang/compiler/analysis/reference.lux b/stdlib/test/test/lux/lang/compiler/analysis/reference.lux index 98db0a006..c6fbf5da0 100644 --- a/stdlib/test/test/lux/lang/compiler/analysis/reference.lux +++ b/stdlib/test/test/lux/lang/compiler/analysis/reference.lux @@ -4,7 +4,8 @@ (control [monad #+ do] pipe) (data ["e" error] - [ident "ident/" Eq<Ident>]) + [ident "ident/" Eq<Ident>] + [text "text/" Eq<Text>]) ["r" math/random] [macro #+ Monad<Meta>] (macro [code]) @@ -22,14 +23,49 @@ (def: analyse (expressionA.analyser (:coerce lang.Eval []))) +(type: Check (-> (e.Error Any) Bool)) + +(do-template [<name> <on-success> <on-failure>] + [(def: <name> + Check + (|>> (case> (#e.Success _) + <on-success> + + (#e.Error _) + <on-failure>)))] + + [success? true false] + [failure? false true] + ) + +(def: (reach-test var-name [export? def-module] [import? dependent-module] check!) + (-> Text [Bool Text] [Bool Text] Check Bool) + (|> (do Monad<Meta> + [_ (moduleL.with-module +0 def-module + (moduleL.define var-name [Any + (if export? + (' {#.export? true}) + (' {})) + []]))] + (moduleL.with-module +0 dependent-module + (do @ + [_ (if import? + (moduleL.import def-module) + (wrap []))] + (typeA.with-inference + (..analyse (code.symbol [def-module var-name])))))) + (macro.run (initL.compiler [])) + check!)) + (context: "References" (<| (times +100) (do @ [[expectedT _] _primitive.primitive - module-name (r.unicode +5) + def-module (r.unicode +5) scope-name (r.unicode +5) var-name (r.unicode +5) - #let [def-name [module-name var-name]]] + dependent-module (|> (r.unicode +5) + (r.filter (|>> (text/= def-module) not)))] ($_ seq (test "Can analyse variable." (|> (scopeL.with-scope scope-name @@ -43,16 +79,24 @@ _ false))) - (test "Can analyse definition." - (|> (do Monad<Meta> - [_ (moduleL.define var-name [expectedT (' {}) []])] - (typeA.with-inference - (..analyse (code.symbol def-name)))) - (moduleL.with-module +0 module-name) - (macro.run (initL.compiler [])) - (case> (^ (#e.Success [_ inferredT (#analysisL.Reference (referenceL.constant constant-name))])) - (and (type/= expectedT inferredT) - (ident/= def-name constant-name)) + (test "Can analyse definition (in the same module)." + (let [def-name [def-module var-name]] + (|> (do Monad<Meta> + [_ (moduleL.define var-name [expectedT (' {}) []])] + (typeA.with-inference + (..analyse (code.symbol def-name)))) + (moduleL.with-module +0 def-module) + (macro.run (initL.compiler [])) + (case> (^ (#e.Success [_ inferredT (#analysisL.Reference (referenceL.constant constant-name))])) + (and (type/= expectedT inferredT) + (ident/= def-name constant-name)) - _ - false))))))) + _ + false)))) + (test "Can analyse definition (if exported from imported module)." + (reach-test var-name [true def-module] [true dependent-module] success?)) + (test "Cannot analyse definition (if not exported from imported module)." + (reach-test var-name [false def-module] [true dependent-module] failure?)) + (test "Cannot analyse definition (if exported from non-imported module)." + (reach-test var-name [true def-module] [false dependent-module] failure?)) + )))) |