(.module:
lux
(lux (control [monad #+ do]
["ex" exception #+ exception:]
pipe)
(concurrency [atom #+ Atom atom])
(data ["e" error]
[text]
text/format
(coll [dict]
[array]))
[macro #+ Monad]
[host #+ do-to object]
[io])
(luxc ["&" lang]
(lang [".L" variable #+ Register]
(translation [".T" common]))))
(host.import org/objectweb/asm/Label)
(host.import java/lang/reflect/AccessibleObject
(setAccessible [boolean] void))
(host.import java/lang/reflect/Method
(invoke [Object (Array Object)] #try Object))
(host.import (java/lang/Class a)
(getDeclaredMethod [String (Array (Class Object))] #try Method))
(host.import java/lang/Object
(getClass [] (Class Object)))
(host.import java/lang/Integer
(#static TYPE (Class Integer)))
(host.import java/lang/ClassLoader)
(def: ClassLoader::defineClass
Method
(case (Class::getDeclaredMethod ["defineClass"
(|> (host.array (Class Object) +4)
(host.array-write +0 (:! (Class Object) (host.class-for String)))
(host.array-write +1 (Object::getClass [] (host.array byte +0)))
(host.array-write +2 (:! (Class Object) Integer::TYPE))
(host.array-write +3 (:! (Class Object) Integer::TYPE)))]
(host.class-for java/lang/ClassLoader))
(#e.Success method)
(do-to method
(AccessibleObject::setAccessible [true]))
(#e.Error error)
(error! error)))
(def: (define-class class-name byte-code loader)
(-> Text commonT.Bytecode ClassLoader (e.Error Object))
(Method::invoke [loader
(array.from-list (list (:! Object class-name)
(:! Object byte-code)
(:! Object (host.long-to-int 0))
(:! Object (host.long-to-int (nat-to-int (host.array-length byte-code))))))]
ClassLoader::defineClass))
(def: (fetch-byte-code class-name store)
(-> Text commonT.Class-Store (Maybe commonT.Bytecode))
(|> store atom.read io.run (dict.get class-name)))
(def: (memory-class-loader store)
(-> commonT.Class-Store ClassLoader)
(object [] ClassLoader []
[]
(ClassLoader (findClass [class-name String]) Class
(case (fetch-byte-code class-name store)
(#.Some bytecode)
(case (define-class class-name bytecode (:! ClassLoader _jvm_this))
(#e.Success class)
(:!! class)
(#e.Error error)
(error! (format "Class definition error: " class-name "\n"
error)))
#.None
(error! (format "Class not found: " class-name))))))
(def: #export init-host
(io.IO commonT.Host)
(io.io (let [store (: commonT.Class-Store
(atom (dict.new text.Hash)))]
{#commonT.loader (memory-class-loader store)
#commonT.store store
#commonT.artifacts (dict.new text.Hash)
#commonT.context ["" +0]
#commonT.anchor #.None})))
(def: #export (with-anchor anchor expr)
(All [a] (-> [Label Register] (Meta a) (Meta a)))
(.function [compiler]
(let [old (:! commonT.Host (get@ #.host compiler))]
(case (expr (set@ #.host
(:! Void (set@ #commonT.anchor (#.Some anchor) old))
compiler))
(#e.Success [compiler' output])
(#e.Success [(update@ #.host
(|>> (:! commonT.Host)
(set@ #commonT.anchor (get@ #commonT.anchor old))
(:! Void))
compiler')
output])
(#e.Error error)
(#e.Error error)))))
(exception: #export No-Anchor)
(def: #export anchor
(Meta [Label Register])
(.function [compiler]
(case (|> compiler (get@ #.host) (:! commonT.Host) (get@ #commonT.anchor))
(#.Some anchor)
(#e.Success [compiler
anchor])
#.None
((&.throw No-Anchor "") compiler))))
(def: #export (with-context name expr)
(All [a] (-> Text (Meta a) (Meta a)))
(.function [compiler]
(let [old (:! commonT.Host (get@ #.host compiler))]
(case (expr (set@ #.host
(:! Void (set@ #commonT.context [(&.normalize-name name) +0] old))
compiler))
(#e.Success [compiler' output])
(#e.Success [(update@ #.host
(|>> (:! commonT.Host)
(set@ #commonT.context (get@ #commonT.context old))
(:! Void))
compiler')
output])
(#e.Error error)
(#e.Error error)))))
(def: #export (with-sub-context expr)
(All [a] (-> (Meta a) (Meta [Text a])))
(.function [compiler]
(let [old (:! commonT.Host (get@ #.host compiler))
[old-name old-sub] (get@ #commonT.context old)
new-name (format old-name "$" (%i (nat-to-int old-sub)))]
(case (expr (set@ #.host
(:! Void (set@ #commonT.context [new-name +0] old))
compiler))
(#e.Success [compiler' output])
(#e.Success [(update@ #.host
(|>> (:! commonT.Host)
(set@ #commonT.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)
(:! commonT.Host)
(get@ #commonT.context)
(let> [name sub]
name))])))
(def: #export class-loader
(Meta ClassLoader)
(function [compiler]
(#e.Success [compiler
(|> compiler
(get@ #.host)
(:! commonT.Host)
(get@ #commonT.loader))])))
(def: #export runtime-class Text "LuxRuntime")
(def: #export function-class Text "LuxFunction")
(def: #export unit Text "\u0000")