aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/target/js.lux
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/source/lux/target/js.lux')
-rw-r--r--stdlib/source/lux/target/js.lux397
1 files changed, 397 insertions, 0 deletions
diff --git a/stdlib/source/lux/target/js.lux b/stdlib/source/lux/target/js.lux
new file mode 100644
index 000000000..756530817
--- /dev/null
+++ b/stdlib/source/lux/target/js.lux
@@ -0,0 +1,397 @@
+(.module:
+ [lux (#- Code or and function if cond undefined for comment false true not)
+ [control
+ [pipe (#+ case>)]]
+ [data
+ ["." text
+ format]
+ [collection
+ ["." list ("#@." functor fold)]]]
+ [macro
+ ["." template]]
+ [type
+ abstract]])
+
+(def: argument (text.enclose ["(" ")"]))
+(def: element (text.enclose ["[" "]"]))
+
+(abstract: #export (Code brand)
+ {}
+
+ Text
+
+ (def: #export code
+ (-> (Code Any) Text)
+ (|>> :representation))
+
+ (template [<type> <brand> <super>+]
+ [(abstract: #export (<brand> brand) {} Any)
+ (`` (type: #export <type> (|> Any <brand> (~~ (template.splice <super>+)))))]
+
+ [Expression Expression' [Code]]
+ [Computation Computation' [Expression' Code]]
+ [Location Location' [Computation' Expression' Code]]
+ [Statement Statement' [Code]]
+ )
+
+ (template [<type> <brand> <super>+]
+ [(abstract: #export <brand> {} Any)
+ (`` (type: #export <type> (|> <brand> (~~ (template.splice <super>+)))))]
+
+ [Var Var' [Location' Computation' Expression' Code]]
+ [Access Access' [Location' Computation' Expression' Code]]
+ [Loop Loop' [Statement' Code]]
+ [Label Label' [Code]]
+ )
+
+ (template [<name> <literal>]
+ [(def: #export <name> Computation (|> <literal> ..argument :abstraction))]
+
+ [null "null"]
+ [undefined "undefined"]
+ [false "false"]
+ [true "true"]
+ [positive-infinity "Infinity"]
+ [negative-infinity "-Infinity"]
+ [not-a-number "NaN"]
+ )
+
+ (def: #export boolean
+ (-> Bit Computation)
+ (|>> (case>
+ #0 ..false
+ #1 ..true)))
+
+ (def: #export number
+ (-> Frac Computation)
+ (|>> %f ..argument :abstraction))
+
+ (def: sanitize
+ (-> Text Text)
+ (`` (|>> (~~ (template [<find> <replace>]
+ [(text.replace-all <find> <replace>)]
+
+ ["\" "\\"]
+ [text.tab "\t"]
+ [text.vertical-tab "\v"]
+ [text.null "\0"]
+ [text.back-space "\b"]
+ [text.form-feed "\f"]
+ [text.new-line "\n"]
+ [text.carriage-return "\r"]
+ [text.double-quote (format "\" text.double-quote)]
+ ))
+ )))
+
+ (def: #export string
+ (-> Text Computation)
+ (|>> ..sanitize
+ (text.enclose [text.double-quote text.double-quote])
+ :abstraction))
+
+ (def: argument-separator ", ")
+ (def: field-separator ": ")
+ (def: statement-suffix ";")
+
+ (def: #export array
+ (-> (List Expression) Computation)
+ (|>> (list@map ..code)
+ (text.join-with ..argument-separator)
+ ..element
+ :abstraction))
+
+ (def: #export var
+ (-> Text Var)
+ (|>> :abstraction))
+
+ (def: #export (at index array-or-object)
+ (-> Expression Expression Access)
+ (|> (format (:representation array-or-object) (..element (:representation index)))
+ ..argument
+ :abstraction))
+
+ (def: #export (the field object)
+ (-> Text Expression Access)
+ (:abstraction (format (:representation object) "." field)))
+
+ (def: #export (apply/* function inputs)
+ (-> Expression (List Expression) Computation)
+ (|> inputs
+ (list@map ..code)
+ (text.join-with ..argument-separator)
+ ..argument
+ (format (:representation function))
+ :abstraction))
+
+ (def: #export (do method inputs object)
+ (-> Text (List Expression) Expression Computation)
+ (apply/* (..the method object) inputs))
+
+ (def: #export object
+ (-> (List [Text Expression]) Computation)
+ (|>> (list@map (.function (_ [key val])
+ (format (:representation (..string key)) ..field-separator (:representation val))))
+ (text.join-with ..argument-separator)
+ (text.enclose ["{" "}"])
+ ..argument
+ :abstraction))
+
+ (def: #export (, pre post)
+ (-> Expression Expression Computation)
+ (|> (format (:representation pre) ", " (:representation post))
+ ..argument
+ :abstraction))
+
+ (def: #export (then pre post)
+ (-> Statement Statement Statement)
+ (:abstraction (format (:representation pre)
+ text.new-line
+ (:representation post))))
+
+ ## (def: indent
+ ## (-> Text Text)
+ ## (text.replace-all text.new-line (format text.new-line text.tab)))
+
+ (def: block
+ (-> Statement Text)
+ (let [close (format text.new-line "}")]
+ (|>> :representation
+ (format text.new-line)
+ ## ..indent
+ (text.enclose ["{"
+ close]))))
+
+ (def: #export (function name inputs body)
+ (-> Var (List Var) Statement Computation)
+ (|> body
+ ..block
+ (format "function " (:representation name)
+ (|> inputs
+ (list@map ..code)
+ (text.join-with ..argument-separator)
+ ..argument)
+ " ")
+ ..argument
+ :abstraction))
+
+ (def: #export (closure inputs body)
+ (-> (List Var) Statement Computation)
+ (|> body
+ ..block
+ (format "function"
+ (|> inputs
+ (list@map ..code)
+ (text.join-with ..argument-separator)
+ ..argument)
+ " ")
+ ..argument
+ :abstraction))
+
+ (template [<name> <op>]
+ [(def: #export (<name> param subject)
+ (-> Expression Expression Computation)
+ (|> (format (:representation subject) " " <op> " " (:representation param))
+ ..argument
+ :abstraction))]
+
+ [= "==="]
+ [< "<"]
+ [<= "<="]
+ [> ">"]
+ [>= ">="]
+
+ [+ "+"]
+ [- "-"]
+ [* "*"]
+ [/ "/"]
+ [% "%"]
+
+ [left-shift "<<"]
+ [arithmetic-right-shift ">>"]
+ [logic-right-shift ">>>"]
+
+ [or "||"]
+ [and "&&"]
+ [bit-xor "^"]
+ [bit-or "|"]
+ [bit-and "&"]
+ )
+
+ (template [<name> <prefix>]
+ [(def: #export <name>
+ (-> Expression Computation)
+ (|>> :representation (text.prefix <prefix>) ..argument :abstraction))]
+
+ [not "!"]
+ [bit-not "~"]
+ [negate "-"]
+ )
+
+ (template [<name> <input> <format>]
+ [(def: #export (<name> value)
+ {#.doc "A 32-bit integer expression."}
+ (-> <input> Computation)
+ (:abstraction (..argument (format (<format> value) "|0"))))]
+
+ [to-i32 Expression :representation]
+ [i32 Int %i]
+ )
+
+ (def: #export (? test then else)
+ (-> Expression Expression Expression Computation)
+ (|> (format (:representation test)
+ " ? " (:representation then)
+ " : " (:representation else))
+ ..argument
+ :abstraction))
+
+ (def: #export type-of
+ (-> Expression Computation)
+ (|>> :representation
+ (format "typeof ")
+ ..argument
+ :abstraction))
+
+ (def: #export (new constructor inputs)
+ (-> Expression (List Expression) Computation)
+ (|> (format "new " (:representation constructor)
+ (|> inputs
+ (list@map ..code)
+ (text.join-with ..argument-separator)
+ ..argument))
+ ..argument
+ :abstraction))
+
+ (def: #export statement
+ (-> Expression Statement)
+ (|>> :representation (text.suffix ..statement-suffix) :abstraction))
+
+ (def: #export use-strict
+ Statement
+ (:abstraction (format text.double-quote "use strict" text.double-quote ..statement-suffix)))
+
+ (def: #export (declare name)
+ (-> Var Statement)
+ (:abstraction (format "var " (:representation name) ..statement-suffix)))
+
+ (def: #export (define name value)
+ (-> Var Expression Statement)
+ (:abstraction (format "var " (:representation name) " = " (:representation value) ..statement-suffix)))
+
+ (def: #export (set name value)
+ (-> Location Expression Statement)
+ (:abstraction (format (:representation name) " = " (:representation value) ..statement-suffix)))
+
+ (def: #export (throw message)
+ (-> Expression Statement)
+ (:abstraction (format "throw " (:representation message) ..statement-suffix)))
+
+ (def: #export (return value)
+ (-> Expression Statement)
+ (:abstraction (format "return " (:representation value) ..statement-suffix)))
+
+ (def: #export (delete value)
+ (-> Location Statement)
+ (:abstraction (format "delete " (:representation value) ..statement-suffix)))
+
+ (def: #export (if test then! else!)
+ (-> Expression Statement Statement Statement)
+ (:abstraction (format "if(" (:representation test) ") "
+ (..block then!)
+ " else "
+ (..block else!))))
+
+ (def: #export (when test then!)
+ (-> Expression Statement Statement)
+ (:abstraction (format "if(" (:representation test) ") "
+ (..block then!))))
+
+ (def: #export (while test body)
+ (-> Expression Statement Loop)
+ (:abstraction (format "while(" (:representation test) ") "
+ (..block body))))
+
+ (def: #export (do-while test body)
+ (-> Expression Statement Loop)
+ (:abstraction (format "do " (..block body)
+ " while(" (:representation test) ")" ..statement-suffix)))
+
+ (def: #export (try body [exception catch])
+ (-> Statement [Var Statement] Statement)
+ (:abstraction (format "try "
+ (..block body)
+ " catch(" (:representation exception) ") "
+ (..block catch))))
+
+ (def: #export (for var init condition update iteration)
+ (-> Var Expression Expression Expression Statement Loop)
+ (:abstraction (format "for(" (:representation (..define var init))
+ " " (:representation condition)
+ ..statement-suffix " " (:representation update)
+ ")"
+ (..block iteration))))
+
+ (def: #export label
+ (-> Text Label)
+ (|>> :abstraction))
+
+ (def: #export (with-label label loop)
+ (-> Label Loop Statement)
+ (:abstraction (format (:representation label) ": " (:representation loop))))
+
+ (template [<keyword> <0> <1>]
+ [(def: #export <0>
+ Statement
+ (:abstraction (format <keyword> ..statement-suffix)))
+
+ (def: #export (<1> label)
+ (-> Label Statement)
+ (:abstraction (format <keyword> " " (:representation label) ..statement-suffix)))]
+
+ ["break" break break-at]
+ ["continue" continue continue-at]
+ )
+
+ (template [<name> <js>]
+ [(def: #export <name>
+ (-> Location Expression)
+ (|>> :representation
+ (text.suffix <js>)
+ :abstraction))]
+
+ [++ "++"]
+ [-- "--"]
+ )
+
+ (def: #export (comment commentary on)
+ (All [kind] (-> Text (Code kind) (Code kind)))
+ (:abstraction (format "/* " commentary " */" " " (:representation on))))
+ )
+
+(def: #export (cond clauses else!)
+ (-> (List [Expression Statement]) Statement Statement)
+ (list@fold (.function (_ [test then!] next!)
+ (..if test then! next!))
+ else!
+ (list.reverse clauses)))
+
+(template [<apply> <arg>+ <type>+ <function>+]
+ [(`` (def: #export (<apply> function)
+ (-> Expression (~~ (template.splice <type>+)) Computation)
+ (.function (_ (~~ (template.splice <arg>+)))
+ (..apply/* function (list (~~ (template.splice <arg>+)))))))
+
+ (`` (template [<definition> <function>]
+ [(def: #export <definition> (<apply> (..var <function>)))]
+
+ (~~ (template.splice <function>+))))]
+
+ [apply/1 [_0] [Expression]
+ [[not-a-number? "isNaN"]]]
+
+ [apply/2 [_0 _1] [Expression Expression]
+ []]
+
+ [apply/3 [_0 _1 _2] [Expression Expression Expression]
+ []]
+ )