(;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;l2i 0))
(:! Object (host;l2i (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")