aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduardo Julian2021-03-01 01:49:30 -0400
committerEduardo Julian2021-03-01 01:49:30 -0400
commitcbc41f10fb3e0e776767d2266b22068172b0f69a (patch)
tree0344edcbe40edf51d16eb70b12a72e97e3c37f11
parent69edb6de2ecf62881bcde1b8013c98450a6a52bc (diff)
Done with Ruby.
-rw-r--r--compilers.md26
-rw-r--r--lux-ruby/source/program.lux196
-rw-r--r--stdlib/source/lux.lux2
-rw-r--r--stdlib/source/lux/control/concurrency/atom.lux9
-rw-r--r--stdlib/source/lux/control/thread.lux3
-rw-r--r--stdlib/source/lux/data/collection/array.lux15
-rw-r--r--stdlib/source/lux/data/text/encoding.lux37
-rw-r--r--stdlib/source/lux/data/text/format.lux9
-rw-r--r--stdlib/source/lux/debug.lux43
-rw-r--r--stdlib/source/lux/host.rb.lux334
-rw-r--r--stdlib/source/lux/math.lux40
-rw-r--r--stdlib/source/lux/target/ruby.lux47
-rw-r--r--stdlib/source/lux/tool/compiler/language/lux/phase/extension/analysis/lua.lux7
-rw-r--r--stdlib/source/lux/tool/compiler/language/lux/phase/extension/analysis/ruby.lux164
-rw-r--r--stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/ruby.lux4
-rw-r--r--stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/ruby/common.lux85
-rw-r--r--stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/ruby/host.lux135
-rw-r--r--stdlib/source/lux/tool/compiler/language/lux/phase/generation/python.lux4
-rw-r--r--stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/case.lux50
-rw-r--r--stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/runtime.lux45
-rw-r--r--stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby.lux59
-rw-r--r--stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/case.lux169
-rw-r--r--stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/function.lux19
-rw-r--r--stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/loop.lux99
-rw-r--r--stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/runtime.lux109
-rw-r--r--stdlib/source/lux/world/file.lux211
-rw-r--r--stdlib/source/lux/world/program.lux34
-rw-r--r--stdlib/source/test/lux.lux3
-rw-r--r--stdlib/source/test/lux/extension.lux6
-rw-r--r--stdlib/source/test/lux/host.rb.lux24
30 files changed, 1637 insertions, 351 deletions
diff --git a/compilers.md b/compilers.md
index 0bea1a06c..3e70d6137 100644
--- a/compilers.md
+++ b/compilers.md
@@ -198,25 +198,25 @@ cd ~/lux/stdlib/ \
---
-# PHP compiler
+# Ruby compiler
## Test
```
-cd ~/lux/lux-php/ && lein lux auto test
-cd ~/lux/lux-php/ && lein clean && lein lux auto test
+cd ~/lux/lux-ruby/ && lein lux auto test
+cd ~/lux/lux-ruby/ && lein clean && lein lux auto test
```
## Build
```
## Develop
-cd ~/lux/lux-php/ \
+cd ~/lux/lux-ruby/ \
&& lein clean \
&& lein lux auto build
## Build JVM-based compiler
-cd ~/lux/lux-php/ \
+cd ~/lux/lux-ruby/ \
&& lein clean \
&& lein lux build \
&& mv target/program.jar jvm_based_compiler.jar
@@ -228,30 +228,32 @@ cd ~/lux/lux-php/ \
## Compile Lux's Standard Library's tests using a JVM-based compiler.
cd ~/lux/stdlib/ \
&& lein clean \
-&& time java -jar ~/lux/lux-php/jvm_based_compiler.jar build --source ~/lux/stdlib/source --target ~/lux/stdlib/target --module test/lux
+&& time java -jar ~/lux/lux-ruby/target/program.jar build --source ~/lux/stdlib/source --target ~/lux/stdlib/target --module test/lux
+
+RUBY_THREAD_VM_STACK_SIZE=15700000 ruby ~/lux/stdlib/target/program.rb
```
---
-# Ruby compiler
+# PHP compiler
## Test
```
-cd ~/lux/lux-ruby/ && lein lux auto test
-cd ~/lux/lux-ruby/ && lein clean && lein lux auto test
+cd ~/lux/lux-php/ && lein lux auto test
+cd ~/lux/lux-php/ && lein clean && lein lux auto test
```
## Build
```
## Develop
-cd ~/lux/lux-ruby/ \
+cd ~/lux/lux-php/ \
&& lein clean \
&& lein lux auto build
## Build JVM-based compiler
-cd ~/lux/lux-ruby/ \
+cd ~/lux/lux-php/ \
&& lein clean \
&& lein lux build \
&& mv target/program.jar jvm_based_compiler.jar
@@ -263,7 +265,7 @@ cd ~/lux/lux-ruby/ \
## Compile Lux's Standard Library's tests using a JVM-based compiler.
cd ~/lux/stdlib/ \
&& lein clean \
-&& time java -jar ~/lux/lux-ruby/jvm_based_compiler.jar build --source ~/lux/stdlib/source --target ~/lux/stdlib/target --module test/lux
+&& time java -jar ~/lux/lux-php/jvm_based_compiler.jar build --source ~/lux/stdlib/source --target ~/lux/stdlib/target --module test/lux
```
---
diff --git a/lux-ruby/source/program.lux b/lux-ruby/source/program.lux
index 044e97923..64a34c003 100644
--- a/lux-ruby/source/program.lux
+++ b/lux-ruby/source/program.lux
@@ -29,6 +29,7 @@
[math
[number
["n" nat]
+ ["i" int]
["." i64]]]
["." world #_
["." file]
@@ -90,6 +91,10 @@
(#static newInternalFromJavaExternal [org/jruby/Ruby java/lang/String] org/jruby/RubyString)
(asJavaString [] java/lang/String)])
+(import: org/jruby/RubySymbol
+ ["#::."
+ (asJavaString [] java/lang/String)])
+
(import: org/jruby/runtime/builtin/IRubyObject)
(import: org/jruby/Ruby
@@ -110,6 +115,11 @@
(import: org/jruby/runtime/ThreadContext)
+(import: org/jruby/RubyRange
+ ["#::."
+ (first [org/jruby/runtime/ThreadContext] org/jruby/runtime/builtin/IRubyObject)
+ (size [org/jruby/runtime/ThreadContext] org/jruby/runtime/builtin/IRubyObject)])
+
(template [<name>]
[(host.interface: <name>
(getValue [] java/lang/Object))
@@ -311,6 +321,18 @@
(exception.report
["Index" (%.nat index)]))
+(exception: (invalid_index {index java/lang/Object})
+ (exception.report
+ ["Class" (|> index
+ java/lang/Object::getClass
+ java/lang/Object::toString)]
+ ["Index" (|> index
+ java/lang/Object::toString)]))
+
+(import: java/util/Arrays
+ ["#::."
+ (#static [t] copyOfRange [[t] int int] [t])])
+
(def: (lux_wrapper_access lux_structure value)
(-> (-> (Array java/lang/Object) org/jruby/runtime/builtin/IRubyObject)
(-> (Array java/lang/Object) org/jruby/internal/runtime/methods/DynamicMethod))
@@ -327,48 +349,61 @@
{block org/jruby/runtime/Block})
org/jruby/runtime/builtin/IRubyObject
(let [member (host.array_read 0 args)]
- (case (host.check org/jruby/RubyFixnum member)
- (#.Some member)
- (case (array.read (org/jruby/RubyFixnum::getLongValue member) value)
- (#.Some value)
- (wrapped_lux_value lux_structure value)
-
- #.None
- (error! (exception.construct ..invalid_tuple_access [(org/jruby/RubyFixnum::getLongValue member)])))
-
- #.None
- (case (host.check org/jruby/RubyString member)
- (#.Some member)
- (case (:coerce Text (org/jruby/RubyString::asJavaString member))
- (^ (static runtime.variant_tag_field))
- (|> value
- (array.read 0)
- maybe.assume
- (:coerce java/lang/Integer)
- java/lang/Integer::longValue
- (org/jruby/RubyFixnum::new ..initial_ruby_runtime))
-
- (^ (static runtime.variant_flag_field))
- (case (array.read 1 value)
- #.None
- ..ruby_nil
-
- (#.Some flag)
- ..lux_unit)
-
- (^ (static runtime.variant_value_field))
- (case (array.read 2 value)
+ (<| (case (host.check org/jruby/RubyFixnum member)
+ (#.Some member)
+ (case (array.read (org/jruby/RubyFixnum::getLongValue member) value)
(#.Some value)
(wrapped_lux_value lux_structure value)
#.None
- (error! (exception.construct ..nil_has_no_lux_representation [])))
+ (error! (exception.construct ..invalid_tuple_access [(org/jruby/RubyFixnum::getLongValue member)])))
+
+ #.None)
+ (case (host.check org/jruby/RubyString member)
+ (#.Some member)
+ (case (:coerce Text (org/jruby/RubyString::asJavaString member))
+ (^ (static runtime.variant_tag_field))
+ (|> value
+ (array.read 0)
+ maybe.assume
+ (:coerce java/lang/Integer)
+ java/lang/Integer::longValue
+ (org/jruby/RubyFixnum::new ..initial_ruby_runtime))
+
+ (^ (static runtime.variant_flag_field))
+ (case (array.read 1 value)
+ #.None
+ ..ruby_nil
+
+ (#.Some flag)
+ ..lux_unit)
+
+ (^ (static runtime.variant_value_field))
+ (case (array.read 2 value)
+ (#.Some value)
+ (wrapped_lux_value lux_structure value)
- field
- (error! (exception.construct ..invalid_variant_access [field])))
-
- #.None
- (error! (format "lux_wrapper_access INVALID INDEX"))))))))
+ #.None
+ (error! (exception.construct ..nil_has_no_lux_representation [])))
+
+ field
+ (error! (exception.construct ..invalid_variant_access [field])))
+
+ #.None)
+ (case (host.check org/jruby/RubyRange member)
+ (#.Some member)
+ (case [(|> member (org/jruby/RubyRange::first thread_context) (host.check org/jruby/RubyFixnum))
+ (|> member (org/jruby/RubyRange::size thread_context) (host.check org/jruby/RubyFixnum))]
+ [(#.Some first) (#.Some size)]
+ (let [first (org/jruby/RubyFixnum::getLongValue first)
+ size (org/jruby/RubyFixnum::getLongValue size)]
+ (lux_structure (java/util/Arrays::copyOfRange value first (i.+ first size))))
+
+ _
+ (error! (exception.construct ..invalid_index (:coerce java/lang/Object member))))
+
+ #.None)
+ (error! (exception.construct ..invalid_index (:coerce java/lang/Object member))))))))
(def: (lux_wrapper_equality value)
(-> (Array java/lang/Object) org/jruby/internal/runtime/methods/DynamicMethod)
@@ -410,6 +445,63 @@
array.size
(org/jruby/RubyFixnum::new ..initial_ruby_runtime)))))
+(def: (lux_wrapper_to_s value)
+ (-> (Array java/lang/Object) org/jruby/internal/runtime/methods/DynamicMethod)
+ (host.object [] org/jruby/internal/runtime/methods/DynamicMethod []
+ [{java/lang/String "to_s"}]
+
+ (org/jruby/internal/runtime/methods/DynamicMethod
+ [] (call self
+ {thread_context org/jruby/runtime/ThreadContext}
+ {self org/jruby/runtime/builtin/IRubyObject}
+ {module org/jruby/RubyModule}
+ {method java/lang/String}
+ {args [org/jruby/runtime/builtin/IRubyObject]}
+ {block org/jruby/runtime/Block})
+ org/jruby/runtime/builtin/IRubyObject
+ (|> value
+ debug.inspect
+ (org/jruby/RubyString::newInternalFromJavaExternal ..initial_ruby_runtime)))))
+
+(exception: (invalid_operation {method Text})
+ (exception.report
+ ["Method" (%.text method)]))
+
+(def: (lux_wrapper_respond_to? value)
+ (-> (Array java/lang/Object) org/jruby/internal/runtime/methods/DynamicMethod)
+ (host.object [] org/jruby/internal/runtime/methods/DynamicMethod []
+ [{java/lang/String "respond_to?"}]
+
+ (org/jruby/internal/runtime/methods/DynamicMethod
+ [] (call self
+ {thread_context org/jruby/runtime/ThreadContext}
+ {self org/jruby/runtime/builtin/IRubyObject}
+ {module org/jruby/RubyModule}
+ {method java/lang/String}
+ {args [org/jruby/runtime/builtin/IRubyObject]}
+ {block org/jruby/runtime/Block})
+ org/jruby/runtime/builtin/IRubyObject
+ (case (|> args
+ (host.array_read 0)
+ (host.check org/jruby/RubySymbol))
+ (#.Some method)
+ (|> (case (|> method
+ org/jruby/RubySymbol::asJavaString
+ (:coerce Text))
+ (^or "==" "equal?"
+ "to_s" "inspect"
+ "[]" "length" "respond_to?"
+ ## "to_hash"
+ )
+ true
+
+ _
+ false)
+ (org/jruby/RubyBoolean::newBoolean ..initial_ruby_runtime))
+
+ #.None
+ (error! (exception.construct ..invalid_operation ["respond_to?"]))))))
+
(exception: (unknown_method {method Text})
(exception.report
["Method" (%.text method)]))
@@ -428,12 +520,18 @@
"[]"
(org/jruby/runtime/callsite/CacheEntry::new (..lux_wrapper_access lux_structure value) 0)
- "=="
+ (^or "==" "equal?")
(org/jruby/runtime/callsite/CacheEntry::new (..lux_wrapper_equality value) 1)
"length"
(org/jruby/runtime/callsite/CacheEntry::new (..lux_wrapper_length value) 2)
+ (^or "to_s" "inspect")
+ (org/jruby/runtime/callsite/CacheEntry::new (..lux_wrapper_to_s value) 3)
+
+ "respond_to?"
+ (org/jruby/runtime/callsite/CacheEntry::new (..lux_wrapper_respond_to? value) 4)
+
_
(error! (exception.construct ..unknown_method [(:coerce Text method)])))))]
(org/jruby/java/proxies/JavaProxy::new ..initial_ruby_runtime meta_class (:coerce java/lang/Object value))))
@@ -519,7 +617,7 @@
(run! (_.global (reference.artifact context))))))))))
(def: platform
- (IO (Platform _.LVar _.Expression _.Statement))
+ (IO (Platform Register _.Expression _.Statement))
(do io.monad
[host ..host]
(wrap {#platform.&file_system (file.async file.default)
@@ -530,9 +628,9 @@
(def: (program context program)
(Program _.Expression _.Statement)
- (_.statement (_.apply/* (list (runtime.lux//program_args _.command_line_arguments)
- _.nil)
- program)))
+ (_.statement (_.apply_lambda/* (list (runtime.lux//program_args _.command_line_arguments)
+ _.nil)
+ program)))
(def: extender
Extender
@@ -564,14 +662,6 @@
(-> Any (Promise Any))
(promise.future (\ world/program.default exit +0)))
-(def: (scope body!)
- (-> _.Statement _.Statement)
- (let [@program (_.local "lux_program")]
- ($_ _.then
- (_.function @program (list) body!)
- (_.statement (_.apply/* (list) @program))
- )))
-
(program: [{service /cli.service}]
(let [extension ".rb"]
(exec (do promise.monad
@@ -585,15 +675,13 @@
generation.bundle
extension/bundle.empty
..program
- [_.LVar
- _.Expression
- _.Statement]
+ [Register _.Expression _.Statement]
..extender
service
[(packager.package (: _.Statement (_.manual ""))
_.code
_.then
- ..scope)
+ (|>>))
(format (/cli.target service)
(\ file.default separator)
"program"
diff --git a/stdlib/source/lux.lux b/stdlib/source/lux.lux
index c18603b4b..1bb7efa07 100644
--- a/stdlib/source/lux.lux
+++ b/stdlib/source/lux.lux
@@ -5281,6 +5281,8 @@
_
(\ meta_monad return token)
+ ## TODO: Figure out why this doesn't work:
+ ## (\ meta_monad wrap token)
))
(macro: #export (static tokens)
diff --git a/stdlib/source/lux/control/concurrency/atom.lux b/stdlib/source/lux/control/concurrency/atom.lux
index 3b57678fc..350554437 100644
--- a/stdlib/source/lux/control/concurrency/atom.lux
+++ b/stdlib/source/lux/control/concurrency/atom.lux
@@ -25,15 +25,18 @@
(with_expansions [<new> (for {@.js "js array new"
@.python "python array new"
- @.lua "lua array new"}
+ @.lua "lua array new"
+ @.ruby "ruby array new"}
(as_is))
<write> (for {@.js "js array write"
@.python "python array write"
- @.lua "lua array write"}
+ @.lua "lua array write"
+ @.ruby "ruby array write"}
(as_is))
<read> (for {@.js "js array read"
@.python "python array read"
- @.lua "lua array read"}
+ @.lua "lua array read"
+ @.ruby "ruby array read"}
(as_is))]
(abstract: #export (Atom a)
(with_expansions [<jvm> (java/util/concurrent/atomic/AtomicReference a)]
diff --git a/stdlib/source/lux/control/thread.lux b/stdlib/source/lux/control/thread.lux
index 8e707e6d2..6be40ef63 100644
--- a/stdlib/source/lux/control/thread.lux
+++ b/stdlib/source/lux/control/thread.lux
@@ -44,7 +44,8 @@
@.js ("js array read" 0 (:representation box))
@.python ("python array read" 0 (:representation box))
- @.lua ("lua array read" 0 (:representation box))})))
+ @.lua ("lua array read" 0 (:representation box))
+ @.ruby ("ruby array read" 0 (:representation box))})))
(def: #export (write value box)
(All [a] (-> a (All [!] (-> (Box ! a) (Thread ! Any)))))
diff --git a/stdlib/source/lux/data/collection/array.lux b/stdlib/source/lux/data/collection/array.lux
index 0bc661941..b9162e53a 100644
--- a/stdlib/source/lux/data/collection/array.lux
+++ b/stdlib/source/lux/data/collection/array.lux
@@ -47,7 +47,8 @@
@.js ("js array new" size)
@.python ("python array new" size)
- @.lua ("lua array new" size)}))
+ @.lua ("lua array new" size)
+ @.ruby ("ruby array new" size)}))
(def: #export (size array)
(All [a] (-> (Array a) Nat))
@@ -65,7 +66,8 @@
@.js ("js array length" array)
@.python ("python array length" array)
- @.lua ("lua array length" array)}))
+ @.lua ("lua array length" array)
+ @.ruby ("ruby array length" array)}))
(template: (!read <read> <null?>)
(let [output (<read> index array)]
@@ -93,7 +95,8 @@
@.js (!read "js array read" "js object undefined?")
@.python (!read "python array read" "python object none?")
- @.lua (!read "lua array read" "lua object nil?")})
+ @.lua (!read "lua array read" "lua object nil?")
+ @.ruby (!read "ruby array read" "ruby object nil?")})
#.None))
(def: #export (write! index value array)
@@ -110,7 +113,8 @@
@.js ("js array write" index value array)
@.python ("python array write" index value array)
- @.lua ("lua array write" index value array)}))
+ @.lua ("lua array write" index value array)
+ @.ruby ("ruby array write" index value array)}))
(def: #export (delete! index array)
(All [a]
@@ -124,7 +128,8 @@
@.js ("js array delete" index array)
@.python ("python array delete" index array)
- @.lua ("lua array delete" index array)})
+ @.lua ("lua array delete" index array)
+ @.ruby ("ruby array delete" index array)})
array))
)
diff --git a/stdlib/source/lux/data/text/encoding.lux b/stdlib/source/lux/data/text/encoding.lux
index 55afc77ed..88bbea138 100644
--- a/stdlib/source/lux/data/text/encoding.lux
+++ b/stdlib/source/lux/data/text/encoding.lux
@@ -192,7 +192,16 @@
(host.import: TextDecoder
(new [host.String])
- (decode [Uint8Array] host.String)))}
+ (decode [Uint8Array] host.String)))
+
+ @.ruby
+ (as_is (host.import: String #as RubyString
+ (encode [Text] RubyString)
+ (force_encoding [Text] Text)
+ (bytes [] Binary))
+
+ (host.import: Array #as RubyArray
+ (pack [Text] RubyString)))}
(as_is)))
(def: (utf8\encode value)
@@ -224,10 +233,16 @@
)
@.python
- (:coerce Binary ("python apply" (:assume ("python constant" "bytearray")) value "utf-8"))}
+ (:coerce Binary ("python apply" (:assume ("python constant" "bytearray")) value "utf-8"))
- ## Default
- ("lua utf8 encode" value)))
+ @.lua
+ ("lua utf8 encode" value)
+
+ @.ruby
+ (|> value
+ (:coerce RubyString)
+ (RubyString::encode ["UTF-8"])
+ (RubyString::bytes []))}))
(def: (utf8\decode value)
(-> Binary (Try Text))
@@ -252,10 +267,18 @@
#try.Success))
@.python
- (host.try (:coerce Text ("python object do" "decode" (:assume value) "utf-8")))}
+ (host.try (:coerce Text ("python object do" "decode" (:assume value) "utf-8")))
+
+ @.lua
+ (#try.Success ("lua utf8 decode" value))
- ## Default
- (#try.Success ("lua utf8 decode" value)))))
+ @.ruby
+ (|> value
+ (:coerce RubyArray)
+ (RubyArray::pack ["C*"])
+ (:coerce RubyString)
+ (RubyString::force_encoding ["UTF-8"])
+ #try.Success)})))
(structure: #export utf8
(Codec Binary Text)
diff --git a/stdlib/source/lux/data/text/format.lux b/stdlib/source/lux/data/text/format.lux
index 2232e0b6d..c67ce2030 100644
--- a/stdlib/source/lux/data/text/format.lux
+++ b/stdlib/source/lux/data/text/format.lux
@@ -16,7 +16,7 @@
["." json]]
[collection
["." list ("#\." monad)]]]
- [time
+ ["." time
["." instant]
["." duration]
["." date]]
@@ -62,16 +62,21 @@
[rev Rev (\ rev.decimal encode)]
[frac Frac (\ frac.decimal encode)]
[ratio ratio.Ratio (\ ratio.codec encode)]
+
[text Text text.format]
+
[name Name (\ name.codec encode)]
+ [location Location location.format]
[code Code code.format]
[type Type type.format]
+
[xml xml.XML (\ xml.codec encode)]
[json json.JSON (\ json.codec encode)]
+
[instant instant.Instant (\ instant.codec encode)]
[duration duration.Duration (\ duration.codec encode)]
[date date.Date (\ date.codec encode)]
- [location Location location.format]
+ [time time.Time (\ time.codec encode)]
)
(template [<type> <format>,<codec>]
diff --git a/stdlib/source/lux/debug.lux b/stdlib/source/lux/debug.lux
index 8006c83dd..47d62fd34 100644
--- a/stdlib/source/lux/debug.lux
+++ b/stdlib/source/lux/debug.lux
@@ -79,7 +79,13 @@
(import: (tostring [.Any] host.String))
(import: math
- (#static type [.Any] #? host.String)))}))
+ (#static type [.Any] #? host.String)))
+
+ @.ruby
+ (as_is (import: Class)
+
+ (import: Object
+ (type [] Class)))}))
(def: Inspector (-> Any Text))
@@ -230,6 +236,41 @@
_
(..tostring value))
+
+ @.ruby
+ (template.with [(class_of <literal>)
+ (Object::type (:coerce ..Object <literal>))]
+ (let [value_class (Object::type (:coerce ..Object value))]
+ (`` (cond (~~ (template [<literal> <type> <format>]
+ [(is? (class_of <literal>) value_class)
+ (|> value (:coerce <type>) <format>)]
+
+ [#0 Bit %.bit]
+ [#1 Bit %.bit]
+ [+123 Int %.int]
+ [+123.456 Frac %.frac]
+ ["+123.456" Text %.text]
+ [("ruby object nil") Any (new> "nil" [])]
+ ))
+
+ (is? (class_of #.None) value_class)
+ (let [variant_tag ("ruby object get" "_lux_tag" value)
+ variant_flag ("ruby object get" "_lux_flag" value)
+ variant_value ("ruby object get" "_lux_value" value)]
+ (if (not (or ("ruby object nil?" variant_tag)
+ ("ruby object nil?" variant_flag)
+ ("ruby object nil?" variant_value)))
+ (|> (format (|> variant_tag (:coerce .Int) %.int)
+ " " (%.bit (not ("ruby object nil?" variant_flag)))
+ " " (inspect variant_value))
+ (text.enclose ["(" ")"]))
+ (inspect_tuple inspect value)))
+
+ (is? (class_of [[] []]) value_class)
+ (inspect_tuple inspect value)
+
+ ## else
+ (:coerce Text ("ruby object do" "to_s" value))))))
})))
(exception: #export (cannot_represent_value {type Type})
diff --git a/stdlib/source/lux/host.rb.lux b/stdlib/source/lux/host.rb.lux
new file mode 100644
index 000000000..63f14e8a3
--- /dev/null
+++ b/stdlib/source/lux/host.rb.lux
@@ -0,0 +1,334 @@
+(.module:
+ [lux (#- Alias)
+ ["." meta]
+ ["@" target]
+ [abstract
+ [monad (#+ do)]]
+ [control
+ ["." io]
+ ["<>" parser ("#\." monad)
+ ["<.>" code (#+ Parser)]]]
+ [data
+ ["." product]
+ ["." maybe]
+ ["." text
+ ["%" format (#+ format)]]
+ [collection
+ ["." list ("#\." functor fold)]]]
+ [type
+ abstract]
+ [macro (#+ with_gensyms)
+ [syntax (#+ syntax:)]
+ ["." code]
+ ["." template]]])
+
+(abstract: #export (Object brand) Any)
+
+(template [<name>]
+ [(with_expansions [<brand> (template.identifier [<name> "'"])]
+ (abstract: #export <brand> Any)
+ (type: #export <name>
+ (..Object <brand>)))]
+
+ [Nil]
+ [Function]
+ )
+
+(template [<name> <type>]
+ [(type: #export <name>
+ <type>)]
+
+ [Boolean Bit]
+ [Integer Int]
+ [Float Frac]
+ [String Text]
+ )
+
+(type: Nilable
+ [Bit Code])
+
+(def: nilable
+ (Parser Nilable)
+ (let [token (' #?)]
+ (<| (<>.and (<>.parses? (<code>.this! token)))
+ (<>.after (<>.not (<code>.this! token)))
+ <code>.any)))
+
+(type: Alias
+ Text)
+
+(def: alias
+ (Parser Alias)
+ (<>.after (<code>.this! (' #as)) <code>.local_identifier))
+
+(type: Field
+ [Bit Text (Maybe Alias) Nilable])
+
+(def: static!
+ (Parser Any)
+ (<code>.this! (' #static)))
+
+(def: field
+ (Parser Field)
+ (<code>.form ($_ <>.and
+ (<>.parses? ..static!)
+ <code>.local_identifier
+ (<>.maybe ..alias)
+ ..nilable)))
+
+(def: constant
+ (Parser Field)
+ (<code>.form ($_ <>.and
+ (<>\wrap true)
+ <code>.local_identifier
+ (<>.maybe ..alias)
+ ..nilable)))
+
+(type: Common_Method
+ {#name Text
+ #alias (Maybe Alias)
+ #inputs (List Nilable)
+ #io? Bit
+ #try? Bit
+ #output Nilable})
+
+(type: Static_Method Common_Method)
+(type: Virtual_Method Common_Method)
+
+(type: Method
+ (#Static Static_Method)
+ (#Virtual Virtual_Method))
+
+(def: common_method
+ (Parser Common_Method)
+ ($_ <>.and
+ <code>.local_identifier
+ (<>.maybe ..alias)
+ (<code>.tuple (<>.some ..nilable))
+ (<>.parses? (<code>.this! (' #io)))
+ (<>.parses? (<code>.this! (' #try)))
+ ..nilable))
+
+(def: static_method
+ (<>.after ..static! ..common_method))
+
+(def: method
+ (Parser Method)
+ (<code>.form (<>.or ..static_method
+ ..common_method)))
+
+(type: Member
+ (#Field Field)
+ (#Method Method))
+
+(def: member
+ (Parser Member)
+ ($_ <>.or
+ ..field
+ ..method
+ ))
+
+(def: input_variables
+ (-> (List Nilable) (List [Bit Code]))
+ (|>> list.enumeration
+ (list\map (function (_ [idx [nilable? type]])
+ [nilable? (|> idx %.nat code.local_identifier)]))))
+
+(def: (nilable_type [nilable? type])
+ (-> Nilable Code)
+ (if nilable?
+ (` (.Maybe (~ type)))
+ type))
+
+(def: (with_nil g!temp [nilable? input])
+ (-> Code [Bit Code] Code)
+ (if nilable?
+ (` (case (~ input)
+ (#.Some (~ g!temp))
+ (~ g!temp)
+
+ #.Nil
+ ("ruby object nil")))
+ input))
+
+(def: (without_nil g!temp [nilable? outputT] output)
+ (-> Code Nilable Code Code)
+ (if nilable?
+ (` (let [(~ g!temp) (~ output)]
+ (if ("ruby object nil?" (~ g!temp))
+ #.None
+ (#.Some (~ g!temp)))))
+ (` (let [(~ g!temp) (~ output)]
+ (if (not ("ruby object nil?" (~ g!temp)))
+ (~ g!temp)
+ (.error! "Nil is an invalid value!"))))))
+
+(type: Import
+ (#Class Text (Maybe Alias) (List Member))
+ (#Function Static_Method)
+ (#Constant Field))
+
+(def: import
+ (Parser [(Maybe Text) Import])
+ ($_ <>.and
+ (<>.maybe <code>.text)
+ ($_ <>.or
+ ($_ <>.and
+ <code>.local_identifier
+ (<>.maybe ..alias)
+ (<>.some member))
+ (<code>.form ..common_method)
+ ..constant
+ )))
+
+(syntax: #export (try expression)
+ {#.doc (doc (case (try (risky_computation input))
+ (#.Right success)
+ (do_something success)
+
+ (#.Left error)
+ (recover_from_failure error)))}
+ (wrap (list (` ("lux try" ((~! io.io) (~ expression)))))))
+
+(def: (with_io with? without)
+ (-> Bit Code Code)
+ (if with?
+ (` (io.io (~ without)))
+ without))
+
+(def: (io_type io? rawT)
+ (-> Bit Code Code)
+ (if io?
+ (` (io.IO (~ rawT)))
+ rawT))
+
+(def: (with_try with? without_try)
+ (-> Bit Code Code)
+ (if with?
+ (` (..try (~ without_try)))
+ without_try))
+
+(def: (try_type try? rawT)
+ (-> Bit Code Code)
+ (if try?
+ (` (.Either .Text (~ rawT)))
+ rawT))
+
+(def: (make_function g!method g!temp source inputsT io? try? outputT)
+ (-> Code Code Code (List Nilable) Bit Bit Nilable Code)
+ (let [g!inputs (input_variables inputsT)]
+ (` (def: ((~ g!method)
+ [(~+ (list\map product.right g!inputs))])
+ (-> [(~+ (list\map nilable_type inputsT))]
+ (~ (|> (nilable_type outputT)
+ (try_type try?)
+ (io_type io?))))
+ (:assume
+ (~ (<| (with_io io?)
+ (with_try try?)
+ (without_nil g!temp outputT)
+ (` ("ruby apply"
+ (:coerce ..Function (~ source))
+ (~+ (list\map (with_nil g!temp) g!inputs)))))))))))
+
+(syntax: #export (import: {[?module import] ..import})
+ (with_gensyms [g!temp]
+ (case import
+ (#Class [class alias members])
+ (with_gensyms [g!object]
+ (let [qualify (: (-> Text Code)
+ (|>> (format (maybe.default class alias) "::") code.local_identifier))
+ g!type (code.local_identifier (maybe.default class alias))
+ module_import (: (List Code)
+ (case ?module
+ (#.Some module)
+ (list (` ("ruby import" (~ (code.text module)))))
+
+ #.None
+ (list)))
+ class_import (` ("ruby constant" (~ (code.text class))))]
+ (wrap (list& (` (type: (~ g!type)
+ (..Object (primitive (~ (code.text class))))))
+ (list\map (function (_ member)
+ (case member
+ (#Field [static? field alias fieldT])
+ (if static?
+ (` ((~! syntax:) ((~ (qualify (maybe.default field alias))))
+ (\ (~! meta.monad) (~' wrap)
+ (list (` (.:coerce (~ (nilable_type fieldT))
+ (.exec
+ (~+ module_import)
+ ("ruby constant" (~ (code.text (format class "::" field)))))))))))
+ (` (def: ((~ (qualify field))
+ (~ g!object))
+ (-> (~ g!type)
+ (~ (nilable_type fieldT)))
+ (:assume
+ (~ (without_nil g!temp fieldT (` ("ruby object get" (~ (code.text field))
+ (:coerce (..Object .Any) (~ g!object))))))))))
+
+ (#Method method)
+ (case method
+ (#Static [method alias inputsT io? try? outputT])
+ (..make_function (qualify (maybe.default method alias))
+ g!temp
+ (` ("ruby object get" (~ (code.text method))
+ (:coerce (..Object .Any)
+ (.exec
+ (~+ module_import)
+ ("ruby constant" (~ (code.text (format class "::" method))))))))
+ inputsT
+ io?
+ try?
+ outputT)
+
+ (#Virtual [method alias inputsT io? try? outputT])
+ (let [g!inputs (input_variables inputsT)]
+ (` (def: ((~ (qualify (maybe.default method alias)))
+ [(~+ (list\map product.right g!inputs))]
+ (~ g!object))
+ (-> [(~+ (list\map nilable_type inputsT))]
+ (~ g!type)
+ (~ (|> (nilable_type outputT)
+ (try_type try?)
+ (io_type io?))))
+ (:assume
+ (~ (<| (with_io io?)
+ (with_try try?)
+ (without_nil g!temp outputT)
+ (` ("ruby object do"
+ (~ (code.text method))
+ (~ g!object)
+ (~+ (list\map (with_nil g!temp) g!inputs)))))))))))))
+ members)))))
+
+ (#Function [name alias inputsT io? try? outputT])
+ (let [imported (` (.exec
+ (~+ (case ?module
+ (#.Some module)
+ (list (` ("ruby import" (~ (code.text module)))))
+
+ #.None
+ (list)))
+ ("ruby constant" (~ (code.text name)))))]
+ (wrap (list (..make_function (code.local_identifier (maybe.default name alias))
+ g!temp
+ imported
+ inputsT
+ io?
+ try?
+ outputT))))
+
+ (#Constant [_ name alias fieldT])
+ (let [imported (` (.exec
+ (~+ (case ?module
+ (#.Some module)
+ (list (` ("ruby import" (~ (code.text module)))))
+
+ #.None
+ (list)))
+ ("ruby constant" (~ (code.text name)))))]
+ (wrap (list (` ((~! syntax:) ((~ (code.local_identifier (maybe.default name alias))))
+ (\ (~! meta.monad) (~' wrap)
+ (list (` (.:coerce (~ (nilable_type fieldT)) (~ imported))))))))))
+ )))
diff --git a/stdlib/source/lux/math.lux b/stdlib/source/lux/math.lux
index 1c4247ad2..7193b417f 100644
--- a/stdlib/source/lux/math.lux
+++ b/stdlib/source/lux/math.lux
@@ -175,7 +175,45 @@
(def: #export root/3
(-> Frac Frac)
- (..pow ("lux f64 /" +3.0 +1.0))))})
+ (..pow ("lux f64 /" +3.0 +1.0))))
+
+ @.ruby
+ (as_is (template [<name> <method>]
+ [(def: #export <name>
+ (-> Frac Frac)
+ (|>> ("ruby apply" ("ruby constant" <method>))
+ (:coerce Frac)))]
+
+ [cos "Math.cos"]
+ [sin "Math.sin"]
+ [tan "Math.tan"]
+
+ [acos "Math.acos"]
+ [asin "Math.asin"]
+ [atan "Math.atan"]
+
+ [exp "Math.exp"]
+ [log "Math.log"]
+
+ [root/2 "Math.sqrt"]
+ [root/3 "Math.cbrt"]
+ )
+
+ (template [<name> <method>]
+ [(def: #export <name>
+ (-> Frac Frac)
+ (|>> ("ruby object do" <method>)
+ (:coerce Int)
+ ("lux i64 f64")))]
+
+ [ceil "ceil"]
+ [floor "floor"]
+ )
+
+ (def: #export (pow param subject)
+ (-> Frac Frac Frac)
+ (:coerce Frac ("ruby object do" "**" subject param))))
+ })
(def: #export (round input)
(-> Frac Frac)
diff --git a/stdlib/source/lux/target/ruby.lux b/stdlib/source/lux/target/ruby.lux
index e884d6c70..641cc8d2e 100644
--- a/stdlib/source/lux/target/ruby.lux
+++ b/stdlib/source/lux/target/ruby.lux
@@ -124,7 +124,8 @@
)
(template [<ruby_name> <lux_name>]
- [(def: #export <lux_name> (..global <ruby_name>))]
+ [(def: #export <lux_name>
+ (..global <ruby_name>))]
["@" latest_error]
["_" last_string_read]
@@ -135,11 +136,17 @@
["/" input_record_separator]
["\" output_record_separator]
["0" script_name]
- ["*" command_line_arguments]
["$" process_id]
["?" exit_status]
)
+ (template [<ruby_name> <lux_name>]
+ [(def: #export <lux_name>
+ (..local <ruby_name>))]
+
+ ["ARGV" command_line_arguments]
+ )
+
(def: #export nil
Literal
(:abstraction "nil"))
@@ -172,8 +179,9 @@
(-> <type> Literal)
(|>> <prep> <format> :abstraction))]
- [%.int int Int (<|)]
+ [%.int int Int (<|)]
[%.text string Text ..sanitize]
+ [(<|) symbol Text (format ":")]
)
(def: #export float
@@ -323,6 +331,13 @@
(..nest (:representation rescue)))))
(text.join_with text.new_line)))))
+ (def: #export (catch expectation body!)
+ (-> Expression Statement Statement)
+ (<| :abstraction
+ ..block
+ (format "catch(" (:representation expectation) ") do"
+ (..nest (:representation body!)))))
+
(def: #export (return value)
(-> Expression Statement)
(:abstraction (format "return " (:representation value) ..statement_suffix)))
@@ -360,8 +375,7 @@
(list\map (|>> :representation))
(text.join_with ..input_separator)
(text.enclose' "|"))
- " "
- (:representation body!))
+ (..nest (:representation body!)))
(text.enclose ["{" "}"])
(format "lambda "))]
(|> (case name
@@ -401,9 +415,14 @@
[">>" bit_shr]
)
- (def: #export (not subject)
- (-> Expression Computation)
- (:abstraction (format "(!" (:representation subject) ")")))
+ (template [<unary> <name>]
+ [(def: #export (<name> subject)
+ (-> Expression Computation)
+ (:abstraction (format "(" <unary> (:representation subject) ")")))]
+
+ ["!" not]
+ ["-" negate]
+ )
(def: #export (comment commentary on)
(All [brand] (-> Text (Code brand) (Code brand)))
@@ -448,11 +467,17 @@
<definitions>))]
[1
- [["print"]]]
+ [["print"]
+ ["require"]]]
[2
- []]
+ [["print"]]]
[3
- []]
+ [["print"]]]
)
+
+(def: #export throw/1
+ (-> Expression Statement)
+ (|>> (..apply/1 (..local "throw"))
+ ..statement))
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/extension/analysis/lua.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/extension/analysis/lua.lux
index 04df1bdbb..99154e105 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/extension/analysis/lua.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/extension/analysis/lua.lux
@@ -28,8 +28,7 @@
["." phase]]]]]])
(def: Nil
- (for {@.lua
- host.Nil}
+ (for {@.lua host.Nil}
Any))
(def: Object
@@ -222,7 +221,7 @@
[_ (analysis/type.infer ..Object)]
(wrap (#analysis.Extension extension (list (analysis.text name))))))]))
-(def: python::function
+(def: lua::function
Handler
(custom
[($_ <>.and <c>.nat <c>.any)
@@ -247,6 +246,6 @@
(bundle.install "apply" lua::apply)
(bundle.install "power" lua::power)
(bundle.install "import" lua::import)
- (bundle.install "function" python::function)
+ (bundle.install "function" lua::function)
(bundle.install "script universe" (/.nullary .Bit))
)))
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/extension/analysis/ruby.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/extension/analysis/ruby.lux
index 3b9f4ad75..8bbd32b3c 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/extension/analysis/ruby.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/extension/analysis/ruby.lux
@@ -27,8 +27,172 @@
[///
["." phase]]]]]])
+(def: array::new
+ Handler
+ (custom
+ [<c>.any
+ (function (_ extension phase archive lengthC)
+ (do phase.monad
+ [lengthA (analysis/type.with_type Nat
+ (phase archive lengthC))
+ [var_id varT] (analysis/type.with_env check.var)
+ _ (analysis/type.infer (type (Array varT)))]
+ (wrap (#analysis.Extension extension (list lengthA)))))]))
+
+(def: array::length
+ Handler
+ (custom
+ [<c>.any
+ (function (_ extension phase archive arrayC)
+ (do phase.monad
+ [[var_id varT] (analysis/type.with_env check.var)
+ arrayA (analysis/type.with_type (type (Array varT))
+ (phase archive arrayC))
+ _ (analysis/type.infer Nat)]
+ (wrap (#analysis.Extension extension (list arrayA)))))]))
+
+(def: array::read
+ Handler
+ (custom
+ [(<>.and <c>.any <c>.any)
+ (function (_ extension phase archive [indexC arrayC])
+ (do phase.monad
+ [indexA (analysis/type.with_type Nat
+ (phase archive indexC))
+ [var_id varT] (analysis/type.with_env check.var)
+ arrayA (analysis/type.with_type (type (Array varT))
+ (phase archive arrayC))
+ _ (analysis/type.infer varT)]
+ (wrap (#analysis.Extension extension (list indexA arrayA)))))]))
+
+(def: array::write
+ Handler
+ (custom
+ [($_ <>.and <c>.any <c>.any <c>.any)
+ (function (_ extension phase archive [indexC valueC arrayC])
+ (do phase.monad
+ [indexA (analysis/type.with_type Nat
+ (phase archive indexC))
+ [var_id varT] (analysis/type.with_env check.var)
+ valueA (analysis/type.with_type varT
+ (phase archive valueC))
+ arrayA (analysis/type.with_type (type (Array varT))
+ (phase archive arrayC))
+ _ (analysis/type.infer (type (Array varT)))]
+ (wrap (#analysis.Extension extension (list indexA valueA arrayA)))))]))
+
+(def: array::delete
+ Handler
+ (custom
+ [($_ <>.and <c>.any <c>.any)
+ (function (_ extension phase archive [indexC arrayC])
+ (do phase.monad
+ [indexA (analysis/type.with_type Nat
+ (phase archive indexC))
+ [var_id varT] (analysis/type.with_env check.var)
+ arrayA (analysis/type.with_type (type (Array varT))
+ (phase archive arrayC))
+ _ (analysis/type.infer (type (Array varT)))]
+ (wrap (#analysis.Extension extension (list indexA arrayA)))))]))
+
+(def: bundle::array
+ Bundle
+ (<| (bundle.prefix "array")
+ (|> bundle.empty
+ (bundle.install "new" array::new)
+ (bundle.install "length" array::length)
+ (bundle.install "read" array::read)
+ (bundle.install "write" array::write)
+ (bundle.install "delete" array::delete)
+ )))
+
+(def: Nil
+ (for {@.ruby host.Nil}
+ Any))
+
+(def: Object
+ (for {@.ruby (type (host.Object Any))}
+ Any))
+
+(def: Function
+ (for {@.ruby host.Function}
+ Any))
+
+(def: object::get
+ Handler
+ (custom
+ [($_ <>.and <c>.text <c>.any)
+ (function (_ extension phase archive [fieldC objectC])
+ (do phase.monad
+ [objectA (analysis/type.with_type ..Object
+ (phase archive objectC))
+ _ (analysis/type.infer .Any)]
+ (wrap (#analysis.Extension extension (list (analysis.text fieldC)
+ objectA)))))]))
+
+(def: object::do
+ Handler
+ (custom
+ [($_ <>.and <c>.text <c>.any (<>.some <c>.any))
+ (function (_ extension phase archive [methodC objectC inputsC])
+ (do {! phase.monad}
+ [objectA (analysis/type.with_type ..Object
+ (phase archive objectC))
+ inputsA (monad.map ! (|>> (phase archive) (analysis/type.with_type Any)) inputsC)
+ _ (analysis/type.infer .Any)]
+ (wrap (#analysis.Extension extension (list& (analysis.text methodC)
+ objectA
+ inputsA)))))]))
+
+(def: bundle::object
+ Bundle
+ (<| (bundle.prefix "object")
+ (|> bundle.empty
+ (bundle.install "get" object::get)
+ (bundle.install "do" object::do)
+ (bundle.install "nil" (/.nullary ..Nil))
+ (bundle.install "nil?" (/.unary Any Bit))
+ )))
+
+(def: ruby::constant
+ Handler
+ (custom
+ [<c>.text
+ (function (_ extension phase archive name)
+ (do phase.monad
+ [_ (analysis/type.infer Any)]
+ (wrap (#analysis.Extension extension (list (analysis.text name))))))]))
+
+(def: ruby::apply
+ Handler
+ (custom
+ [($_ <>.and <c>.any (<>.some <c>.any))
+ (function (_ extension phase archive [abstractionC inputsC])
+ (do {! phase.monad}
+ [abstractionA (analysis/type.with_type ..Function
+ (phase archive abstractionC))
+ inputsA (monad.map ! (|>> (phase archive) (analysis/type.with_type Any)) inputsC)
+ _ (analysis/type.infer Any)]
+ (wrap (#analysis.Extension extension (list& abstractionA inputsA)))))]))
+
+(def: ruby::import
+ Handler
+ (custom
+ [<c>.text
+ (function (_ extension phase archive name)
+ (do phase.monad
+ [_ (analysis/type.infer Bit)]
+ (wrap (#analysis.Extension extension (list (analysis.text name))))))]))
+
(def: #export bundle
Bundle
(<| (bundle.prefix "ruby")
(|> bundle.empty
+ (dictionary.merge bundle::array)
+ (dictionary.merge bundle::object)
+
+ (bundle.install "constant" ruby::constant)
+ (bundle.install "apply" ruby::apply)
+ (bundle.install "import" ruby::import)
+ (bundle.install "script universe" (/.nullary .Bit))
)))
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/ruby.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/ruby.lux
index 8b1b94bbb..12bcfc9b1 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/ruby.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/ruby.lux
@@ -5,6 +5,7 @@
["." dictionary]]]]
["." / #_
["#." common]
+ ["#." host]
[////
[generation
[ruby
@@ -12,4 +13,5 @@
(def: #export bundle
Bundle
- /common.bundle)
+ (dictionary.merge /common.bundle
+ /host.bundle))
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/ruby/common.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/ruby/common.lux
index 9f04b35d2..50eddb998 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/ruby/common.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/ruby/common.lux
@@ -47,34 +47,71 @@
(#try.Failure error)
(/////.throw extension.invalid_syntax [extension_name %synthesis input]))))
+## TODO: Get rid of this ASAP
+(def: lux::syntax_char_case!
+ (..custom [($_ <>.and
+ <s>.any
+ <s>.any
+ (<>.some (<s>.tuple ($_ <>.and
+ (<s>.tuple (<>.many <s>.i64))
+ <s>.any))))
+ (function (_ extension_name phase archive [input else conditionals])
+ (do {! /////.monad}
+ [inputG (phase archive input)
+ elseG (phase archive else)
+ @input (\ ! map _.local (generation.gensym "input"))
+ conditionalsG (: (Operation (List [Expression Expression]))
+ (monad.map ! (function (_ [chars branch])
+ (do !
+ [branchG (phase archive branch)]
+ (wrap [(|> chars
+ (list\map (|>> .int _.int (_.= @input)))
+ (list\fold (function (_ clause total)
+ (if (is? _.nil total)
+ clause
+ (_.or clause total)))
+ _.nil))
+ branchG])))
+ conditionals))
+ #let [closure (_.lambda #.None (list @input)
+ (list\fold (function (_ [test then] else)
+ (_.if test (_.return then) else))
+ (_.return elseG)
+ conditionalsG))]]
+ (wrap (_.apply_lambda/* (list inputG) closure))))]))
+
(def: lux_procs
Bundle
(|> /.empty
- (/.install "is" (binary (product.uncurry _.=)))
+ (/.install "syntax char case!" lux::syntax_char_case!)
+ (/.install "is" (binary (function (_ [reference subject])
+ (_.do "equal?" (list reference) subject))))
(/.install "try" (unary //runtime.lux//try))))
-(def: keep_i64
- (All [input]
- (-> (-> input Expression)
- (-> input Expression)))
- (function.compose (_.bit_and (_.manual "0xFFFFFFFFFFFFFFFF"))))
+(def: (capped operation parameter subject)
+ (-> (-> Expression Expression Expression)
+ (-> Expression Expression Expression))
+ (//runtime.i64//64 (operation parameter subject)))
(def: i64_procs
Bundle
(<| (/.prefix "i64")
(|> /.empty
- (/.install "and" (binary (product.uncurry _.bit_and)))
- (/.install "or" (binary (product.uncurry _.bit_or)))
- (/.install "xor" (binary (product.uncurry _.bit_xor)))
- (/.install "left-shift" (binary (..keep_i64 (product.uncurry _.bit_shl))))
- (/.install "right-shift" (binary (product.uncurry //runtime.i64//logic_right_shift)))
- (/.install "=" (binary (product.uncurry _.=)))
- (/.install "+" (binary (..keep_i64 (product.uncurry _.+))))
- (/.install "-" (binary (..keep_i64 (product.uncurry _.-))))
+ (/.install "and" (binary (product.uncurry //runtime.i64//and)))
+ (/.install "or" (binary (product.uncurry //runtime.i64//or)))
+ (/.install "xor" (binary (product.uncurry //runtime.i64//xor)))
+ (/.install "left-shift" (binary (product.uncurry //runtime.i64//left_shift)))
+ (/.install "right-shift" (binary (product.uncurry //runtime.i64//right_shift)))
+
(/.install "<" (binary (product.uncurry _.<)))
- (/.install "*" (binary (..keep_i64 (product.uncurry _.*))))
- (/.install "/" (binary (product.uncurry _./)))
- (/.install "%" (binary (product.uncurry _.%)))
+ (/.install "=" (binary (product.uncurry _.=)))
+ (/.install "+" (binary (product.uncurry (..capped _.+))))
+ (/.install "-" (binary (product.uncurry (..capped _.-))))
+ (/.install "*" (binary (product.uncurry (..capped _.*))))
+ (/.install "/" (binary (product.uncurry //runtime.i64//division)))
+ (/.install "%" (binary (function (_ [parameter subject])
+ (_.do "remainder" (list parameter) subject))))
+
(/.install "f64" (unary (_./ (_.float +1.0))))
(/.install "char" (unary (_.do "chr" (list (_.string "UTF-8")))))
)))
@@ -87,10 +124,11 @@
(/.install "-" (binary (product.uncurry _.-)))
(/.install "*" (binary (product.uncurry _.*)))
(/.install "/" (binary (product.uncurry _./)))
- (/.install "%" (binary (product.uncurry _.%)))
+ (/.install "%" (binary (function (_ [parameter subject])
+ (_.do "remainder" (list parameter) subject))))
(/.install "=" (binary (product.uncurry _.=)))
(/.install "<" (binary (product.uncurry _.<)))
- (/.install "int" (unary (_.do "floor" (list))))
+ (/.install "i64" (unary (_.do "floor" (list))))
(/.install "encode" (unary (_.do "to_s" (list))))
(/.install "decode" (unary //runtime.f64//decode)))))
@@ -100,7 +138,7 @@
(def: (text//clip [paramO extraO subjectO])
(Trinary Expression)
- (//runtime.text//clip subjectO paramO extraO))
+ (//runtime.text//clip paramO extraO subjectO))
(def: (text//index [startO partO textO])
(Trinary Expression)
@@ -112,7 +150,7 @@
(|> /.empty
(/.install "=" (binary (product.uncurry _.=)))
(/.install "<" (binary (product.uncurry _.<)))
- (/.install "concat" (binary (product.uncurry _.+)))
+ (/.install "concat" (binary (product.uncurry (function.flip _.+))))
(/.install "index" (trinary text//index))
(/.install "size" (unary (_.the "length")))
(/.install "char" (binary (product.uncurry //runtime.text//char)))
@@ -121,9 +159,8 @@
(def: (io//log! messageG)
(Unary Expression)
- (_.or (_.apply/* (list (|> messageG (_.+ (_.string text.new_line))))
- (_.local "puts"))
- //runtime.unit))
+ (_.or //runtime.unit
+ (_.print/2 messageG (_.string text.new_line))))
(def: io//error!
(Unary Expression)
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/ruby/host.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/ruby/host.lux
new file mode 100644
index 000000000..206034cd7
--- /dev/null
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/ruby/host.lux
@@ -0,0 +1,135 @@
+(.module:
+ [lux #*
+ [abstract
+ ["." monad (#+ do)]]
+ [control
+ ["." function]
+ ["<>" parser
+ ["<s>" synthesis (#+ Parser)]]]
+ [data
+ [collection
+ ["." dictionary]
+ ["." list]]
+ [text
+ ["%" format (#+ format)]]]
+ [target
+ ["_" ruby (#+ Var Expression)]]]
+ ["." // #_
+ ["#." common (#+ custom)]
+ ["//#" /// #_
+ ["/" bundle]
+ ["/#" // #_
+ ["." extension]
+ [generation
+ [extension (#+ Nullary Unary Binary Trinary
+ nullary unary binary trinary)]
+ ["." reference]
+ ["//" ruby #_
+ ["#." runtime (#+ Operation Phase Handler Bundle
+ with_vars)]]]
+ ["/#" // #_
+ ["." generation]
+ ["//#" /// #_
+ ["#." phase]]]]]])
+
+(def: (array::new [size])
+ (Unary Expression)
+ (_.do "new" (list size) (_.local "Array")))
+
+(def: array::length
+ (Unary Expression)
+ (_.the "size"))
+
+(def: (array::read [indexG arrayG])
+ (Binary Expression)
+ (_.nth indexG arrayG))
+
+(def: (array::write [indexG valueG arrayG])
+ (Trinary Expression)
+ (//runtime.array//write indexG valueG arrayG))
+
+(def: (array::delete [indexG arrayG])
+ (Binary Expression)
+ (//runtime.array//write indexG _.nil arrayG))
+
+(def: array
+ Bundle
+ (<| (/.prefix "array")
+ (|> /.empty
+ (/.install "new" (unary array::new))
+ (/.install "length" (unary array::length))
+ (/.install "read" (binary array::read))
+ (/.install "write" (trinary array::write))
+ (/.install "delete" (binary array::delete))
+ )))
+
+(def: object::get
+ Handler
+ (custom
+ [($_ <>.and <s>.text <s>.any)
+ (function (_ extension phase archive [fieldS objectS])
+ (do ////////phase.monad
+ [objectG (phase archive objectS)]
+ (wrap (_.the fieldS objectG))))]))
+
+(def: object::do
+ Handler
+ (custom
+ [($_ <>.and <s>.text <s>.any (<>.some <s>.any))
+ (function (_ extension phase archive [methodS objectS inputsS])
+ (do {! ////////phase.monad}
+ [objectG (phase archive objectS)
+ inputsG (monad.map ! (phase archive) inputsS)]
+ (wrap (_.do methodS inputsG objectG))))]))
+
+(template [<!> <?> <unit>]
+ [(def: <!> (Nullary Expression) (function.constant <unit>))
+ (def: <?> (Unary Expression) (_.= <unit>))]
+
+ [object::nil object::nil? _.nil]
+ )
+
+(def: object
+ Bundle
+ (<| (/.prefix "object")
+ (|> /.empty
+ (/.install "get" object::get)
+ (/.install "do" object::do)
+ (/.install "nil" (nullary object::nil))
+ (/.install "nil?" (unary object::nil?))
+ )))
+
+(def: ruby::constant
+ (custom
+ [<s>.text
+ (function (_ extension phase archive name)
+ (\ ////////phase.monad wrap (_.local name)))]))
+
+(def: ruby::apply
+ (custom
+ [($_ <>.and <s>.any (<>.some <s>.any))
+ (function (_ extension phase archive [abstractionS inputsS])
+ (do {! ////////phase.monad}
+ [abstractionG (phase archive abstractionS)
+ inputsG (monad.map ! (phase archive) inputsS)]
+ (wrap (_.apply/* inputsG abstractionG))))]))
+
+(def: ruby::import
+ (custom
+ [<s>.text
+ (function (_ extension phase archive module)
+ (\ ////////phase.monad wrap
+ (_.require/1 (_.string module))))]))
+
+(def: #export bundle
+ Bundle
+ (<| (/.prefix "ruby")
+ (|> /.empty
+ (dictionary.merge ..array)
+ (dictionary.merge ..object)
+
+ (/.install "constant" ruby::constant)
+ (/.install "apply" ruby::apply)
+ (/.install "import" ruby::import)
+ (/.install "script universe" (nullary (function.constant (_.bool reference.universe))))
+ )))
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python.lux
index cdaabfc08..2e86ad107 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python.lux
@@ -26,8 +26,6 @@
[reference (#+)
[variable (#+)]]]]]]])
-(exception: #export cannot-recur-as-an-expression)
-
(def: (statement expression archive synthesis)
Phase!
(case synthesis
@@ -60,6 +58,8 @@
(//////phase\map _.return (/function.function statement expression archive abstraction))
))
+(exception: #export cannot-recur-as-an-expression)
+
(def: #export (expression archive synthesis)
Phase
(case synthesis
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/case.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/case.lux
index eb6ae3e19..202e922c1 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/case.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/case.lux
@@ -151,27 +151,29 @@
[right_choice (_.string "") inc]
)
-(def: (alternation in_closure? g!once pre! post!)
- (-> Bit SVar (Statement Any) (Statement Any) (Statement Any))
+(def: (with_looping in_closure? g!once body!)
+ (-> Bit SVar (Statement Any) (Statement Any))
(.if in_closure?
- ($_ _.then
- (_.while (_.bool true)
- ($_ _.then
- ..save!
- pre!)
- #.None)
- ..restore!
- post!)
+ (_.while (_.bool true)
+ body!
+ #.None)
($_ _.then
(_.set (list g!once) (_.bool true))
(_.while g!once
($_ _.then
(_.set (list g!once) (_.bool false))
- ..save!
- pre!)
- (#.Some _.continue))
- ..restore!
- post!)))
+ body!)
+ (#.Some _.continue)))))
+
+(def: (alternation in_closure? g!once pre! post!)
+ (-> Bit SVar (Statement Any) (Statement Any) (Statement Any))
+ ($_ _.then
+ (..with_looping in_closure? g!once
+ ($_ _.then
+ ..save!
+ pre!))
+ ..restore!
+ post!))
(def: (pattern_matching' in_closure? statement expression archive)
(-> Bit Phase! Phase Archive Path (Operation (Statement Any)))
@@ -271,20 +273,10 @@
(do ///////phase.monad
[pattern_matching! (pattern_matching' in_closure? statement expression archive pathP)
g!once (..gensym "once")]
- (wrap (.if in_closure?
- ($_ _.then
- (_.while (_.bool true)
- pattern_matching!
- #.None)
- (_.raise (_.Exception/1 (_.string case.pattern_matching_error))))
- ($_ _.then
- (_.set (list g!once) (_.bool true))
- (_.while g!once
- ($_ _.then
- (_.set (list g!once) (_.bool false))
- pattern_matching!)
- (#.Some _.continue))
- (_.raise (_.Exception/1 (_.string case.pattern_matching_error))))))))
+ (wrap ($_ _.then
+ (..with_looping in_closure? g!once
+ pattern_matching!)
+ (_.raise (_.Exception/1 (_.string case.pattern_matching_error)))))))
(def: #export dependencies
(-> Path (List SVar))
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/runtime.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/runtime.lux
index 933bcf6b0..1638a64ca 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/runtime.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/runtime.lux
@@ -247,8 +247,8 @@
test_recursion! (_.if is_last?
## Must recurse.
($_ _.then
- (_.set (list sum) sum_value)
- (_.set (list wantedTag) (_.- sum_tag wantedTag)))
+ (_.set (list wantedTag) (_.- sum_tag wantedTag))
+ (_.set (list sum) sum_value))
no_match!)]
(<| (_.while (_.bool true))
(_.cond (list [(_.= wantedTag sum_tag)
@@ -272,31 +272,12 @@
@sum//get
))
-(runtime: i64//+limit
- (|> (_.int +1)
- (_.bit_shl (_.int +63))
- (_.- (_.int +1))))
-
-(runtime: i64//-limit
- (_.- (|> (_.int +1)
- (_.bit_shl (_.int +63)))
- (_.int +0)))
-
-(runtime: i64//+iteration
- (|> (_.int +1)
- (_.bit_shl (_.int +64))))
-
-(runtime: i64//-iteration
- (|> ..i64//+iteration
- _.negate))
-
-(runtime: i64//+cap
- (|> ..i64//+limit
- (_.+ (_.int +1))))
-
-(runtime: i64//-cap
- (|> ..i64//-limit
- (_.- (_.int +1))))
+(def: i64//+limit (_.manual "+0x7FFFFFFFFFFFFFFF"))
+(def: i64//-limit (_.manual "-0x8000000000000000"))
+(def: i64//+iteration (_.manual "+0x10000000000000000"))
+(def: i64//-iteration (_.manual "-0x10000000000000000"))
+(def: i64//+cap (_.manual "+0x8000000000000000"))
+(def: i64//-cap (_.manual "-0x8000000000000001"))
(runtime: (i64//64 input)
(with_vars [temp]
@@ -355,9 +336,9 @@
(_.return (_.- (|> subject (..i64//division param) (_.* param))
subject)))
-(template [<runtime> <python>]
+(template [<runtime> <host>]
[(runtime: (<runtime> left right)
- (_.return (..i64//64 (<python> (..as_nat left) (..as_nat right)))))]
+ (_.return (..i64//64 (<host> (..as_nat left) (..as_nat right)))))]
[i64//and _.bit_and]
[i64//or _.bit_or]
@@ -378,12 +359,6 @@
(def: runtime//i64
(Statement Any)
($_ _.then
- @i64//+limit
- @i64//-limit
- @i64//+iteration
- @i64//-iteration
- @i64//+cap
- @i64//-cap
@i64//64
@i64//nat_top
@i64//left_shift
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby.lux
index 9524441f2..f1a4e3c1c 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby.lux
@@ -26,7 +26,41 @@
[reference (#+)
[variable (#+)]]]]]]])
-(def: #export (generate archive synthesis)
+(def: (statement expression archive synthesis)
+ Phase!
+ (case synthesis
+ (^template [<tag>]
+ [(^ (<tag> value))
+ (//////phase\map _.return (expression archive synthesis))])
+ ([////synthesis.bit]
+ [////synthesis.i64]
+ [////synthesis.f64]
+ [////synthesis.text]
+ [////synthesis.variant]
+ [////synthesis.tuple]
+ [#////synthesis.Reference]
+ [////synthesis.branch/get]
+ [////synthesis.function/apply]
+ [#////synthesis.Extension])
+
+ (^ (////synthesis.branch/case case))
+ (/case.case! false statement expression archive case)
+
+ (^template [<tag> <generator>]
+ [(^ (<tag> value))
+ (<generator> statement expression archive value)])
+ ([////synthesis.branch/let /case.let!]
+ [////synthesis.branch/if /case.if!]
+ [////synthesis.loop/scope /loop.scope!]
+ [////synthesis.loop/recur /loop.recur!])
+
+ (^ (////synthesis.function/abstraction abstraction))
+ (//////phase\map _.return (/function.function statement expression archive abstraction))
+ ))
+
+(exception: #export cannot-recur-as-an-expression)
+
+(def: (expression archive synthesis)
Phase
(case synthesis
(^template [<tag> <generator>]
@@ -39,23 +73,32 @@
(^template [<tag> <generator>]
[(^ (<tag> value))
- (<generator> generate archive value)])
+ (<generator> expression archive value)])
([////synthesis.variant /structure.variant]
[////synthesis.tuple /structure.tuple]
- [////synthesis.branch/case /case.case]
[////synthesis.branch/let /case.let]
[////synthesis.branch/if /case.if]
[////synthesis.branch/get /case.get]
- [////synthesis.loop/scope /loop.scope]
- [////synthesis.loop/recur /loop.recur]
-
- [////synthesis.function/abstraction /function.function]
[////synthesis.function/apply /function.apply])
+ (^template [<tag> <generator>]
+ [(^ (<tag> value))
+ (<generator> statement expression archive value)])
+ ([////synthesis.branch/case /case.case]
+ [////synthesis.loop/scope /loop.scope]
+ [////synthesis.function/abstraction /function.function])
+
+ (^ (////synthesis.loop/recur _))
+ (//////phase.throw ..cannot-recur-as-an-expression [])
+
(#////synthesis.Reference value)
(//reference.reference /reference.system archive value)
(#////synthesis.Extension extension)
- (///extension.apply archive generate extension)))
+ (///extension.apply archive expression extension)))
+
+(def: #export generate
+ Phase
+ ..expression)
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/case.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/case.lux
index 428ac6279..e21957afe 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/case.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/case.lux
@@ -35,6 +35,10 @@
[meta
[archive (#+ Archive)]]]]]]])
+(def: #export (gensym prefix)
+ (-> Text (Operation LVar))
+ (///////phase\map (|>> %.nat (format prefix) _.local) /////generation.next))
+
(def: #export register
(-> Register LVar)
(|>> (///reference.local //reference.system) :assume))
@@ -54,6 +58,15 @@
(_.lambda #.None (list (..register register)))
(_.apply_lambda/* (list valueO))))))
+(def: #export (let! statement expression archive [valueS register bodyS])
+ (Generator! [Synthesis Register Synthesis])
+ (do ///////phase.monad
+ [valueO (expression archive valueS)
+ bodyO (statement expression archive bodyS)]
+ (wrap ($_ _.then
+ (_.set (list (..register register)) valueO)
+ bodyO))))
+
(def: #export (if expression archive [testS thenS elseS])
(Generator [Synthesis Synthesis Synthesis])
(do ///////phase.monad
@@ -62,6 +75,16 @@
elseO (expression archive elseS)]
(wrap (_.? testO thenO elseO))))
+(def: #export (if! statement expression archive [testS thenS elseS])
+ (Generator! [Synthesis Synthesis Synthesis])
+ (do ///////phase.monad
+ [test! (expression archive testS)
+ then! (statement expression archive thenS)
+ else! (statement expression archive elseS)]
+ (wrap (_.if test!
+ then!
+ else!))))
+
(def: #export (get expression archive [pathP valueS])
(Generator [(List Member) Synthesis])
(do ///////phase.monad
@@ -106,7 +129,13 @@
Statement
(_.set (list @cursor) (|> @savepoint (_.do "pop" (list)))))
-(def: fail! _.break)
+(def: #export symbol
+ (_.symbol "lux_break"))
+
+(def: fail!
+ _.break
+ ## (_.throw/1 ..symbol)
+ )
(def: (multi_pop! pops)
(-> Nat Statement)
@@ -130,23 +159,44 @@
[right_choice (_.string "") inc]
)
-(def: (alternation pre! post!)
- (-> Statement Statement Statement)
+(def: (with_looping in_closure? g!once g!continue? body!)
+ (-> Bit LVar LVar Statement Statement)
+ ## (_.catch ..symbol body!)
+ (.if in_closure?
+ ($_ _.then
+ (_.while (_.bool true)
+ body!))
+ ($_ _.then
+ (_.set (list g!once) (_.bool true))
+ (_.set (list g!continue?) (_.bool false))
+ (<| (_.while (_.bool true))
+ (_.if g!once
+ ($_ _.then
+ (_.set (list g!once) (_.bool false))
+ body!)
+ ($_ _.then
+ (_.set (list g!continue?) (_.bool true))
+ _.break)))
+ (_.when g!continue?
+ _.next)))
+ )
+
+(def: (alternation in_closure? g!once g!continue? pre! post!)
+ (-> Bit LVar LVar Statement Statement Statement)
($_ _.then
- (_.while (_.bool true)
- ($_ _.then
- ..save!
- pre!))
- ($_ _.then
- ..restore!
- post!)))
-
-(def: (pattern_matching' expression archive)
- (-> Phase Archive Path (Operation Statement))
+ (with_looping in_closure? g!once g!continue?
+ ($_ _.then
+ ..save!
+ pre!))
+ ..restore!
+ post!))
+
+(def: (pattern_matching' in_closure? statement expression archive)
+ (-> Bit (Generator! Path))
(function (recur pathP)
(.case pathP
(#/////synthesis.Then bodyS)
- (///////phase\map _.return (expression archive bodyS))
+ (statement expression archive bodyS)
#/////synthesis.Pop
(///////phase\wrap ..pop!)
@@ -221,58 +271,49 @@
(..multi_pop! (n.+ 2 extra_pops))
next!))))
- (^template [<tag> <combinator>]
- [(^ (<tag> preP postP))
- (do ///////phase.monad
- [pre! (recur preP)
- post! (recur postP)]
- (wrap (<combinator> pre! post!)))])
- ([/////synthesis.path/seq _.then]
- [/////synthesis.path/alt ..alternation]))))
-
-(def: (pattern_matching expression archive pathP)
- (-> Phase Archive Path (Operation Statement))
+ (^ (/////synthesis.path/seq preP postP))
+ (do ///////phase.monad
+ [pre! (recur preP)
+ post! (recur postP)]
+ (wrap ($_ _.then
+ pre!
+ post!)))
+
+ (^ (/////synthesis.path/alt preP postP))
+ (do ///////phase.monad
+ [pre! (recur preP)
+ post! (recur postP)
+ g!once (..gensym "once")
+ g!continue? (..gensym "continue")]
+ (wrap (..alternation in_closure? g!once g!continue? pre! post!)))
+ )))
+
+(def: (pattern_matching in_closure? statement expression archive pathP)
+ (-> Bit (Generator! Path))
(do ///////phase.monad
- [pattern_matching! (pattern_matching' expression archive pathP)]
+ [pattern_matching! (pattern_matching' in_closure? statement expression archive pathP)
+ g!once (..gensym "once")
+ g!continue? (..gensym "continue")]
(wrap ($_ _.then
- (_.while (_.bool true)
- pattern_matching!)
+ (..with_looping in_closure? g!once g!continue?
+ pattern_matching!)
(_.statement (_.raise (_.string case.pattern_matching_error)))))))
-(def: #export dependencies
- (-> Path (List LVar))
- (|>> case.storage
- (get@ #case.dependencies)
- set.to_list
- (list\map (function (_ variable)
- (.case variable
- (#///////variable.Local register)
- (..register register)
-
- (#///////variable.Foreign register)
- (..capture register))))))
-
-(def: #export (case expression archive [valueS pathP])
- (Generator [Synthesis Path])
+(def: #export (case! in_closure? statement expression archive [valueS pathP])
+ (-> Bit (Generator! [Synthesis Path]))
(do ///////phase.monad
- [initG (expression archive valueS)
- [[case_module case_artifact] pattern_matching!] (/////generation.with_new_context archive
- (pattern_matching expression archive pathP))
- #let [## @case (_.local (///reference.artifact [case_module case_artifact]))
- ## @dependencies+ (..dependencies (/////synthesis.path/seq (/////synthesis.path/then valueS)
- ## pathP))
- ## directive (_.function @case @dependencies+
- ## ($_ _.then
- ## (_.set (list @cursor) (_.array (list initG)))
- ## (_.set (list @savepoint) (_.array (list)))
- ## pattern_matching!))
- directive (_.lambda #.None (list)
- ($_ _.then
- (_.set (list @cursor) (_.array (list initG)))
- (_.set (list @savepoint) (_.array (list)))
- pattern_matching!))]
- ## _ (/////generation.execute! directive)
- ## _ (/////generation.save! (%.nat case_artifact) directive)
- ]
- ## (wrap (_.apply/* @dependencies+ @case))
- (wrap (_.apply_lambda/* (list) directive))))
+ [stack_init (expression archive valueS)
+ pattern_matching! (pattern_matching in_closure? statement expression archive pathP)]
+ (wrap ($_ _.then
+ (_.set (list @cursor) (_.array (list stack_init)))
+ (_.set (list @savepoint) (_.array (list)))
+ pattern_matching!
+ ))))
+
+(def: #export (case statement expression archive case)
+ (-> Phase! (Generator [Synthesis Path]))
+ (|> case
+ (case! true statement expression archive)
+ (\ ///////phase.monad map
+ (|>> (_.lambda #.None (list))
+ (_.apply_lambda/* (list))))))
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/function.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/function.lux
index e2ace391d..21d74f8cd 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/function.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/function.lux
@@ -62,15 +62,12 @@
(def: input
(|>> inc //case.register))
-(def: #export (function expression archive [environment arity bodyS])
- (Generator (Abstraction Synthesis))
+(def: #export (function statement expression archive [environment arity bodyS])
+ (-> Phase! (Generator (Abstraction Synthesis)))
(do {! ///////phase.monad}
- [[[function_module function_artifact] bodyO] (/////generation.with_new_context archive
- (do !
- [function_name (\ ! map ///reference.artifact
- (/////generation.context archive))]
- (/////generation.with_anchor (_.local function_name)
- (expression archive bodyS))))
+ [[[function_module function_artifact] body!] (/////generation.with_new_context archive
+ (/////generation.with_anchor 1
+ (statement expression archive bodyS)))
closureO+ (monad.map ! (expression archive) environment)
#let [function_name (///reference.artifact [function_module function_artifact])
@curried (_.local "curried")
@@ -90,9 +87,9 @@
($_ _.then
(_.set (list @num_args) (_.the "length" @curried))
(_.cond (list [(|> @num_args (_.= arityO))
- ($_ _.then
- initialize!
- (_.return bodyO))]
+ (<| (_.then initialize!)
+ //loop.with_scope
+ body!)]
[(|> @num_args (_.> arityO))
(let [slice (.function (_ from to)
(_.array_range from to @curried))
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/loop.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/loop.lux
index 4bdf1bc55..a2df0884a 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/loop.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/loop.lux
@@ -4,7 +4,7 @@
["." monad (#+ do)]]
[data
["." product]
- [text
+ ["." text
["%" format (#+ format)]]
[collection
["." list ("#\." functor fold)]
@@ -30,59 +30,66 @@
[reference
["#." variable (#+ Register)]]]]]]])
-(def: loop_name
- (-> Nat LVar)
- (|>> %.nat (format "loop") _.local))
+(def: (setup offset bindings body)
+ (-> Register (List Expression) Statement Statement)
+ (|> bindings
+ list.enumeration
+ (list\map (function (_ [register value])
+ (_.set (list (//case.register (n.+ offset register)))
+ value)))
+ list.reverse
+ (list\fold _.then body)))
-(def: #export (scope expression archive [start initsS+ bodyS])
- (Generator (Scope Synthesis))
+(def: symbol
+ (_.symbol "lux_continue"))
+
+(def: #export with_scope
+ (-> Statement Statement)
+ (_.while (_.bool true)))
+
+(def: #export (scope! statement expression archive [start initsS+ bodyS])
+ (Generator! (Scope Synthesis))
(case initsS+
## function/false/non-independent loop
#.Nil
- (expression archive bodyS)
+ (statement expression archive bodyS)
## true loop
_
(do {! ///////phase.monad}
- [@loop (\ ! map ..loop_name /////generation.next)
- initsO+ (monad.map ! (expression archive) initsS+)
- [[loop_module loop_artifact] bodyO] (/////generation.with_new_context archive
- (do !
- [@loop (\ ! map (|>> ///reference.artifact _.local)
- (/////generation.context archive))]
- (/////generation.with_anchor @loop
- (expression archive bodyS))))
- #let [@loop (|> [loop_module loop_artifact] ///reference.artifact _.local)
- locals (|> initsS+
- list.enumeration
- (list\map (|>> product.left (n.+ start) //case.register)))
- actual_loop (_.statement
- (_.lambda (#.Some @loop) locals
- (_.return bodyO)))
- [directive instantiation] (: [Statement Expression]
- (case (|> (synthesis.path/then bodyS)
- //case.dependencies
- (set.from_list _.code_hash)
- (set.difference (set.from_list _.code_hash locals))
- set.to_list)
- #.Nil
- [actual_loop
- @loop]
+ [initsO+ (monad.map ! (expression archive) initsS+)
+ body! (/////generation.with_anchor start
+ (statement expression archive bodyS))]
+ (wrap (<| (..setup start initsO+)
+ ..with_scope
+ body!)))))
- foreigns
- [(_.statement
- (_.lambda (#.Some @loop) foreigns
- ($_ _.then
- actual_loop
- (_.return @loop))))
- (_.apply_lambda/* foreigns @loop)]))]
- _ (/////generation.execute! directive)
- _ (/////generation.save! (%.nat loop_artifact) directive)]
- (wrap (_.apply_lambda/* initsO+ instantiation)))))
+(def: #export (scope statement expression archive [start initsS+ bodyS])
+ (-> Phase! (Generator (Scope Synthesis)))
+ (case initsS+
+ ## function/false/non-independent loop
+ #.Nil
+ (expression archive bodyS)
+
+ ## true loop
+ _
+ (do {! ///////phase.monad}
+ [body! (scope! statement expression archive [start initsS+ bodyS])]
+ (wrap (|> body!
+ (_.lambda #.None (list))
+ (_.apply_lambda/* (list)))))))
-(def: #export (recur expression archive argsS+)
- (Generator (List Synthesis))
+(def: #export (recur! statement expression archive argsS+)
+ (Generator! (List Synthesis))
(do {! ///////phase.monad}
- [@scope /////generation.anchor
- argsO+ (monad.map ! (expression archive) argsS+)]
- (wrap (_.apply_lambda/* argsO+ @scope))))
+ [offset /////generation.anchor
+ @temp (//case.gensym "lux_recur_values")
+ argsO+ (monad.map ! (expression archive) argsS+)
+ #let [re_binds (|> argsO+
+ list.enumeration
+ (list\map (function (_ [idx _])
+ (_.nth (_.int (.int idx)) @temp))))]]
+ (wrap ($_ _.then
+ (_.set (list @temp) (_.array argsO+))
+ (..setup offset re_binds
+ _.next)))))
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/runtime.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/runtime.lux
index d74915164..01befb892 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/runtime.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/ruby/runtime.lux
@@ -39,7 +39,7 @@
(template [<name> <base>]
[(type: #export <name>
- (<base> LVar Expression Statement))]
+ (<base> Register Expression Statement))]
[Operation /////generation.Operation]
[Phase /////generation.Phase]
@@ -51,12 +51,10 @@
(-> Phase Archive i (Operation Expression)))
(type: #export Phase!
- (-> Phase Archive Synthesis (Operation (Statement Any))))
+ (-> Phase Archive Synthesis (Operation Statement)))
(type: #export (Generator! i)
- (-> Phase! Phase Archive i (Operation (Statement Any))))
-
-(def: prefix Text "LuxRuntime")
+ (-> Phase! Phase Archive i (Operation Statement)))
(def: #export unit
(_.string /////synthesis.unit))
@@ -196,8 +194,8 @@
test_recursion! (_.if is_last?
## Must recurse.
($_ _.then
- (_.set (list sum) sum_value)
- (_.set (list wantedTag) (_.- sum_tag wantedTag)))
+ (_.set (list wantedTag) (_.- sum_tag wantedTag))
+ (_.set (list sum) sum_value))
no_match!)]
(<| (_.while (_.bool true))
(_.cond (list [(_.= sum_tag wantedTag)
@@ -245,18 +243,76 @@
@lux//program_args
))
-(runtime: (i64//logic_right_shift param subject)
- (let [mask (|> (_.int +1)
- (_.bit_shl (_.- param (_.int +64)))
- (_.- (_.int +1)))]
+(def: i64//+limit (_.manual "+0x7FFFFFFFFFFFFFFF"))
+(def: i64//-limit (_.manual "-0x8000000000000000"))
+(def: i64//+iteration (_.manual "+0x10000000000000000"))
+(def: i64//-iteration (_.manual "-0x10000000000000000"))
+(def: i64//+cap (_.manual "+0x8000000000000000"))
+(def: i64//-cap (_.manual "-0x8000000000000001"))
+
+(runtime: (i64//64 input)
+ (with_vars [temp]
+ (`` (<| (~~ (template [<scenario> <iteration> <cap> <entrance>]
+ [(_.if (|> input <scenario>)
+ ($_ _.then
+ (_.set (list temp) (_.% <iteration> input))
+ (_.return (_.? (|> temp <scenario>)
+ (|> temp (_.- <cap>) (_.+ <entrance>))
+ temp))))]
+
+ [(_.> ..i64//+limit) ..i64//+iteration ..i64//+cap ..i64//-limit]
+ [(_.< ..i64//-limit) ..i64//-iteration ..i64//-cap ..i64//+limit]
+ ))
+ (_.return input)))))
+
+(runtime: i64//nat_top
+ (|> (_.int +1)
+ (_.bit_shl (_.int +64))
+ (_.- (_.int +1))))
+
+(def: as_nat
+ (_.% (_.manual "0x10000000000000000")))
+
+(runtime: (i64//left_shift param subject)
+ (_.return (|> subject
+ (_.bit_shl (_.% (_.int +64) param))
+ ..i64//64)))
+
+(runtime: (i64//right_shift param subject)
+ ($_ _.then
+ (_.set (list param) (_.% (_.int +64) param))
+ (_.return (_.? (_.= (_.int +0) param)
+ subject
+ (|> subject
+ ..as_nat
+ (_.bit_shr param))))))
+
+(template [<runtime> <host>]
+ [(runtime: (<runtime> left right)
+ (_.return (..i64//64 (<host> (..as_nat left) (..as_nat right)))))]
+
+ [i64//and _.bit_and]
+ [i64//or _.bit_or]
+ [i64//xor _.bit_xor]
+ )
+
+(runtime: (i64//division parameter subject)
+ (let [extra (_.do "remainder" (list parameter) subject)]
(_.return (|> subject
- (_.bit_shr param)
- (_.bit_and mask)))))
+ (_.- extra)
+ (_./ parameter)))))
(def: runtime//i64
Statement
($_ _.then
- @i64//logic_right_shift
+ @i64//64
+ @i64//nat_top
+ @i64//left_shift
+ @i64//right_shift
+ @i64//and
+ @i64//or
+ @i64//xor
+ @i64//division
))
(runtime: (f64//decode inputG)
@@ -291,13 +347,15 @@
(_.and (|> value (_.>= (_.int +0)))
(|> value (_.< top))))
-(runtime: (text//clip @text @from @to)
- (_.return (|> @text (_.array_range @from @to))))
+(runtime: (text//clip offset length text)
+ (_.if (_.= (_.int +0) length)
+ (_.return (_.string ""))
+ (_.return (_.array_range offset (_.+ offset (_.- (_.int +1) length)) text))))
(runtime: (text//char idx text)
(_.if (|> idx (within? (_.the "length" text)))
- (_.return (..some (|> text (_.array_range idx idx) (_.do "ord" (list)))))
- (_.return ..none)))
+ (_.return (|> text (_.array_range idx idx) (_.do "ord" (list))))
+ (_.statement (_.raise (_.string "[Lux Error] Cannot get char from text.")))))
(def: runtime//text
Statement
@@ -307,6 +365,17 @@
@text//char
))
+(runtime: (array//write idx value array)
+ ($_ _.then
+ (_.set (list (_.nth idx array)) value)
+ (_.return array)))
+
+(def: runtime//array
+ Statement
+ ($_ _.then
+ @array//write
+ ))
+
(def: runtime
Statement
($_ _.then
@@ -315,11 +384,9 @@
runtime//i64
runtime//f64
runtime//text
+ runtime//array
))
-(def: #export artifact
- ..prefix)
-
(def: #export generate
(Operation [Registry Output])
(do ///////phase.monad
diff --git a/stdlib/source/lux/world/file.lux b/stdlib/source/lux/world/file.lux
index 972019c39..0d6958d23 100644
--- a/stdlib/source/lux/world/file.lux
+++ b/stdlib/source/lux/world/file.lux
@@ -1139,6 +1139,217 @@
..default_separator)
))
)
+
+ @.ruby
+ (as_is (host.import: Time #as RubyTime
+ (#static at [Frac] RubyTime)
+
+ (to_f [] Frac))
+
+ (host.import: Stat #as RubyStat
+ (executable? [] Bit)
+ (size Int)
+ (mtime [] RubyTime))
+
+ (host.import: File #as RubyFile
+ (#static SEPARATOR host.String)
+ (#static open [Path host.String] #io #try RubyFile)
+ (#static stat [Path] #io #try RubyStat)
+ (#static delete [Path] #io #try Int)
+ (#static file? [Path] #io #try Bit)
+ (#static directory? [Path] #io #try Bit)
+ (#static utime [RubyTime RubyTime Path] #io #try Int)
+
+ (read [] #io #try Binary)
+ (write [Binary] #io #try Int)
+ (flush [] #io #try #? Any)
+ (close [] #io #try #? Any))
+
+ (host.import: Dir #as RubyDir
+ (#static open [Path] #io #try RubyDir)
+
+ (children [] #io #try (Array Path))
+ (close [] #io #try #? Any))
+
+ (host.import: "fileutils" FileUtils #as RubyFileUtils
+ (#static touch [Path] #io #try #? Any)
+ (#static move [Path Path] #io #try #? Any)
+ (#static rmdir [Path] #io #try #? Any)
+ (#static mkdir [Path] #io #try #? Any))
+
+ (def: default_separator
+ Text
+ (..RubyFile::SEPARATOR))
+
+ (`` (structure: (file path)
+ (-> Path (File IO))
+
+ (~~ (template [<name> <mode>]
+ [(def: <name>
+ (..can_modify
+ (function (<name> data)
+ (do {! (try.with io.monad)}
+ [file (RubyFile::open [path <mode>])
+ data (RubyFile::write [data] file)
+ _ (RubyFile::flush [] file)
+ _ (RubyFile::close [] file)]
+ (wrap [])))))]
+
+ [over_write "wb"]
+ [append "ab"]
+ ))
+
+ (def: content
+ (..can_query
+ (function (_ _)
+ (do {! (try.with io.monad)}
+ [file (RubyFile::open [path "rb"])
+ data (RubyFile::read [] file)
+ _ (RubyFile::close [] file)]
+ (wrap data)))))
+
+ (def: name
+ (..can_see
+ (function (_ _)
+ (|> path
+ (text.split_all_with ..default_separator)
+ list.reverse
+ list.head
+ (maybe.default path)))))
+
+ (def: path
+ (..can_see
+ (function (_ _)
+ path)))
+
+ (~~ (template [<capability> <name> <pipeline>]
+ [(def: <name>
+ (<capability>
+ (function (_ _)
+ (do {! (try.with io.monad)}
+ [stat (: (IO (Try RubyStat))
+ (RubyFile::stat [path]))]
+ (wrap (`` (|> stat (: RubyStat) (~~ (template.splice <pipeline>)))))))))]
+
+ [..can_query size [RubyStat::size .nat]]
+ [..can_query last_modified [(RubyStat::mtime [])
+ (RubyTime::to_f [])
+ (f.* +1,000.0)
+ f.int
+ duration.from_millis
+ instant.absolute]]
+ [..can_query can_execute? [(RubyStat::executable? [])]]
+ ))
+
+ (def: modify
+ (..can_modify
+ (function (_ moment)
+ (let [moment (|> moment
+ instant.relative
+ duration.to_millis
+ i.frac
+ (f./ +1,000.0)
+ RubyTime::at)]
+ (do {! (try.with io.monad)}
+ [_ (RubyFile::utime [moment moment path])]
+ (wrap []))))))
+
+ (def: move
+ (..can_open
+ (function (_ destination)
+ (do {! (try.with io.monad)}
+ [_ (RubyFileUtils::move [path destination])]
+ (wrap (file destination))))))
+
+ (def: delete
+ (..can_delete
+ (function (_ _)
+ (do {! (try.with io.monad)}
+ [_ (RubyFile::delete [path])]
+ (wrap [])))))
+ ))
+
+ (`` (structure: (directory path)
+ (-> Path (Directory IO))
+
+ (def: scope
+ (..can_see
+ (function (_ _)
+ path)))
+
+ (~~ (template [<name> <test> <constructor> <capability>]
+ [(def: <name>
+ (..can_query
+ (function (_ _)
+ (do {! (try.with io.monad)}
+ [self (RubyDir::open [path])
+ children (RubyDir::children [] self)
+ output (loop [input (|> children
+ array.to_list
+ (list\map (|>> (format path ..default_separator))))
+ output (: (List (<capability> IO))
+ (list))]
+ (case input
+ #.Nil
+ (wrap output)
+
+ (#.Cons head tail)
+ (do !
+ [verdict (<test> head)]
+ (if verdict
+ (recur tail (#.Cons (<constructor> head) output))
+ (recur tail output)))))
+ _ (RubyDir::close [] self)]
+ (wrap output)))))]
+
+ [files RubyFile::file? ..file File]
+ [directories RubyFile::directory? directory Directory]
+ ))
+
+ (def: discard
+ (..can_delete
+ (function (discard _)
+ (do {! (try.with io.monad)}
+ [_ (RubyFileUtils::rmdir [path])]
+ (wrap [])))))
+ ))
+
+ (`` (structure: #export default
+ (System IO)
+
+ (~~ (template [<name> <test> <constructor> <exception>]
+ [(def: <name>
+ (..can_open
+ (function (_ path)
+ (do {! (try.with io.monad)}
+ [verdict (<test> path)]
+ (\ io.monad wrap
+ (if verdict
+ (#try.Success (<constructor> path))
+ (exception.throw <exception> [path])))))))]
+
+ [file RubyFile::file? ..file ..cannot_find_file]
+ [directory RubyFile::directory? ..directory ..cannot_find_directory]
+ ))
+
+ (def: create_file
+ (..can_open
+ (function (_ path)
+ (do {! (try.with io.monad)}
+ [_ (RubyFileUtils::touch [path])]
+ (wrap (..file path))))))
+
+ (def: create_directory
+ (..can_open
+ (function (create_directory path)
+ (do {! (try.with io.monad)}
+ [_ (RubyFileUtils::mkdir path)]
+ (wrap (..directory path))))))
+
+ (def: separator
+ ..default_separator)
+ ))
+ )
}))
(template [<get> <signature> <create> <find> <exception>]
diff --git a/stdlib/source/lux/world/program.lux b/stdlib/source/lux/world/program.lux
index 7a3d125a0..acaf36711 100644
--- a/stdlib/source/lux/world/program.lux
+++ b/stdlib/source/lux/world/program.lux
@@ -19,7 +19,8 @@
["%" format (#+ format)]]
[collection
["." array (#+ Array) ("#\." fold)]
- ["." dictionary (#+ Dictionary)]]]
+ ["." dictionary (#+ Dictionary)]
+ ["." list ("#\." functor)]]]
[math
[number
["i" int]]]]
@@ -203,7 +204,19 @@
(wrap default))
(#try.Failure _)
- (wrap default)))))}
+ (wrap default)))))
+ @.ruby (as_is (host.import: Env #as RubyEnv
+ (#static keys [] (Array Text))
+ (#static fetch [Text] Text))
+
+ (host.import: "fileutils" FileUtils #as RubyFileUtils
+ (#static pwd [] #io Path))
+
+ (host.import: Dir #as RubyDir
+ (#static home [] #io Path))
+
+ (host.import: Kernel #as RubyKernel
+ (#static exit [Int] #io Nothing)))}
(as_is)))
(structure: #export default
@@ -235,7 +248,13 @@
[value (os/environ::get [variable])]
(wrap (dictionary.put variable value environment))))
environment.empty
- (array.to_list keys)))}
+ (array.to_list keys)))
+ @.ruby (|> (RubyEnv::keys [])
+ array.to_list
+ (list\map (function (_ variable)
+ [variable (RubyEnv::fetch [variable])]))
+ (dictionary.from_list text.hash)
+ io.io)}
## TODO: Replace dummy implementation.
(io.io environment.empty))))
@@ -250,7 +269,8 @@
(NodeJs_OS::homedir []))
<default>)
@.python (os/path::expanduser ["~"])
- @.lua (..run_command "~" "echo ~")}
+ @.lua (..run_command "~" "echo ~")
+ @.ruby (RubyDir::home [])}
## TODO: Replace dummy implementation.
<default>)))
@@ -273,7 +293,8 @@
on_windows (..run_command default "cd")]
(if (is? default on_windows)
(..run_command default "pwd")
- (wrap on_windows)))}
+ (wrap on_windows)))
+ @.ruby (RubyFileUtils::pwd [])}
## TODO: Replace dummy implementation.
(io.io <default>))))
@@ -292,4 +313,5 @@
## else
(..default_exit! code))
@.python (os::_exit [code])
- @.lua (os/exit [code])}))))
+ @.lua (os/exit [code])
+ @.ruby (RubyKernel::exit [code])}))))
diff --git a/stdlib/source/test/lux.lux b/stdlib/source/test/lux.lux
index 0379b8427..ef6177deb 100644
--- a/stdlib/source/test/lux.lux
+++ b/stdlib/source/test/lux.lux
@@ -183,7 +183,8 @@
@.jvm on_valid_host
@.js on_valid_host
@.python on_valid_host
- @.lua on_valid_host}
+ @.lua on_valid_host
+ @.ruby on_valid_host}
on_default))))))
(def: conversion_tests
diff --git a/stdlib/source/test/lux/extension.lux b/stdlib/source/test/lux/extension.lux
index 67abd0eca..450570c20 100644
--- a/stdlib/source/test/lux/extension.lux
+++ b/stdlib/source/test/lux/extension.lux
@@ -5,7 +5,8 @@
["." jvm]
["." js]
["." python]
- ["." lua]]
+ ["." lua]
+ ["." ruby]]
[abstract
[monad (#+ do)]]
[control
@@ -65,7 +66,8 @@
@.js (js.string self)
@.python (python.unicode self)
- @.lua (lua.string self)})))))
+ @.lua (lua.string self)
+ @.ruby (ruby.string self)})))))
(for {@.old
(as_is)}
diff --git a/stdlib/source/test/lux/host.rb.lux b/stdlib/source/test/lux/host.rb.lux
new file mode 100644
index 000000000..0b6cac81b
--- /dev/null
+++ b/stdlib/source/test/lux/host.rb.lux
@@ -0,0 +1,24 @@
+(.module:
+ [lux #*
+ ["_" test (#+ Test)]
+ [abstract
+ [monad (#+ do)]]
+ [control
+ ["." try]]
+ [data
+ ["." text ("#\." equivalence)]]
+ [math
+ ["." random (#+ Random)]
+ [number
+ ["." nat]
+ ["." frac]]]]
+ {1
+ ["." /]})
+
+(def: #export test
+ Test
+ (do {! random.monad}
+ []
+ (<| (_.covering /._)
+ (_.test "TBD"
+ true))))