aboutsummaryrefslogtreecommitdiff
path: root/new-luxc/source/luxc/lang/analysis
diff options
context:
space:
mode:
Diffstat (limited to 'new-luxc/source/luxc/lang/analysis')
-rw-r--r--new-luxc/source/luxc/lang/analysis/function.lux10
-rw-r--r--new-luxc/source/luxc/lang/analysis/inference.lux46
-rw-r--r--new-luxc/source/luxc/lang/analysis/structure.lux30
-rw-r--r--new-luxc/source/luxc/lang/analysis/type.lux16
4 files changed, 63 insertions, 39 deletions
diff --git a/new-luxc/source/luxc/lang/analysis/function.lux b/new-luxc/source/luxc/lang/analysis/function.lux
index 627fb7c0a..5a6df4d3e 100644
--- a/new-luxc/source/luxc/lang/analysis/function.lux
+++ b/new-luxc/source/luxc/lang/analysis/function.lux
@@ -102,10 +102,14 @@
(&;with-stacked-errors
(function [_]
(Cannot-Apply-Function (format " Function: " (%type funcT) "\n"
- "Arguments: " (|> args (list/map %code) (text;join-with " ")))))
+ "Arguments:" (|> args
+ list;enumerate
+ (list/map (function [[idx argC]]
+ (format "\n " (%n idx) " " (%code argC))))
+ (text;join-with "")))))
(do meta;Monad<Meta>
- [expected meta;expected-type
+ [expectedT meta;expected-type
[applyT argsA] (&inference;apply-function analyse funcT args)
_ (&;with-type-env
- (tc;check expected applyT))]
+ (tc;check expectedT applyT))]
(wrap (la;apply argsA funcA)))))
diff --git a/new-luxc/source/luxc/lang/analysis/inference.lux b/new-luxc/source/luxc/lang/analysis/inference.lux
index cd484a623..fea685024 100644
--- a/new-luxc/source/luxc/lang/analysis/inference.lux
+++ b/new-luxc/source/luxc/lang/analysis/inference.lux
@@ -16,6 +16,9 @@
(exception: #export Cannot-Infer)
(exception: #export Cannot-Infer-Argument)
(exception: #export Smaller-Variant-Than-Expected)
+(exception: #export Invalid-Type-Application)
+(exception: #export Not-A-Record-Type)
+(exception: #export Not-A-Variant-Type)
## When doing inference, type-variables often need to be created in
## order to figure out which types are present in the expression being
@@ -90,16 +93,16 @@
## Function types are used for this, although inference is not always
## done for function application (alternative uses may be records and
## tagged variants).
-## But, so long as the type being used for the inference can be trated
+## But, so long as the type being used for the inference can be treated
## as a function type, this method of inference should work.
-(def: #export (apply-function analyse funcT args)
+(def: #export (apply-function analyse inferT args)
(-> &;Analyser Type (List Code) (Meta [Type (List Analysis)]))
(case args
#;Nil
- (:: Monad<Meta> wrap [funcT (list)])
+ (:: Monad<Meta> wrap [inferT (list)])
(#;Cons argC args')
- (case funcT
+ (case inferT
(#;Named name unnamedT)
(apply-function analyse unnamedT args)
@@ -107,7 +110,7 @@
(&common;with-var
(function [[var-id varT]]
(do Monad<Meta>
- [[outputT argsA] (apply-function analyse (maybe;assume (type;apply (list varT) funcT)) args)]
+ [[outputT argsA] (apply-function analyse (maybe;assume (type;apply (list varT) inferT)) args)]
(do @
[? (&;with-type-env
(tc;bound? var-id))
@@ -123,7 +126,15 @@
(do Monad<Meta>
[[ex-id exT] (&;with-type-env
tc;existential)]
- (apply-function analyse (maybe;assume (type;apply (list exT) funcT)) args))
+ (apply-function analyse (maybe;assume (type;apply (list exT) inferT)) args))
+
+ (#;Apply inputT transT)
+ (case (type;apply (list inputT) transT)
+ (#;Some outputT)
+ (apply-function analyse outputT args)
+
+ #;None
+ (&;throw Invalid-Type-Application (%type inferT)))
## Arguments are inferred back-to-front because, by convention,
## Lux functions take the most important arguments *last*, which
@@ -134,18 +145,23 @@
## things together more easily.
(#;Function inputT outputT)
(do Monad<Meta>
- [[outputT' args'A] (apply-function analyse outputT args')
- argA (&;with-stacked-errors
+ [argA (&;with-stacked-errors
(function [_] (Cannot-Infer-Argument
(format "Inferred Type: " (%type inputT) "\n"
" Argument: " (%code argC))))
(&;with-expected-type inputT
- (analyse argC)))]
+ (analyse argC)))
+ [outputT' args'A] (apply-function analyse outputT args')]
(wrap [outputT' (list& argA args'A)]))
_
- (&;throw Cannot-Infer (format "Inference Type: " (%type funcT)
- " Arguments: " (|> args (list/map %code) (text;join-with " ")))))
+ (&;throw Cannot-Infer (format " Type: " (%type inferT) "\n"
+ "Arguments:"
+ (|> args
+ list;enumerate
+ (list/map (function [[idx argC]]
+ (format "\n " (%n idx) " " (%code argC))))
+ (text;join-with "")))))
))
## Turns a record type into the kind of function type suitable for inference.
@@ -153,9 +169,7 @@
(-> Type (Meta Type))
(case type
(#;Named name unnamedT)
- (do Monad<Meta>
- [unnamedT+ (record unnamedT)]
- (wrap unnamedT+))
+ (record unnamedT)
(^template [<tag>]
(<tag> env bodyT)
@@ -169,7 +183,7 @@
(:: Monad<Meta> wrap (type;function (type;flatten-tuple type) type))
_
- (&;fail (format "Not a record type: " (%type type)))))
+ (&;throw Not-A-Record-Type (%type type))))
## Turns a variant type into the kind of function type suitable for inference.
(def: #export (variant tag expected-size type)
@@ -225,4 +239,4 @@
(&common;variant-out-of-bounds-error type expected-size tag)))
_
- (&;fail (format "Not a variant type: " (%type type))))))
+ (&;throw Not-A-Variant-Type (%type type)))))
diff --git a/new-luxc/source/luxc/lang/analysis/structure.lux b/new-luxc/source/luxc/lang/analysis/structure.lux
index 0284245e1..5cac1a0d3 100644
--- a/new-luxc/source/luxc/lang/analysis/structure.lux
+++ b/new-luxc/source/luxc/lang/analysis/structure.lux
@@ -40,9 +40,9 @@
(do meta;Monad<Meta>
[expectedT meta;expected-type]
(&;with-stacked-errors
- (function [_] (Not-Variant-Type (format " Tag: " (%n tag) "\n"
+ (function [_] (Not-Variant-Type (format " Type: " (%type expectedT) "\n"
"Value: " (%code valueC) "\n"
- " Type: " (%type expectedT))))
+ " Tag: " (%n tag))))
(case expectedT
(#;Sum _)
(let [flat (type;flatten-variant expectedT)
@@ -102,9 +102,9 @@
(analyse-sum analyse tag valueC)))
_
- (&;throw Not-Variant-Type (format " Tag: " (%n tag) "\n"
- "Value: " (%code valueC) "\n"
- " Type: " (%type expectedT)))))))
+ (&;throw Not-Variant-Type (format " Type: " (%type expectedT) "\n"
+ " Tag: " (%n tag) "\n"
+ "Value: " (%code valueC)))))))
(def: (analyse-typed-product analyse members)
(-> &;Analyser (List Code) (Meta la;Analysis))
@@ -302,10 +302,16 @@
(-> &;Analyser (List [Code Code]) (Meta la;Analysis))
(do meta;Monad<Meta>
[members (normalize members)
- [members recordT] (order members)
- expectedT meta;expected-type
- inferenceT (&inference;record recordT)
- [inferredT membersA] (&inference;apply-function analyse inferenceT members)
- _ (&;with-type-env
- (tc;check expectedT inferredT))]
- (wrap (la;product membersA))))
+ [membersC recordT] (order members)
+ expectedT meta;expected-type]
+ (case expectedT
+ (#;Var _)
+ (do @
+ [inferenceT (&inference;record recordT)
+ [inferredT membersA] (&inference;apply-function analyse inferenceT membersC)
+ _ (&;with-type-env
+ (tc;check expectedT inferredT))]
+ (wrap (la;product membersA)))
+
+ _
+ (analyse-product analyse membersC))))
diff --git a/new-luxc/source/luxc/lang/analysis/type.lux b/new-luxc/source/luxc/lang/analysis/type.lux
index d0b038d93..74bb712f4 100644
--- a/new-luxc/source/luxc/lang/analysis/type.lux
+++ b/new-luxc/source/luxc/lang/analysis/type.lux
@@ -12,20 +12,20 @@
(def: #export (analyse-check analyse eval type value)
(-> &;Analyser &;Eval Code Code (Meta Analysis))
(do Monad<Meta>
- [actual (eval Type type)
- #let [actual (:! Type actual)]
- expected meta;expected-type
+ [actualT (eval Type type)
+ #let [actualT (:! Type actualT)]
+ expectedT meta;expected-type
_ (&;with-type-env
- (TC;check expected actual))]
- (&;with-expected-type actual
+ (TC;check expectedT actualT))]
+ (&;with-expected-type actualT
(analyse value))))
(def: #export (analyse-coerce analyse eval type value)
(-> &;Analyser &;Eval Code Code (Meta Analysis))
(do Monad<Meta>
- [actual (eval Type type)
- expected meta;expected-type
+ [actualT (eval Type type)
+ expectedT meta;expected-type
_ (&;with-type-env
- (TC;check expected (:! Type actual)))]
+ (TC;check expectedT (:! Type actualT)))]
(&;with-expected-type Top
(analyse value))))