aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--stdlib/source/lux/lang/compiler/analysis/reference.lux44
-rw-r--r--stdlib/source/lux/macro.lux6
-rw-r--r--stdlib/test/test/lux/lang/compiler/analysis/reference.lux74
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?))
+ ))))