(.module: lux (lux (control [monad #+ do] ["ex" exception #+ exception:] ["p" parser]) (data ["e" error] [text] text/format (coll [list "list/" Functor] [dict #+ Dict])) [macro #+ with-gensyms] (macro [code] ["s" syntax #+ syntax:]) [host]) (luxc ["&" lang] (lang ["la" analysis] ["ls" synthesis] (host [ruby #+ Ruby Expression Statement]))) [///] (/// [".T" runtime] [".T" case] [".T" function] [".T" loop])) ## [Types] (type: #export Translator (-> ls.Synthesis (Meta Expression))) (type: #export Proc (-> Translator (List ls.Synthesis) (Meta Expression))) (type: #export Bundle (Dict Text Proc)) (syntax: (Vector [size s.nat] elemT) (wrap (list (` [(~+ (list.repeat size elemT))])))) (type: #export Nullary (-> (Vector +0 Expression) Expression)) (type: #export Unary (-> (Vector +1 Expression) Expression)) (type: #export Binary (-> (Vector +2 Expression) Expression)) (type: #export Trinary (-> (Vector +3 Expression) Expression)) (type: #export Variadic (-> (List Expression) Expression)) ## [Utils] (def: #export (install name unnamed) (-> Text (-> Text Proc) (-> Bundle Bundle)) (dict.put name (unnamed name))) (def: #export (prefix prefix bundle) (-> Text Bundle Bundle) (|> bundle dict.entries (list/map (function [[key val]] [(format prefix " " key) val])) (dict.from-list text.Hash))) (def: (wrong-arity proc expected actual) (-> Text Nat Nat Text) (format "Wrong number of arguments for " (%t proc) "\n" "Expected: " (|> expected nat-to-int %i) "\n" " Actual: " (|> actual nat-to-int %i))) (syntax: (arity: [name s.local-symbol] [arity s.nat]) (with-gensyms [g!proc g!name g!translate g!inputs] (do @ [g!input+ (monad.seq @ (list.repeat arity (macro.gensym "input")))] (wrap (list (` (def: #export ((~ (code.local-symbol name)) (~ g!proc)) (-> (-> (..Vector (~ (code.nat arity)) Expression) Expression) (-> Text ..Proc)) (function [(~ g!name)] (function [(~ g!translate) (~ g!inputs)] (case (~ g!inputs) (^ (list (~+ g!input+))) (do macro.Monad [(~+ (|> g!input+ (list/map (function [g!input] (list g!input (` ((~ g!translate) (~ g!input)))))) list.concat))] ((~' wrap) ((~ g!proc) [(~+ g!input+)]))) (~' _) (macro.fail (wrong-arity (~ g!name) +1 (list.size (~ g!inputs)))))))))))))) (arity: nullary +0) (arity: unary +1) (arity: binary +2) (arity: trinary +3) (def: #export (variadic proc) (-> Variadic (-> Text Proc)) (function [proc-name] (function [translate inputsS] (do macro.Monad [inputsI (monad.map @ translate inputsS)] (wrap (proc inputsI)))))) ## [Procedures] ## [[Lux]] (def: (lux//is [leftO rightO]) Binary (ruby.= leftO rightO)) (def: (lux//if [testO thenO elseO]) Trinary (caseT.translate-if testO thenO elseO)) (def: (lux//try riskyO) Unary (runtimeT.lux//try riskyO)) (def: (lux//noop valueO) Unary valueO) (exception: #export Wrong-Syntax) (def: #export (wrong-syntax procedure args) (-> Text (List ls.Synthesis) Text) (format "Procedure: " procedure "\n" "Arguments: " (%code (code.tuple args)))) (def: lux//loop (-> Text Proc) (function [proc-name] (function [translate inputsS] (case (s.run inputsS ($_ p.seq s.nat (s.tuple (p.many s.any)) s.any)) (#e.Success [offset initsS+ bodyS]) (loopT.translate-loop translate offset initsS+ bodyS) (#e.Error error) (&.throw Wrong-Syntax (wrong-syntax proc-name inputsS))) ))) (def: lux//recur (-> Text Proc) (function [proc-name] (function [translate inputsS] (loopT.translate-recur translate inputsS)))) (def: lux-procs Bundle (|> (dict.new text.Hash) (install "noop" (unary lux//noop)) (install "is" (binary lux//is)) (install "try" (unary lux//try)) (install "if" (trinary lux//if)) (install "loop" lux//loop) (install "recur" lux//recur) )) ## [[Bits]] (do-template [ ] [(def: ( [subjectO paramO]) Binary ( paramO subjectO))] [bit//and ruby.bit-and] [bit//or ruby.bit-or] [bit//xor ruby.bit-xor] ) (def: (bit//shift-left [subjectO paramO]) Binary (ruby.bit-and "0xFFFFFFFFFFFFFFFF" (ruby.bit-shl paramO subjectO))) (do-template [ ] [(def: ( [subjectO paramO]) Binary ( paramO subjectO))] [bit//shift-right ruby.bit-shr] [bit//unsigned-shift-right runtimeT.bit//shift-right] ) (def: bit//count Unary runtimeT.bit//count) (def: bit-procs Bundle (<| (prefix "bit") (|> (dict.new text.Hash) (install "count" (unary bit//count)) (install "and" (binary bit//and)) (install "or" (binary bit//or)) (install "xor" (binary bit//xor)) (install "shift-left" (binary bit//shift-left)) (install "unsigned-shift-right" (binary bit//unsigned-shift-right)) (install "shift-right" (binary bit//shift-right)) ))) ## [[Arrays]] (def: (array//new sizeO) Unary (ruby.apply "Array.new" (list sizeO))) (def: (array//get [arrayO idxO]) Binary (runtimeT.array//get arrayO idxO)) (def: (array//put [arrayO idxO elemO]) Trinary (runtimeT.array//put arrayO idxO elemO)) (def: (array//remove [arrayO idxO]) Binary (runtimeT.array//put arrayO idxO ruby.nil)) (def: array//size Unary ruby.length) (def: array-procs Bundle (<| (prefix "array") (|> (dict.new text.Hash) (install "new" (unary array//new)) (install "get" (binary array//get)) (install "put" (trinary array//put)) (install "remove" (binary array//remove)) (install "size" (unary array//size)) ))) ## [[Numbers]] (host.import java/lang/Double (#static MIN_VALUE Double) (#static MAX_VALUE Double)) (do-template [ ] [(def: ( _) Nullary ( ))] [nat//min 0 ruby.int] [nat//max -1 ruby.int] [frac//smallest Double::MIN_VALUE ruby.float] [frac//min (f/* -1.0 Double::MAX_VALUE) ruby.float] [frac//max Double::MAX_VALUE ruby.float] [deg//min 0 ruby.int] [deg//max -1 ruby.int] ) (do-template [ ] [(def: ( _) Nullary )] [int//min (|> (ruby.int -2) (ruby.pow (ruby.int 63)))] [int//max (|> (ruby.int 2) (ruby.pow (ruby.int 63)) (ruby.- (ruby.int 1)))] ) (do-template [ ] [(def: ( _) Nullary )] [frac//not-a-number (ruby./ (ruby.float 0.0) (ruby.float 0.0))] [frac//positive-infinity (ruby./ (ruby.float 0.0) (ruby.float 1.0))] [frac//negative-infinity (ruby./ (ruby.float 0.0) (ruby.float -1.0))] ) (do-template [ ] [(def: ( [subjectO paramO]) Binary (ruby.bit-and "0xFFFFFFFFFFFFFFFF" ( paramO subjectO)))] [int//add ruby.+] [int//sub ruby.-] [int//mul ruby.*] ) (do-template [ ] [(def: ( [subjectO paramO]) Binary ( paramO subjectO))] [int//div ruby./] [int//rem ruby.%] [nat//add ruby.+] [nat//sub ruby.-] [nat//mul ruby.*] [nat//div runtimeT.nat///] [nat//rem runtimeT.nat//%] [deg//add ruby.+] [deg//sub ruby.-] [deg//mul runtimeT.deg//*] [deg//div runtimeT.deg///] [deg//rem ruby.-] [deg//scale ruby.*] [deg//reciprocal ruby./] ) (do-template [ ] [(def: ( [subjectO paramO]) Binary ( paramO subjectO))] [frac//add ruby.+] [frac//sub ruby.-] [frac//mul ruby.*] [frac//div ruby./] [frac//rem ruby.%] [frac//= ruby.=] [frac//< ruby.<] [text//= ruby.=] [text//< ruby.<] ) (do-template [ ] [(def: ( [subjectO paramO]) Binary ( paramO subjectO))] [nat//= ruby.=] [nat//< runtimeT.nat//<] [int//= ruby.=] [int//< ruby.<] [deg//= ruby.=] [deg//< runtimeT.nat//<]) (do-template [] [(def: ( inputO) Unary inputO)] [nat//to-int] [int//to-nat] ) (def: frac//encode Unary (ruby.send "to_s" (list))) (def: (frac//decode inputO) Unary (ruby.call (list) (ruby.lambda #.None (list) (ruby.block! (list (ruby.set! (list "input") inputO) (ruby.set! (list "temp") (ruby.send "to_f" (list) "input")) (ruby.if! (ruby.or (ruby.not (ruby.= (ruby.float 0.0) "temp")) (ruby.or (ruby.= (ruby.string "0") "input") (ruby.= (ruby.string "0.0") "input"))) (ruby.return! (runtimeT.some "temp")) (ruby.return! runtimeT.none))))))) (do-template [ ] [(def: ( inputO) Unary (ruby./ inputO))] [int//to-frac (ruby.float 1.0)] [deg//to-frac (ruby.send "to_f" (list) (ruby.bit-shl (ruby.int 32) (ruby.int 1)))] ) (do-template [ ] [(def: Unary )] [frac//to-int (ruby.send "floor" (list))] [frac//to-deg runtimeT.deg//from-frac] ) (def: nat//char Unary (ruby.send "chr" (list))) (def: nat-procs Bundle (<| (prefix "nat") (|> (dict.new text.Hash) (install "+" (binary nat//add)) (install "-" (binary nat//sub)) (install "*" (binary nat//mul)) (install "/" (binary nat//div)) (install "%" (binary nat//rem)) (install "=" (binary nat//=)) (install "<" (binary nat//<)) (install "min" (nullary nat//min)) (install "max" (nullary nat//max)) (install "to-int" (unary nat//to-int)) (install "char" (unary nat//char))))) (def: int-procs Bundle (<| (prefix "int") (|> (dict.new text.Hash) (install "+" (binary int//add)) (install "-" (binary int//sub)) (install "*" (binary int//mul)) (install "/" (binary int//div)) (install "%" (binary int//rem)) (install "=" (binary int//=)) (install "<" (binary int//<)) (install "min" (nullary int//min)) (install "max" (nullary int//max)) (install "to-nat" (unary int//to-nat)) (install "to-frac" (unary int//to-frac))))) (def: deg-procs Bundle (<| (prefix "deg") (|> (dict.new text.Hash) (install "+" (binary deg//add)) (install "-" (binary deg//sub)) (install "*" (binary deg//mul)) (install "/" (binary deg//div)) (install "%" (binary deg//rem)) (install "=" (binary deg//=)) (install "<" (binary deg//<)) (install "scale" (binary deg//scale)) (install "reciprocal" (binary deg//reciprocal)) (install "min" (nullary deg//min)) (install "max" (nullary deg//max)) (install "to-frac" (unary deg//to-frac))))) (def: frac-procs Bundle (<| (prefix "frac") (|> (dict.new text.Hash) (install "+" (binary frac//add)) (install "-" (binary frac//sub)) (install "*" (binary frac//mul)) (install "/" (binary frac//div)) (install "%" (binary frac//rem)) (install "=" (binary frac//=)) (install "<" (binary frac//<)) (install "smallest" (nullary frac//smallest)) (install "min" (nullary frac//min)) (install "max" (nullary frac//max)) (install "not-a-number" (nullary frac//not-a-number)) (install "positive-infinity" (nullary frac//positive-infinity)) (install "negative-infinity" (nullary frac//negative-infinity)) (install "to-deg" (unary frac//to-deg)) (install "to-int" (unary frac//to-int)) (install "encode" (unary frac//encode)) (install "decode" (unary frac//decode))))) ## [[Text]] (do-template [ ] [(def: Unary (ruby.send (list)))] [text//size "length"] [text//upper "upcase"] [text//lower "downcase"] [text//trim "strip"] [text//hash "hash"] ) (def: (text//concat [subjectO paramO]) Binary (|> subjectO (ruby.+ paramO))) (def: (text//contains? [subjectO paramO]) Binary (ruby.send "include?" (list paramO) subjectO)) (def: (text//char [subjectO paramO]) Binary (runtimeT.text//char subjectO paramO)) (do-template [ ] [(def: ( [subjectO paramO extraO]) Trinary (ruby.send (list paramO extraO) subjectO))] [text//replace-all "gsub"] [text//replace-once "sub"] ) (def: (text//clip [subjectO paramO extraO]) Trinary (runtimeT.text//clip subjectO paramO extraO)) (def: (text//index [textO partO startO]) Trinary (runtimeT.text//index textO partO startO)) (def: text-procs Bundle (<| (prefix "text") (|> (dict.new text.Hash) (install "=" (binary text//=)) (install "<" (binary text//<)) (install "concat" (binary text//concat)) (install "index" (trinary text//index)) (install "size" (unary text//size)) (install "hash" (unary text//hash)) (install "replace-once" (trinary text//replace-once)) (install "replace-all" (trinary text//replace-all)) (install "char" (binary text//char)) (install "clip" (trinary text//clip)) (install "upper" (unary text//upper)) (install "lower" (unary text//lower)) ))) ## [[Math]] (do-template [ ] [(def: Unary (|>> (list) (ruby.apply )))] [math//cos "Math.cos"] [math//sin "Math.sin"] [math//tan "Math.tan"] [math//acos "Math.acos"] [math//asin "Math.asin"] [math//atan "Math.atan"] [math//exp "Math.exp"] [math//log "Math.log"] ) (do-template [ ] [(def: Unary (ruby.send (list)))] [math//ceil "ceil"] [math//floor "floor"] ) (def: (math//pow [inputO paramO]) Binary (ruby.pow paramO inputO)) (def: math-procs Bundle (<| (prefix "math") (|> (dict.new text.Hash) (install "cos" (unary math//cos)) (install "sin" (unary math//sin)) (install "tan" (unary math//tan)) (install "acos" (unary math//acos)) (install "asin" (unary math//asin)) (install "atan" (unary math//atan)) (install "exp" (unary math//exp)) (install "log" (unary math//log)) (install "ceil" (unary math//ceil)) (install "floor" (unary math//floor)) (install "pow" (binary math//pow)) ))) ## [[IO]] (def: (io//log messageO) Unary (ruby.or (ruby.apply "puts" (list (ruby.+ (ruby.string "\n") messageO))) runtimeT.unit)) (def: io//error Unary ruby.raise) (def: io//exit Unary (|>> (list) (ruby.apply "exit"))) (def: (io//current-time []) Nullary (|> "Time" (ruby.send "now" (list)) (ruby.send "to_f" (list)) (ruby.* (ruby.float 1000.0)) (ruby.send "to_i" (list)))) (def: io-procs Bundle (<| (prefix "io") (|> (dict.new text.Hash) (install "log" (unary io//log)) (install "error" (unary io//error)) (install "exit" (unary io//exit)) (install "current-time" (nullary io//current-time))))) ## [[Atoms]] (def: atom//new Unary (|>> [(ruby.string runtimeT.atom//field)] (list) ruby.dictionary)) (def: atom//read Unary (ruby.nth (ruby.string runtimeT.atom//field))) (def: (atom//compare-and-swap [atomO oldO newO]) Trinary (runtimeT.atom//compare-and-swap atomO oldO newO)) (def: atom-procs Bundle (<| (prefix "atom") (|> (dict.new text.Hash) (install "new" (unary atom//new)) (install "read" (unary atom//read)) (install "compare-and-swap" (trinary atom//compare-and-swap))))) ## [[Box]] (def: box//new Unary (|>> (list) ruby.array)) (def: box//read Unary (ruby.nth (ruby.int 0))) (def: (box//write [valueO boxO]) Binary (runtimeT.box//write valueO boxO)) (def: box-procs Bundle (<| (prefix "box") (|> (dict.new text.Hash) (install "new" (unary box//new)) (install "read" (unary box//read)) (install "write" (binary box//write))))) ## [[Processes]] (def: (process//concurrency-level []) Nullary (ruby.int 1)) (def: process//future Unary runtimeT.process//future) (def: (process//schedule [milli-secondsO procedureO]) Binary (runtimeT.process//schedule milli-secondsO procedureO)) (def: process-procs Bundle (<| (prefix "process") (|> (dict.new text.Hash) (install "concurrency-level" (nullary process//concurrency-level)) (install "future" (unary process//future)) (install "schedule" (binary process//schedule)) ))) ## [Bundles] (def: #export procedures Bundle (<| (prefix "lux") (|> lux-procs (dict.merge bit-procs) (dict.merge nat-procs) (dict.merge int-procs) (dict.merge deg-procs) (dict.merge frac-procs) (dict.merge text-procs) (dict.merge array-procs) (dict.merge math-procs) (dict.merge io-procs) (dict.merge atom-procs) (dict.merge box-procs) (dict.merge process-procs) )))