diff options
author | Eduardo Julian | 2018-03-06 01:07:43 -0400 |
---|---|---|
committer | Eduardo Julian | 2018-03-06 01:07:43 -0400 |
commit | 38bd6f35d81705ab0c04c85601ac5b236b62605a (patch) | |
tree | 4c2fd4f6369067965017aeea18ba68b1f658344d /new-luxc/source/luxc/lang/translation/lua.lux | |
parent | 9bf491a18e4b772505c3767cf0249eb24f0a822b (diff) |
- Initial Lua backend implementation.
Diffstat (limited to 'new-luxc/source/luxc/lang/translation/lua.lux')
-rw-r--r-- | new-luxc/source/luxc/lang/translation/lua.lux | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/new-luxc/source/luxc/lang/translation/lua.lux b/new-luxc/source/luxc/lang/translation/lua.lux new file mode 100644 index 000000000..115471cbe --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/lua.lux @@ -0,0 +1,228 @@ +(.module: + lux + (lux (control ["ex" exception #+ exception:] + pipe + [monad #+ do]) + (data [bit] + [maybe] + ["e" error #+ Error] + [text "text/" Eq<Text>] + text/format + (coll [array])) + [macro] + [io #+ IO Process io] + [host #+ class: interface: object] + (world [file #+ File])) + (luxc [lang] + (lang [".L" variable #+ Register] + (host [lua #+ Lua Expression Statement])) + [".C" io])) + +(host.import java/lang/Object) + +(host.import java/lang/String + (getBytes [String] #try (Array byte))) + +(host.import java/lang/CharSequence) + +(host.import java/lang/Appendable + (append [CharSequence] Appendable)) + +(host.import java/lang/StringBuilder + (new []) + (toString [] String)) + +(host.import net/sandius/rembulan/StateContext) + +(host.import net/sandius/rembulan/impl/StateContexts + (#static newDefaultInstance [] StateContext)) + +(host.import net/sandius/rembulan/env/RuntimeEnvironment) + +(host.import net/sandius/rembulan/env/RuntimeEnvironments + (#static system [] RuntimeEnvironment)) + +(host.import net/sandius/rembulan/Table) + +(host.import net/sandius/rembulan/lib/StandardLibrary + (#static in [RuntimeEnvironment] StandardLibrary) + (installInto [StateContext] Table)) + +(host.import net/sandius/rembulan/Variable + (new [Object])) + +(host.import net/sandius/rembulan/runtime/LuaFunction) + +(host.import net/sandius/rembulan/load/ChunkLoader + (loadTextChunk [Variable String String] LuaFunction)) + +(host.import net/sandius/rembulan/compiler/CompilerChunkLoader + (#static of [String] CompilerChunkLoader)) + +(host.import net/sandius/rembulan/exec/DirectCallExecutor + (#static newExecutor [] DirectCallExecutor) + (call [StateContext Object (Array Object)] (Array Object))) + +(type: #export Anchor [Text Register]) + +(type: #export Host + {#context [Text Nat] + #anchor (Maybe Anchor) + #interpreter (-> Text (Error Top)) + #module-buffer (Maybe StringBuilder) + #program-buffer StringBuilder}) + +(def: #export init + (IO Host) + (io {#context ["" +0] + #anchor #.None + #interpreter (let [runtime-env (RuntimeEnvironments::system []) + std-lib (StandardLibrary::in [runtime-env]) + state-context (StateContexts::newDefaultInstance []) + table (StandardLibrary::installInto [state-context] std-lib) + variable (Variable::new [table]) + loader (CompilerChunkLoader::of ["_lux_definition"]) + executor (DirectCallExecutor::newExecutor [])] + (function [code] + (let [lua-function (ChunkLoader::loadTextChunk [variable "lux compilation" code] + loader)] + ("lux try" (io (DirectCallExecutor::call [state-context (:! Object lua-function) (array.new +0)] + executor)))))) + #module-buffer #.None + #program-buffer (StringBuilder::new [])})) + +(def: #export lua-module-name Text "module.lua") + +(def: #export init-module-buffer + (Meta Unit) + (function [compiler] + (#e.Success [(update@ #.host + (|>> (:! Host) + (set@ #module-buffer (#.Some (StringBuilder::new []))) + (:! Void)) + compiler) + []]))) + +(exception: #export No-Active-Module-Buffer) +(exception: #export Cannot-Execute) + +(def: #export (with-sub-context expr) + (All [a] (-> (Meta a) (Meta [Text a]))) + (function [compiler] + (let [old (:! Host (get@ #.host compiler)) + [old-name old-sub] (get@ #context old) + new-name (format old-name "___" (%i (nat-to-int old-sub)))] + (case (expr (set@ #.host + (:! Void (set@ #context [new-name +0] old)) + compiler)) + (#e.Success [compiler' output]) + (#e.Success [(update@ #.host + (|>> (:! Host) + (set@ #context [old-name (n/inc old-sub)]) + (:! Void)) + compiler') + [new-name output]]) + + (#e.Error error) + (#e.Error error))))) + +(def: #export context + (Meta Text) + (function [compiler] + (#e.Success [compiler + (|> (get@ #.host compiler) + (:! Host) + (get@ #context) + (let> [name sub] + name))]))) + +(def: #export (with-anchor anchor expr) + (All [a] (-> Anchor (Meta a) (Meta a))) + (function [compiler] + (let [old (:! Host (get@ #.host compiler))] + (case (expr (set@ #.host + (:! Void (set@ #anchor (#.Some anchor) old)) + compiler)) + (#e.Success [compiler' output]) + (#e.Success [(update@ #.host + (|>> (:! Host) + (set@ #anchor (get@ #anchor old)) + (:! Void)) + compiler') + output]) + + (#e.Error error) + (#e.Error error))))) + +(exception: #export No-Anchor) + +(def: #export anchor + (Meta Anchor) + (function [compiler] + (case (|> compiler (get@ #.host) (:! Host) (get@ #anchor)) + (#.Some anchor) + (#e.Success [compiler anchor]) + + #.None + ((lang.throw No-Anchor "") compiler)))) + +(def: #export module-buffer + (Meta StringBuilder) + (function [compiler] + (case (|> compiler (get@ #.host) (:! Host) (get@ #module-buffer)) + #.None + ((lang.fail (No-Active-Module-Buffer "")) compiler) + + (#.Some module-buffer) + (#e.Success [compiler module-buffer])))) + +(def: #export program-buffer + (Meta StringBuilder) + (function [compiler] + (#e.Success [compiler (|> compiler (get@ #.host) (:! Host) (get@ #program-buffer))]))) + +(def: (execute code) + (-> Expression (Meta Unit)) + (function [compiler] + (let [interpreter (|> compiler (get@ #.host) (:! Host) (get@ #interpreter))] + (case (interpreter code) + (#e.Error error) + ((lang.fail (Cannot-Execute error)) compiler) + + (#e.Success _) + (#e.Success [compiler []]))))) + +(exception: #export Unknown-Member) + +(def: #export variant-tag-field "_lux_tag") +(def: #export variant-flag-field "_lux_flag") +(def: #export variant-value-field "_lux_value") + +(def: #export unit Text "\u0000") + +(def: #export (definition-name [module name]) + (-> Ident Text) + (lang.normalize-name (format module "$" name))) + +(def: #export (save code) + (-> Lua (Meta Unit)) + (do macro.Monad<Meta> + [module-buffer module-buffer + #let [_ (Appendable::append [(:! CharSequence code)] + module-buffer)]] + (execute code))) + +(def: #export (save-module! target) + (-> File (Meta (Process Unit))) + (do macro.Monad<Meta> + [module macro.current-module-name + module-buffer module-buffer + program-buffer program-buffer + #let [module-code (StringBuilder::toString [] module-buffer) + _ (Appendable::append [(:! CharSequence (format module-code "\n"))] + program-buffer)]] + (wrap (ioC.write target + (format (lang.normalize-name module) "/" lua-module-name) + (|> module-code + (String::getBytes ["UTF-8"]) + e.assume))))) |