aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/lang/compiler/analysis.lux
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/source/lux/lang/compiler/analysis.lux')
-rw-r--r--stdlib/source/lux/lang/compiler/analysis.lux281
1 files changed, 281 insertions, 0 deletions
diff --git a/stdlib/source/lux/lang/compiler/analysis.lux b/stdlib/source/lux/lang/compiler/analysis.lux
new file mode 100644
index 000000000..235e399fb
--- /dev/null
+++ b/stdlib/source/lux/lang/compiler/analysis.lux
@@ -0,0 +1,281 @@
+(.module:
+ [lux #- nat int deg]
+ (lux (data [product]
+ [error]
+ [text "text/" Eq<Text>]
+ (coll [list "list/" Fold<List>]))
+ [function])
+ [///reference #+ Register Variable Reference]
+ [//])
+
+(type: #export #rec Primitive
+ #Unit
+ (#Bool Bool)
+ (#Nat Nat)
+ (#Int Int)
+ (#Deg Deg)
+ (#Frac Frac)
+ (#Text Text))
+
+(type: #export Tag Nat)
+
+(type: #export (Composite a)
+ (#Sum (Either a a))
+ (#Product [a a]))
+
+(type: #export #rec Pattern
+ (#Simple Primitive)
+ (#Complex (Composite Pattern))
+ (#Bind Register))
+
+(type: #export (Branch' e)
+ {#when Pattern
+ #then e})
+
+(type: #export (Match' e)
+ [(Branch' e) (List (Branch' e))])
+
+(type: #export Environment
+ (List Variable))
+
+(type: #export #rec Analysis
+ (#Primitive Primitive)
+ (#Structure (Composite Analysis))
+ (#Reference Reference)
+ (#Case Analysis (Match' Analysis))
+ (#Function Environment Analysis)
+ (#Apply Analysis Analysis))
+
+(type: #export Operation
+ (//.Operation .Lux))
+
+(type: #export Compiler
+ (//.Compiler .Lux Code Analysis))
+
+(type: #export Branch
+ (Branch' Analysis))
+
+(type: #export Match
+ (Match' Analysis))
+
+(do-template [<name> <tag>]
+ [(template: #export (<name> content)
+ (<tag> content))]
+
+ [control/case #Case]
+ )
+
+(do-template [<name> <type> <tag>]
+ [(def: #export <name>
+ (-> <type> Analysis)
+ (|>> <tag> #Primitive))]
+
+ [bool Bool #Bool]
+ [nat Nat #Nat]
+ [int Int #Int]
+ [deg Deg #Deg]
+ [frac Frac #Frac]
+ [text Text #Text]
+ )
+
+(type: #export (Variant a)
+ {#lefts Nat
+ #right? Bool
+ #value a})
+
+(type: #export (Tuple a) (List a))
+
+(type: #export Arity Nat)
+
+(type: #export (Abstraction c) [Environment Arity c])
+
+(type: #export (Application c) [c (List c)])
+
+(def: (last? size tag)
+ (-> Nat Tag Bool)
+ (n/= (dec size) tag))
+
+(template: #export (no-op value)
+ (|> +1 #///reference.Local #///reference.Variable #..Reference
+ (#..Function (list))
+ (#..Apply value)))
+
+(do-template [<name> <type> <structure> <prep-value>]
+ [(def: #export (<name> size tag value)
+ (-> Nat Tag <type> <type>)
+ (let [left (function.constant (|>> #.Left #Sum <structure>))
+ right (|>> #.Right #Sum <structure>)]
+ (if (last? size tag)
+ (if (n/= +1 tag)
+ (right value)
+ (list/fold left
+ (right value)
+ (list.n/range +0 (n/- +2 tag))))
+ (list/fold left
+ (case value
+ (<structure> (#Sum _))
+ (<prep-value> value)
+
+ _
+ value)
+ (list.n/range +0 tag)))))]
+
+ [sum-analysis Analysis #Structure no-op]
+ [sum-pattern Pattern #Complex id]
+ )
+
+(do-template [<name> <type> <primitive> <structure>]
+ [(def: #export (<name> members)
+ (-> (Tuple <type>) <type>)
+ (case (list.reverse members)
+ #.Nil
+ (<primitive> #Unit)
+
+ (#.Cons singleton #.Nil)
+ singleton
+
+ (#.Cons last prevs)
+ (list/fold (function (_ left right) (<structure> (#Product left right)))
+ last prevs)))]
+
+ [product-analysis Analysis #Primitive #Structure]
+ [product-pattern Pattern #Simple #Complex]
+ )
+
+(def: #export (apply [func args])
+ (-> (Application Analysis) Analysis)
+ (list/fold (function (_ arg func) (#Apply arg func)) func args))
+
+(do-template [<name> <type> <tag>]
+ [(def: #export (<name> value)
+ (-> <type> (Tuple <type>))
+ (case value
+ (<tag> (#Product left right))
+ (#.Cons left (<name> right))
+
+ _
+ (list value)))]
+
+ [tuple Analysis #Structure]
+ [tuple-pattern Pattern #Complex]
+ )
+
+(do-template [<name> <type> <tag>]
+ [(def: #export (<name> value)
+ (-> <type> (Maybe (Variant <type>)))
+ (loop [lefts +0
+ variantA value]
+ (case variantA
+ (<tag> (#Sum (#.Left valueA)))
+ (case valueA
+ (<tag> (#Sum _))
+ (recur (inc lefts) valueA)
+
+ _
+ (#.Some {#lefts lefts
+ #right? false
+ #value valueA}))
+
+ (<tag> (#Sum (#.Right valueA)))
+ (#.Some {#lefts lefts
+ #right? true
+ #value valueA})
+
+ _
+ #.None)))]
+
+ [variant Analysis #Structure]
+ [variant-pattern Pattern #Complex]
+ )
+
+(def: #export (application analysis)
+ (-> Analysis (Application Analysis))
+ (case analysis
+ (#Apply head func)
+ (let [[func' tail] (application func)]
+ [func' (#.Cons head tail)])
+
+ _
+ [analysis (list)]))
+
+(template: #export (pattern/unit)
+ (#..Simple #..Unit))
+
+(do-template [<name> <tag>]
+ [(template: #export (<name> content)
+ (#..Simple (<tag> content)))]
+
+ [pattern/bool #..Bool]
+ [pattern/nat #..Nat]
+ [pattern/int #..Int]
+ [pattern/deg #..Deg]
+ [pattern/frac #..Frac]
+ [pattern/text #..Text]
+ )
+
+(def: #export (with-source-code source action)
+ (All [a] (-> Source (Operation a) (Operation a)))
+ (function (_ compiler)
+ (let [old-source (get@ #.source compiler)]
+ (case (action (set@ #.source source compiler))
+ (#error.Error error)
+ (#error.Error error)
+
+ (#error.Success [compiler' output])
+ (#error.Success [(set@ #.source old-source compiler')
+ output])))))
+
+(def: fresh-bindings
+ (All [k v] (Bindings k v))
+ {#.counter +0
+ #.mappings (list)})
+
+(def: fresh-scope
+ Scope
+ {#.name (list)
+ #.inner +0
+ #.locals fresh-bindings
+ #.captured fresh-bindings})
+
+(def: #export (with-scope action)
+ (All [a] (-> (Operation a) (Operation [Scope a])))
+ (function (_ compiler)
+ (case (action (update@ #.scopes (|>> (#.Cons fresh-scope)) compiler))
+ (#error.Success [compiler' output])
+ (case (get@ #.scopes compiler')
+ #.Nil
+ (#error.Error "Impossible error: Drained scopes!")
+
+ (#.Cons head tail)
+ (#error.Success [(set@ #.scopes tail compiler')
+ [head output]]))
+
+ (#error.Error error)
+ (#error.Error error))))
+
+(def: #export (with-current-module name action)
+ (All [a] (-> Text (Operation a) (Operation a)))
+ (function (_ compiler)
+ (case (action (set@ #.current-module (#.Some name) compiler))
+ (#error.Success [compiler' output])
+ (#error.Success [(set@ #.current-module
+ (get@ #.current-module compiler)
+ compiler')
+ output])
+
+ (#error.Error error)
+ (#error.Error error))))
+
+(def: #export (with-cursor cursor action)
+ (All [a] (-> Cursor (Operation a) (Operation a)))
+ (if (text/= "" (product.left cursor))
+ action
+ (function (_ compiler)
+ (let [old-cursor (get@ #.cursor compiler)]
+ (case (action (set@ #.cursor cursor compiler))
+ (#error.Success [compiler' output])
+ (#error.Success [(set@ #.cursor old-cursor compiler')
+ output])
+
+ (#error.Error error)
+ (#error.Error error))))))