aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/platform/compiler/phase/statement/total.lux
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/source/lux/platform/compiler/phase/statement/total.lux')
-rw-r--r--stdlib/source/lux/platform/compiler/phase/statement/total.lux56
1 files changed, 56 insertions, 0 deletions
diff --git a/stdlib/source/lux/platform/compiler/phase/statement/total.lux b/stdlib/source/lux/platform/compiler/phase/statement/total.lux
new file mode 100644
index 000000000..15f116aa1
--- /dev/null
+++ b/stdlib/source/lux/platform/compiler/phase/statement/total.lux
@@ -0,0 +1,56 @@
+(.module:
+ [lux #*
+ [control
+ ["." monad (#+ do)]
+ ["ex" exception (#+ exception:)]]
+ [data
+ [text
+ format]]
+ ["." macro]]
+ ["." // (#+ Phase)
+ ["/." //
+ ["." analysis
+ ["." expression]
+ ["." type]
+ ["///." macro]]
+ ["." extension]]])
+
+(exception: #export (not-a-statement {code Code})
+ (ex.report ["Statement" (%code code)]))
+
+(exception: #export (not-a-macro {code Code})
+ (ex.report ["Code" (%code code)]))
+
+(exception: #export (macro-was-not-found {name Name})
+ (ex.report ["Name" (%name name)]))
+
+(def: #export (phase code)
+ Phase
+ (case code
+ (^ [_ (#.Form (list& [_ (#.Text name)] inputs))])
+ (extension.apply "Statement" phase [name inputs])
+
+ (^ [_ (#.Form (list& macro inputs))])
+ (do ///.Monad<Operation>
+ [expansion (//.lift-analysis
+ (do @
+ [macroA (type.with-type Macro
+ (expression.compile macro))]
+ (case macroA
+ (^ (analysis.constant macro-name))
+ (do @
+ [?macro (extension.lift (macro.find-macro macro-name))
+ macro (case ?macro
+ (#.Some macro)
+ (wrap macro)
+
+ #.None
+ (///.throw macro-was-not-found macro-name))]
+ (extension.lift (///macro.expand macro-name macro inputs)))
+
+ _
+ (///.throw not-a-macro code))))]
+ (monad.map @ phase expansion))
+
+ _
+ (///.throw not-a-statement code)))