aboutsummaryrefslogtreecommitdiff
path: root/stdlib
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--stdlib/source/lux/data/error/exception.lux2
-rw-r--r--stdlib/source/lux/data/format/json.lux70
-rw-r--r--stdlib/source/lux/data/struct/vector.lux15
-rw-r--r--stdlib/source/lux/lexer.lux2
-rw-r--r--stdlib/source/lux/macro/poly.lux44
-rw-r--r--stdlib/source/lux/macro/syntax/common.lux27
-rw-r--r--stdlib/source/lux/math/random.lux10
-rw-r--r--stdlib/source/lux/type.lux97
-rw-r--r--stdlib/test/test/lux/data/error/exception.lux50
-rw-r--r--stdlib/test/test/lux/data/format/json.lux402
-rw-r--r--stdlib/test/test/lux/data/struct/vector.lux19
-rw-r--r--stdlib/test/tests.lux4
12 files changed, 308 insertions, 434 deletions
diff --git a/stdlib/source/lux/data/error/exception.lux b/stdlib/source/lux/data/error/exception.lux
index be9a09327..c3e9143e2 100644
--- a/stdlib/source/lux/data/error/exception.lux
+++ b/stdlib/source/lux/data/error/exception.lux
@@ -35,7 +35,7 @@
(#;Right (then error))
(#;Left error))))
-(def: #export (else to-do try)
+(def: #export (otherwise to-do try)
(All [a]
(-> (-> Text a) (Error a) a))
(case try
diff --git a/stdlib/source/lux/data/format/json.lux b/stdlib/source/lux/data/format/json.lux
index c51e4b04c..d48b5b97a 100644
--- a/stdlib/source/lux/data/format/json.lux
+++ b/stdlib/source/lux/data/format/json.lux
@@ -67,8 +67,8 @@
wrapper (lambda [x] (` (;;json (~ x))))]
(case token
(^template [<ast-tag> <ctor> <json-tag>]
- [_ (<ast-tag> value)]
- (wrap (list (` (: JSON (<json-tag> (~ (<ctor> value))))))))
+ [_ (<ast-tag> value)]
+ (wrap (list (` (: JSON (<json-tag> (~ (<ctor> value))))))))
([#;BoolS ast;bool #Boolean]
[#;IntS (|>. int-to-real ast;real) #Number]
[#;RealS ast;real #Number]
@@ -109,7 +109,7 @@
(def: (show-array show-json elems)
(-> (-> JSON Text) (-> Array Text))
(format "["
- (|> elems (Vector/map show-json) vector;vector-to-list (text;join-with ","))
+ (|> elems (Vector/map show-json) vector;to-list (text;join-with ","))
"]"))
(def: (show-object show-json object)
@@ -125,8 +125,8 @@
(-> JSON Text)
(case json
(^template [<tag> <show>]
- (<tag> value)
- (<show> value))
+ (<tag> value)
+ (<show> value))
([#Null show-null]
[#Boolean show-boolean]
[#Number show-number]
@@ -316,7 +316,7 @@
_ (lexer;this-char <close>)]
(wrap (<prep> elems))))]
- [array~ Array #"[" #"]" (json~ []) vector;list-to-vector]
+ [array~ Array #"[" #"]" (json~ []) vector;from-list]
[object~ Object #"{" #"}" (kv~ json~) (dict;from-list text;Hash<Text>)]
)
@@ -485,7 +485,7 @@
(case json
(#Array values)
(do Monad<Error>
- [elems (mapM @ parser (vector;vector-to-list values))]
+ [elems (mapM @ parser (vector;to-list values))]
(wrap elems))
_
@@ -631,8 +631,8 @@
true
(^template [<tag> <struct>]
- [(<tag> x') (<tag> y')]
- (:: <struct> = x' y'))
+ [(<tag> x') (<tag> y')]
+ (:: <struct> = x' y'))
([#Boolean bool;Eq<Bool>]
[#Number number;Eq<Real>]
[#String text;Eq<Text>])
@@ -719,18 +719,18 @@
(All [a b] (-> (-> a b) (List a) (List b)))
List/map)
-(poly: #export (|Codec@JSON//encode| *env* :x:)
+(poly: #export (Codec<JSON,?>//encode *env* :x:)
(let [->Codec//encode (: (-> AST AST)
(lambda [.type.] (` (-> (~ .type.) JSON))))]
(let% [<basic> (do-template [<type> <matcher> <encoder>]
[(do @ [_ (<matcher> :x:)] (wrap (` (: (~ (->Codec//encode (` <type>))) <encoder>))))]
[Unit poly;unit (lambda [(~ (ast;symbol ["" "0"]))] #Null)]
- [Bool poly;bool ;;boolean]
- [Int poly;int (|>. int-to-real ;;number)]
- [Real poly;real ;;number]
- [Char poly;char (|>. char;->Text ;;string)]
- [Text poly;text ;;string])]
+ [Bool poly;bool ;;gen-boolean]
+ [Int poly;int (|>. ;int-to-real ;;gen-number)]
+ [Real poly;real ;;gen-number]
+ [Char poly;char (|>. char;as-text ;;gen-string)]
+ [Text poly;text ;;gen-string])]
($_ compiler;either
<basic>
(with-gensyms [g!type-fun g!case g!input g!key g!val]
@@ -745,7 +745,7 @@
_
(compiler;fail ""))
#let [new-*env* (poly;extend-env g!type-fun g!vars *env*)]
- .val. (|Codec@JSON//encode| new-*env* :val:)
+ .val. (Codec<JSON,?>//encode new-*env* :val:)
#let [:x:+ (case g!vars
#;Nil
(->Codec//encode (type;type-to-ast :x:))
@@ -767,14 +767,14 @@
))
(do @
[:sub: (poly;maybe :x:)
- .sub. (|Codec@JSON//encode| *env* :sub:)]
+ .sub. (Codec<JSON,?>//encode *env* :sub:)]
(wrap (` (: (~ (->Codec//encode (type;type-to-ast :x:)))
- (;;nullable (~ .sub.))))))
+ (;;gen-nullable (~ .sub.))))))
(do @
[:sub: (poly;list :x:)
- .sub. (|Codec@JSON//encode| *env* :sub:)]
+ .sub. (Codec<JSON,?>//encode *env* :sub:)]
(wrap (` (: (~ (->Codec//encode (type;type-to-ast :x:)))
- (|>. (_map_ (~ .sub.)) vector;list-to-vector ;;array)))))
+ (|>. (_map_ (~ .sub.)) vector;from-list ;;gen-array)))))
(with-gensyms [g!type-fun g!case g!input]
(do @
[[g!vars cases] (poly;variant :x:)
@@ -783,7 +783,7 @@
(lambda [[name :case:]]
(do @
[#let [tag (ast;tag name)]
- encoder (|Codec@JSON//encode| new-*env* :case:)]
+ encoder (Codec<JSON,?>//encode new-*env* :case:)]
(wrap (list (` ((~ tag) (~ g!case)))
(` (;;json [(~ (ast;text (product;right name)))
((~ encoder) (~ g!case))]))))))
@@ -808,7 +808,7 @@
synthesis (mapM @
(lambda [[name :slot:]]
(do @
- [encoder (|Codec@JSON//encode| new-*env* :slot:)]
+ [encoder (Codec<JSON,?>//encode new-*env* :slot:)]
(wrap [(` (~ (ast;text (product;right name))))
(` ((~ encoder) (get@ (~ (ast;tag name)) (~ g!input))))])))
slots)
@@ -824,7 +824,7 @@
(lambda [(~@ g!vars) (~ g!input)]
(;;json (~ (ast;record synthesis))))
)))))
- (with-gensyms [g!type-fun g!case g!input]
+ (with-gensyms [g!type-fun g!case]
(do @
[[g!vars members] (poly;tuple :x:)
#let [new-*env* (poly;extend-env g!type-fun g!vars *env*)]
@@ -832,7 +832,7 @@
(lambda [:member:]
(do @
[g!member (compiler;gensym "g!member")
- encoder (|Codec@JSON//encode| new-*env* :member:)]
+ encoder (Codec<JSON,?>//encode new-*env* :member:)]
(wrap [g!member encoder])))
members)
#let [:x:+ (case g!vars
@@ -845,18 +845,16 @@
(~ (->Codec//encode (` ((~ (type;type-to-ast :x:)) (~@ g!vars)))))))))]
#let [.tuple. (` [(~@ (List/map product;left pattern-matching))])]]
(wrap (` (: (~ :x:+)
- (lambda [(~@ g!vars) (~ g!input)]
- (case (~ g!input)
- (~ .tuple.)
- (;;array (list (~@ (List/map (lambda [[g!member g!encoder]]
- (` ((~ g!encoder) (~ g!member))))
- pattern-matching))))))
+ (lambda [(~@ g!vars) (~ .tuple.)]
+ (;;json [(~@ (List/map (lambda [[g!member g!encoder]]
+ (` ((~ g!encoder) (~ g!member))))
+ pattern-matching))]))
)))
))
(do @
[[:func: :args:] (poly;apply :x:)
- .func. (|Codec@JSON//encode| *env* :func:)
- .args. (mapM @ (|Codec@JSON//encode| *env*) :args:)]
+ .func. (Codec<JSON,?>//encode *env* :func:)
+ .args. (mapM @ (Codec<JSON,?>//encode *env*) :args:)]
(wrap (` (: (~ (->Codec//encode (type;type-to-ast :x:)))
((~ .func.) (~@ .args.))))))
(poly;bound *env* :x:)
@@ -869,7 +867,7 @@
(let% [<basic> (do-template [<type> <matcher> <decoder>]
[(do @ [_ (<matcher> :x:)] (wrap (` (: (~ (->Codec//decode (` <type>))) <decoder>))))]
- [Unit poly;unit ;;null]
+ [Unit poly;unit ;;unit]
[Bool poly;bool ;;bool]
[Int poly;int ;;int]
[Real poly;real ;;real]
@@ -931,8 +929,8 @@
[#let [tag (ast;tag name)]
decoder (Codec<JSON,?>//decode new-*env* :case:)]
(wrap (list (` (do Monad<Parser>
- [(~ g!_) (;;at 0 (;;text! (~ (ast;text (product;right name)))))
- (~ g!_) (;;at 1 (~ decoder))]
+ [(~ g!_) (;;at +0 (;;text! (~ (ast;text (product;right name)))))
+ (~ g!_) (;;at +1 (~ decoder))]
((~ (' wrap)) ((~ tag) (~ g!_)))))))))
cases)
#let [:x:+ (case g!vars
@@ -1026,6 +1024,6 @@
(syntax: #export (Codec<JSON,?> :x:)
(wrap (list (` (: (Codec JSON (~ :x:))
(struct
- (def: (~ (' encode)) (|Codec@JSON//encode| (~ :x:)))
+ (def: (~ (' encode)) (Codec<JSON,?>//encode (~ :x:)))
(def: (~ (' decode)) (Codec<JSON,?>//decode (~ :x:)))
))))))
diff --git a/stdlib/source/lux/data/struct/vector.lux b/stdlib/source/lux/data/struct/vector.lux
index 4b8fb4bf3..9c04bc173 100644
--- a/stdlib/source/lux/data/struct/vector.lux
+++ b/stdlib/source/lux/data/struct/vector.lux
@@ -365,12 +365,11 @@
(struct: #export (Eq<Vector> Eq<a>) (All [a] (-> (Eq a) (Eq (Vector a))))
(def: (= v1 v2)
(and (=+ (get@ #size v1) (get@ #size v2))
- (:: (Eq<Node> Eq<a>) =
- (#Base (get@ #tail v1))
- (#Base (get@ #tail v2)))
- (:: (Eq<Node> Eq<a>) =
- (#Hierarchy (get@ #root v1))
- (#Hierarchy (get@ #root v2))))))
+ (let [(^open "Node/") (Eq<Node> Eq<a>)]
+ (and (Node/= (#Base (get@ #tail v1))
+ (#Base (get@ #tail v2)))
+ (Node/= (#Hierarchy (get@ #root v1))
+ (#Hierarchy (get@ #root v2))))))))
(struct: _ (Fold Node)
(def: (fold f init xs)
@@ -436,9 +435,9 @@
(struct: #export _ (Monad Vector)
(def: applicative Applicative<Vector>)
- (def: (join ffa)
+ (def: join
(let [(^open) Functor<Vector>
(^open) Fold<Vector>
(^open) Monoid<Vector>]
- (fold append unit ffa)))
+ (fold append unit)))
)
diff --git a/stdlib/source/lux/lexer.lux b/stdlib/source/lux/lexer.lux
index 654259d8d..77ce0ce93 100644
--- a/stdlib/source/lux/lexer.lux
+++ b/stdlib/source/lux/lexer.lux
@@ -4,7 +4,7 @@
## You can obtain one at http://mozilla.org/MPL/2.0/.
(;module:
- [lux #- not]
+ [lux #- not default]
(lux (control functor
applicative
monad
diff --git a/stdlib/source/lux/macro/poly.lux b/stdlib/source/lux/macro/poly.lux
index ac7043f26..914575cc0 100644
--- a/stdlib/source/lux/macro/poly.lux
+++ b/stdlib/source/lux/macro/poly.lux
@@ -9,7 +9,7 @@
[eq])
(data [text]
text/format
- (struct [list "List/" Monad<List>]
+ (struct [list "List/" Fold<List> Monad<List>]
[dict #+ Dict])
[number]
[product]
@@ -140,7 +140,7 @@
_
(:: compiler;Monad<Lux> wrap [(;list) :type:])))))
-(do-template [<combinator> <sub-comb>]
+(do-template [<combinator> <sub-comb> <build>]
[(def: #export <combinator>
(Matcher [(List AST) (List [Ident Type])])
(lambda [:type:]
@@ -148,11 +148,17 @@
[[tags :type:] (tagged :type:)
_ (compiler;assert (>+ +0 (list;size tags)) "Records and variants must have tags.")
[vars :type:] (polymorphic :type:)
- members (<sub-comb> :type:)]
- (wrap [vars (list;zip2 tags members)]))))]
-
- [variant sum+]
- [record prod+]
+ members (<sub-comb> :type:)
+ #let [num-tags (list;size tags)
+ [init-tags last-tag] (list;split (dec+ num-tags) tags)
+ [init-types last-types] (list;split (dec+ num-tags) members)]]
+ (wrap [vars (list;concat (;list (list;zip2 init-tags init-types)
+ (;list [(default (undefined)
+ (list;head last-tag))
+ (<build> last-types)])))]))))]
+
+ [variant sum+ type;variant]
+ [record prod+ type;tuple]
)
(def: #export tuple
@@ -301,35 +307,21 @@
(def: (common-poly-name? poly-func)
(-> Text Bool)
- (and (text;starts-with? "|" poly-func)
- (text;ends-with? "|" poly-func)))
+ (text;contains? "?" poly-func))
(def: (derivation-name poly args)
(-> Text (List Text) (Maybe Text))
(if (common-poly-name? poly)
- (case (text;sub +1 (dec+ (text;size poly)) poly)
- (#;Some clean-poly)
- (case (list;reverse args)
- #;Nil
- #;None
-
- (#;Cons type #;Nil)
- (#;Some (format type "/" clean-poly))
-
- (#;Cons type args)
- (#;Some (format type "/" clean-poly "@" (|> args list;reverse (text;join-with ",")))))
-
- #;None
- #;None)
+ (#;Some (List/fold (text;replace-once "?") poly args))
#;None))
(syntax: #export (derived: {_ex-lev common;export-level}
{?name (s;opt s;local-symbol)}
- {[poly-func poly-args] (s;either (s;form (s;seq s;symbol (s;many s;symbol)))
- (s;seq s;symbol (:: @ wrap (;list))))}
+ {[poly-func poly-args] (s;form (s;seq s;symbol (s;many s;symbol)))}
{?custom-impl (s;opt s;any)})
(do @
- [name (case ?name
+ [poly-args (mapM @ compiler;normalize poly-args)
+ name (case ?name
(#;Some name)
(wrap name)
diff --git a/stdlib/source/lux/macro/syntax/common.lux b/stdlib/source/lux/macro/syntax/common.lux
index 743768fe6..6cec7f713 100644
--- a/stdlib/source/lux/macro/syntax/common.lux
+++ b/stdlib/source/lux/macro/syntax/common.lux
@@ -7,7 +7,9 @@
lux
(lux (control monad)
(data (struct [list])
- text/format)
+ text/format
+ [ident "Ident/" Eq<Ident>]
+ [product])
[compiler]
(macro [ast]
["s" syntax #+ syntax: Syntax])))
@@ -104,18 +106,17 @@
(def: (find-def-args meta-data)
(-> (List [Ident AST]) (List Text))
(default (list)
- (list;find (lambda [[tag value]]
- (case tag
- (^=> ["lux" "func-args"]
- {(s;run (list value) list-meta^)
- (#;Right [_ args])}
- {(s;run args (s;some text-meta^))
- (#;Right [_ args])})
- (#;Some args)
-
- _
- #;None))
- meta-data)))
+ (case (list;find (|>. product;left (Ident/= ["lux" "func-args"])) meta-data)
+ (^=> (#;Some [_ value])
+ {(s;run (list value) list-meta^)
+ (#;Right [_ args])}
+ {(s;run args (s;some text-meta^))
+ (#;Right [_ args])})
+ (#;Some args)
+
+ _
+ #;None)
+ ))
(def: #export (def compiler)
(-> Compiler (Syntax Def-Syntax))
diff --git a/stdlib/source/lux/math/random.lux b/stdlib/source/lux/math/random.lux
index aee5674ad..41481a284 100644
--- a/stdlib/source/lux/math/random.lux
+++ b/stdlib/source/lux/math/random.lux
@@ -174,6 +174,16 @@
(wrap sample)
(filter pred gen))))
+(def: #export (maybe value-gen)
+ (All [a] (-> (Random a) (Random (Maybe a))))
+ (do Monad<Random>
+ [some? bool]
+ (if some?
+ (do @
+ [value value-gen]
+ (wrap (#;Some value)))
+ (wrap #;None))))
+
(do-template [<name> <type> <zero> <plus>]
[(def: #export (<name> size value-gen)
(All [a] (-> Nat (Random a) (Random (<type> a))))
diff --git a/stdlib/source/lux/type.lux b/stdlib/source/lux/type.lux
index 4a84582c4..fbd269daa 100644
--- a/stdlib/source/lux/type.lux
+++ b/stdlib/source/lux/type.lux
@@ -22,24 +22,24 @@
(#;HostT name (List/map (beta-reduce env) params))
(^template [<tag>]
- (<tag> left right)
- (<tag> (beta-reduce env left) (beta-reduce env right)))
+ (<tag> left right)
+ (<tag> (beta-reduce env left) (beta-reduce env right)))
([#;SumT] [#;ProdT])
(^template [<tag>]
- (<tag> left right)
- (<tag> (beta-reduce env left) (beta-reduce env right)))
+ (<tag> left right)
+ (<tag> (beta-reduce env left) (beta-reduce env right)))
([#;LambdaT]
[#;AppT])
(^template [<tag>]
- (<tag> old-env def)
- (case old-env
- #;Nil
- (<tag> env def)
+ (<tag> old-env def)
+ (case old-env
+ #;Nil
+ (<tag> env def)
- _
- type))
+ _
+ type))
([#;UnivQ]
[#;ExQ])
@@ -65,17 +65,17 @@
(list;zip2 xparams yparams)))
(^template [<tag>]
- [<tag> <tag>]
- true)
+ [<tag> <tag>]
+ true)
([#;VoidT] [#;UnitT])
(^template [<tag>]
- [(<tag> xid) (<tag> yid)]
- (=+ yid xid))
+ [(<tag> xid) (<tag> yid)]
+ (=+ yid xid))
([#;VarT] [#;ExT] [#;BoundT])
(^or [(#;LambdaT xleft xright) (#;LambdaT yleft yright)]
- [(#;AppT xleft xright) (#;AppT yleft yright)])
+ [(#;AppT xleft xright) (#;AppT yleft yright)])
(and (= xleft yleft)
(= xright yright))
@@ -85,12 +85,12 @@
(= xtype ytype))
(^template [<tag>]
- [(<tag> xL xR) (<tag> yL yR)]
- (and (= xL yL) (= xR yR)))
+ [(<tag> xL xR) (<tag> yL yR)]
+ (and (= xL yL) (= xR yR)))
([#;SumT] [#;ProdT])
(^or [(#;UnivQ xenv xbody) (#;UnivQ yenv ybody)]
- [(#;ExQ xenv xbody) (#;ExQ yenv ybody)])
+ [(#;ExQ xenv xbody) (#;ExQ yenv ybody)])
(and (=+ (list;size yenv) (list;size xenv))
(= xbody ybody)
(List/fold (lambda [[x y] prev] (and prev (= x y)))
@@ -140,8 +140,8 @@
(-> Type Type (Maybe Type))
(case type-fun
(^template [<tag>]
- (<tag> env body)
- (#;Some (beta-reduce (list& type-fun param env) body)))
+ (<tag> env body)
+ (#;Some (beta-reduce (list& type-fun param env) body)))
([#;UnivQ] [#;ExQ])
(#;AppT F A)
@@ -163,24 +163,24 @@
(list (~@ (List/map type-to-ast params)))))
(^template [<tag>]
- <tag>
- (` <tag>))
+ <tag>
+ (` <tag>))
([#;VoidT] [#;UnitT])
(^template [<tag>]
- (<tag> idx)
- (` (<tag> (~ (ast;nat idx)))))
+ (<tag> idx)
+ (` (<tag> (~ (ast;nat idx)))))
([#;VarT] [#;ExT] [#;BoundT])
(^template [<tag>]
- (<tag> left right)
- (` (<tag> (~ (type-to-ast left))
- (~ (type-to-ast right)))))
+ (<tag> left right)
+ (` (<tag> (~ (type-to-ast left))
+ (~ (type-to-ast right)))))
([#;LambdaT] [#;AppT])
(^template [<tag> <macro> <flattener>]
- (<tag> left right)
- (` (<macro> (~@ (List/map type-to-ast (<flattener> type))))))
+ (<tag> left right)
+ (` (<macro> (~@ (List/map type-to-ast (<flattener> type))))))
([#;SumT | flatten-sum]
[#;ProdT & flatten-prod])
@@ -188,9 +188,9 @@
(ast;symbol name)
(^template [<tag>]
- (<tag> env body)
- (` (<tag> (list (~@ (List/map type-to-ast env)))
- (~ (type-to-ast body)))))
+ (<tag> env body)
+ (` (<tag> (list (~@ (List/map type-to-ast env)))
+ (~ (type-to-ast body)))))
([#;UnivQ] [#;ExQ])
))
@@ -212,14 +212,14 @@
"Unit"
(^template [<tag> <open> <close> <flatten>]
- (<tag> _)
- ($_ Text/append <open>
- (|> (<flatten> type)
- (List/map type-to-text)
- list;reverse
- (list;interpose " ")
- (List/fold Text/append ""))
- <close>))
+ (<tag> _)
+ ($_ Text/append <open>
+ (|> (<flatten> type)
+ (List/map type-to-text)
+ list;reverse
+ (list;interpose " ")
+ (List/fold Text/append ""))
+ <close>))
([#;SumT "(| " ")" flatten-sum]
[#;ProdT "[" "]" flatten-prod])
@@ -273,3 +273,20 @@
_
type))
+
+(do-template [<name> <base> <ctor>]
+ [(def: #export (<name> types)
+ (-> (List Type) Type)
+ (case types
+ #;Nil
+ <base>
+
+ (#;Cons type #;Nil)
+ type
+
+ (#;Cons type types')
+ (<ctor> type (<name> types'))))]
+
+ [variant Void #;SumT]
+ [tuple Unit #;ProdT]
+ )
diff --git a/stdlib/test/test/lux/data/error/exception.lux b/stdlib/test/test/lux/data/error/exception.lux
new file mode 100644
index 000000000..16d09a626
--- /dev/null
+++ b/stdlib/test/test/lux/data/error/exception.lux
@@ -0,0 +1,50 @@
+## Copyright (c) Eduardo Julian. All rights reserved.
+## This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+## If a copy of the MPL was not distributed with this file,
+## You can obtain one at http://mozilla.org/MPL/2.0/.
+
+(;module:
+ lux
+ (lux (codata [io])
+ (control monad)
+ (data (error ["&" exception #+ exception:])
+ [text]
+ [number])
+ (codata function)
+ (math ["R" random])
+ pipe)
+ lux/test)
+
+(exception: Some-Exception)
+
+(exception: Another-Exception)
+
+(exception: Unknown-Exception)
+
+(test: "Exceptions"
+ [should-throw? R;bool
+ which? R;bool
+ should-catch? R;bool
+ default-val R;nat
+ some-val R;nat
+ another-val R;nat
+ otherwise-val R;nat
+ #let [this-ex (if should-catch?
+ (if which?
+ Some-Exception
+ Another-Exception)
+ Unknown-Exception)
+ this-val (if should-throw?
+ (if should-catch?
+ (if which?
+ some-val
+ another-val)
+ otherwise-val)
+ default-val)]]
+ (assert "Catch and otherwhise handlers can properly handle the flow of exception-handling."
+ (=+ this-val (|> (if should-throw?
+ (&;return default-val)
+ (&;throw this-ex "Uh-oh..."))
+ (&;catch Some-Exception (lambda [ex] some-val))
+ (&;catch Another-Exception (lambda [ex] another-val))
+ (&;otherwise (lambda [ex] otherwise-val))))))
diff --git a/stdlib/test/test/lux/data/format/json.lux b/stdlib/test/test/lux/data/format/json.lux
index 78b0b1a76..d7c622bd5 100644
--- a/stdlib/test/test/lux/data/format/json.lux
+++ b/stdlib/test/test/lux/data/format/json.lux
@@ -6,309 +6,121 @@
(;module:
lux
(lux (codata [io])
- (control monad)
+ (control monad
+ codec
+ eq)
(data [text "Text/" Monoid<Text>]
text/format
error
- (format [json #* "JSON/" Eq<JSON> Codec<Text,JSON>])
+ [bool]
+ [char]
+ [maybe]
+ [number]
+ (format ["&" json])
(struct [vector #+ vector]
- [dict]))
+ [dict]
+ [list]))
[compiler #+ with-gensyms]
+ [macro]
(macro [ast]
[syntax #+ syntax:]
[poly #+ derived:])
- [pipe]
+ (math ["R" random])
+ pipe
test)
)
-## [Utils]
-(syntax: (reads-to-itself expr)
- (with-gensyms [g!json g!parsed g!message]
- (wrap (list (` (: (Test Unit)
- (let [(~ g!json) (~ expr)]
- (case (|> (~ g!json) JSON/encode JSON/decode)
- (#;Left (~ g!message))
- (fail (~ g!message))
-
- (#;Right (~ g!parsed))
- (if (JSON/= (~ g!json) (~ g!parsed))
- (~ (' (:: Monad<Test> wrap [])))
- (fail (format "Expression does not parse to itself: " (~ (ast;text (ast;ast-to-text expr)))
- "\n\nWhich is: " (|> (~ g!json) JSON/encode)
- "\n\nInstead, it parsed to: " (JSON/encode (~ g!parsed))))
- ))))
- )))))
-
-## [Tests]
-## (derived: (Codec<JSON,?> ;Bool))
-## (derived: (Codec<JSON,?> ;Int))
-## (derived: (Codec<JSON,?> ;Real))
-## (derived: (Codec<JSON,?> ;Char))
-## (derived: (Codec<JSON,?> ;Text))
-
-## (type: Int-List (List Int))
-## (derived: (Codec<JSON,?> ;;Int-List))
-
-## (type: Int-Maybe (Maybe Int))
-## (derived: (Codec<JSON,?> ;;Int-Maybe))
-
-## (type: Triple [Bool Int Text])
-## (derived: (Codec<JSON,?> ;;Triple))
-
-## (type: User
-## {#alive? Bool
-## #age Int
-## #name Text})
-## (derived: (Codec<JSON,?> ;;User))
-
-## (type: Options
-## (#One Bool)
-## (#Two Int)
-## (#Three Text))
-## (derived: (Codec<JSON,?> ;;Options))
-
-## (test: "Auto-generated codecs"
-## (let% [<tests> (do-template [<input> <output> <codec>]
-## [(match <output>
-## (|> <input>
-## (:: <codec> encode)
-## JSON/encode))
-## (match+ <input>
-## (should-pass (|> (JSON/decode <output>)
-## (pipe;%> Error/Monad
-## [(:: <codec> decode)]))))]
-
-## [true "true" Codec<JSON,Bool>]
-## [123 "123.0" Codec<JSON,Int>]
-## [123.45 "123.45" Codec<JSON,Real>]
-## [#"a" "\"a\"" Codec<JSON,Char>]
-## ["yolo" "\"yolo\"" Codec<JSON,Text>]
-
-## [(#;Cons 1 (#;Cons 2 (#;Cons 3 #;Nil))) "[1.0,2.0,3.0]" Codec<JSON,Int-List>]
-## [#;Nil "[]" Codec<JSON,Int-List>]
-## [(#;Some 1) "1.0" Codec<JSON,Int-Maybe>]
-## [#;None "null" Codec<JSON,Int-Maybe>]
-## [[false 456 "lol"] "[false,456.0,\"lol\"]" Codec<JSON,Triple>]
-## [{#alive? true #age 25 #name "Eduardo Julian"}
-## "{\"alive?\":true,\"age\":25.0,\"name\":\"Eduardo Julian\"}"
-## Codec<JSON,User>]
-## [(#One true) "[\"One\",true]" Codec<JSON,Options>]
-## [(#Two 123) "[\"Two\",123.0]" Codec<JSON,Options>]
-## [(#Three "yolo") "[\"Three\",\"yolo\"]" Codec<JSON,Options>]
-## )]
-## (test-all <tests>
-## )))
-
-(test: "Basics"
- (test-all (match #json;Null
- null)
-
- (match (#json;Boolean true)
- (gen-boolean true))
-
- (match (#json;Boolean false)
- (gen-boolean false))
-
- (match (#json;Number 123.45)
- (gen-number 123.45))
-
- (match (#json;String "YOLO")
- (gen-string "YOLO"))
-
- ## (match (^ (#json;Array (list (#json;Boolean true) (#json;Number 123.45) (#json;String "YOLO"))))
- ## (json [(gen-boolean true) (gen-number 123.45) (gen-string "YOLO")]))
-
- ## (match (^ (#json;Object (list ["yolo" (#json;Boolean true)]
- ## ["lol" (#json;Number 123.45)])))
- ## (json {"yolo" (gen-boolean true)
- ## "lol" (gen-number 123.45)}))
-
- (match (#;Some (#json;Boolean true))
- (get "yolo" (json {"yolo" true
- "lol" 123.45})))
-
- (match (#;Left _)
- (get "yolo" (json {})))
-
- ## (match (^ (#;Some (#json;Object (list ["lol" (#json;Number 123.45)]
- ## ["yolo" (#json;Boolean true)]))))
- ## (|> (json {"yolo" (gen-boolean true)})
- ## (set "lol" (gen-number 123.45))))
-
- (match (#;Right true)
- (get-boolean "value" (json {"value" true})))
-
- (match (#;Right 123.45)
- (get-number "value" (json {"value" 123.45})))
-
- (match (#;Right "YOLO")
- (get-string "value" (json {"value" "YOLO"})))
-
- ## (match (^ (#;Right (list (#json;Boolean true) (#json;Number 123.45) (#json;String "YOLO"))))
- ## (get-array "value" (json {"value" (json [(gen-boolean true)
- ## (gen-number 123.45)
- ## (gen-string "YOLO")])})))
-
- ## (match (^ (#;Right (list ["yolo" (#json;Boolean true)]
- ## ["lol" (#json;Number 123.45)])))
- ## (get-object "value" (json {"value" (json {"yolo" (gen-boolean true)
- ## "lol" (gen-number 123.45)})})))
-
- (match (#;Left _)
- (get-array "value" (json {})))
-
- (match (#;Left _)
- (get-array "value" (gen-boolean true)))
- ))
-
-(test: "Encoding"
- (test-all (match "null"
- (JSON/encode (json #null)))
-
- (match "123.0"
- (JSON/encode (json 123)))
-
- (match "123.46"
- (JSON/encode (json 123.46)))
-
- (match "true"
- (JSON/encode (json true)))
-
- (match "false"
- (JSON/encode (json false)))
-
- (match "\"YOLO\""
- (JSON/encode (json "YOLO")))
-
- (match "[null,123.46,true,\"YOLO\",[\"nyan\",\"cat\"]]"
- (JSON/encode (json [#null 123.46 true "YOLO" ["nyan" "cat"]])))
-
- (match "{\"foo\":\"bar\",\"baz\":null,\"quux\":[\"nyan\",{\"cat\":\"meme\"}]}"
- (JSON/encode (json {"foo" "bar"
- "baz" #null
- "quux" ["nyan" {"cat" "meme"}]})))
- ))
-
-(test: "Decoding"
- (test-all (reads-to-itself (json #null))
- (reads-to-itself (json 123))
- (reads-to-itself (json 123.46))
- (reads-to-itself (json true))
- (reads-to-itself (json false))
- (reads-to-itself (json "\tY\"OLO\n"))
- (reads-to-itself (json [#null 123.46 true "YOLO" ["nyan" "cat"]]))
- (reads-to-itself (json {"foo" "bar"
- "baz" #null
- "quux" ["nyan" {"cat" "meme"}]}))
- ))
-
-(test: "Parser"
- (test-all (should-pass (run unit
- (json #null)))
- (should-fail (run unit
- (json 123)))
-
- (match+ 123.45
- (should-pass (run real
- (json 123.45))))
- (should-fail (run real
- (json #null)))
-
- (match+ 123
- (should-pass (run int
- (json 123))))
- (should-fail (run int
- (json #null)))
-
- (match+ true
- (should-pass (run bool
- (json true))))
- (should-fail (run bool
- (json 123)))
-
- (match+ "YOLO"
- (should-pass (run text
- (json "YOLO"))))
- (should-fail (run text
- (json 123)))
-
- (match+ (^ (list "YOLO" "LOL" "MEME"))
- (should-pass (run (array text)
- (json ["YOLO" "LOL" "MEME"]))))
- (should-fail (run (array text)
- (json 123)))
-
- (match+ "LOL"
- (should-pass (run (at +1 text)
- (json ["YOLO" "LOL" "MEME"]))))
- (should-fail (run (array text)
- (json 123)))
-
- (match+ "MEME"
- (should-pass (run (field "baz" text)
- (json {"foo" "YOLO"
- "bar" "LOL"
- "baz" "MEME"}))))
- (should-fail (run (field "baz" text)
- (json 123)))
-
- (match+ (#json;Number 123.0)
- (should-pass (run any
- (json 123))))
-
- (match+ ["YOLO" "MEME"]
- (should-pass (run (seq (field "foo" text)
- (field "baz" text))
- (json {"foo" "YOLO"
- "bar" "LOL"
- "baz" "MEME"}))))
- (should-fail (run (seq (field "foo" text)
- (field "baz" text))
- (json {"foo" "YOLO"
- "bar" "LOL"})))
-
- (match+ (#;Left "YOLO")
- (should-pass (run (alt (field "foo" text)
- (field "baz" text))
- (json {"foo" "YOLO"
- "bar" "LOL"
- "baz" "MEME"}))))
- (match+ (#;Right "MEME")
- (should-pass (run (alt (field "fool" text)
- (field "baz" text))
- (json {"foo" "YOLO"
- "bar" "LOL"
- "baz" "MEME"}))))
- (should-fail (run (alt (field "fool" text)
- (field "baz" text))
- (json {"foo" "YOLO"
- "bar" "LOL"})))
-
- (match+ "YOLO"
- (should-pass (run (either (field "foo" text)
- (field "baz" text))
- (json {"foo" "YOLO"
- "bar" "LOL"
- "baz" "MEME"}))))
- (match+ "MEME"
- (should-pass (run (either (field "fool" text)
- (field "baz" text))
- (json {"foo" "YOLO"
- "bar" "LOL"
- "baz" "MEME"}))))
- (should-fail (run (either (field "fool" text)
- (field "baz" text))
- (json {"foo" "YOLO"
- "bar" "LOL"})))
-
- (match+ (#;Some "YOLO")
- (should-pass (run (opt (field "foo" text))
- (json {"foo" "YOLO"
- "bar" "LOL"
- "baz" "MEME"}))))
- (match+ #;None
- (should-pass (run (opt (field "fool" text))
- (json {"foo" "YOLO"
- "bar" "LOL"
- "baz" "MEME"}))))
- ))
+(def: gen-json
+ (R;Random &;JSON)
+ (R;rec (lambda [gen-json]
+ (do R;Monad<Random>
+ [size (:: @ map (%+ +2) R;nat)]
+ ($_ R;alt
+ (:: @ wrap [])
+ R;bool
+ R;real
+ (R;text size)
+ (R;vector size gen-json)
+ (R;dict text;Hash<Text> size (R;text size) gen-json)
+ )))))
+
+(test: "JSON"
+ [sample gen-json
+ #let [(^open "&/") &;Eq<JSON>
+ (^open "&/") &;Codec<Text,JSON>]]
+ ($_ seq
+ (assert "Every JSON is equal to itself."
+ (&/= sample sample))
+
+ (assert "Can encode/decode JSON."
+ (|> sample &/encode &/decode
+ (case> (#;Right result)
+ (&/= sample result)
+
+ (#;Left _)
+ false)))
+ ))
+
+(type: Variant
+ (#Case0 Bool)
+ (#Case1 Int)
+ (#Case2 Real))
+
+(type: Record
+ {#unit Unit
+ #bool Bool
+ #int Int
+ #real Real
+ #char Char
+ #text Text
+ #maybe (Maybe Int)
+ #list (List Int)
+ #variant Variant
+ #tuple [Int Real Char]})
+
+(def: gen-record
+ (R;Random Record)
+ (do R;Monad<Random>
+ [size (:: @ map (%+ +2) R;nat)]
+ ($_ R;seq
+ (:: @ wrap [])
+ R;bool
+ R;int
+ R;real
+ R;char
+ (R;text size)
+ (R;maybe R;int)
+ (R;list size R;int)
+ ($_ R;alt R;bool R;int R;real)
+ ($_ R;seq R;int R;real R;char)
+ )))
+
+(derived: (&;Codec<JSON,?> Record))
+
+(struct: _ (Eq Record)
+ (def: (= recL recR)
+ (and (:: bool;Eq<Bool> = (get@ #bool recL) (get@ #bool recR))
+ (;= (get@ #int recL) (get@ #int recR))
+ (=. (get@ #real recL) (get@ #real recR))
+ (:: char;Eq<Char> = (get@ #char recL) (get@ #char recR))
+ (:: text;Eq<Text> = (get@ #text recL) (get@ #text recR))
+ (:: (maybe;Eq<Maybe> number;Eq<Int>) = (get@ #maybe recL) (get@ #maybe recR))
+ (:: (list;Eq<List> number;Eq<Int>) = (get@ #list recL) (get@ #list recR))
+ (let [[tL0 tL1 tL2] (get@ #tuple recL)
+ [tR0 tR1 tR2] (get@ #tuple recR)]
+ (and (;= tL0 tR0)
+ (=. tL1 tR1)
+ (:: char;Eq<Char> = tL2 tR2)))
+ )))
+
+(test: "Polytypism"
+ [sample gen-record
+ #let [(^open "&/") Eq<Record>
+ (^open "&/") Codec<JSON,Record>]]
+ (assert "Can encode/decode arbitrary types."
+ (|> sample &/encode &/decode
+ (case> (#;Right result)
+ (&/= sample result)
+
+ (#;Left _)
+ false))))
diff --git a/stdlib/test/test/lux/data/struct/vector.lux b/stdlib/test/test/lux/data/struct/vector.lux
index 2ccfa2fc1..c3f3a706e 100644
--- a/stdlib/test/test/lux/data/struct/vector.lux
+++ b/stdlib/test/test/lux/data/struct/vector.lux
@@ -35,10 +35,8 @@
(=+ size (&;size sample))))
(assert "Can add and remove elements to vectors."
- (and (=+ (inc+ size)
- (&;size (&;add non-member sample)))
- (=+ (dec+ size)
- (&;size (&;pop sample)))))
+ (and (=+ (inc+ size) (&;size (&;add non-member sample)))
+ (=+ (dec+ size) (&;size (&;pop sample)))))
(assert "Can put and get elements into vectors."
(|> sample
@@ -49,16 +47,12 @@
(assert "Can update elements of vectors."
(|> sample
- (&;put idx non-member)
- (&;update idx inc+)
- (&;at idx)
- (default (undefined))
+ (&;put idx non-member) (&;update idx inc+)
+ (&;at idx) (default (undefined))
(=+ (inc+ non-member))))
(assert "Can safely transform to/from lists."
- (|> sample
- &;to-list &;from-list
- (&/= sample)))
+ (|> sample &;to-list &;from-list (&/= sample)))
(assert "Can identify members of a vector."
(and (not (&;member? number;Eq<Nat> sample non-member))
@@ -76,8 +70,7 @@
(assert "Applicative allows you to create singleton vectors, and apply vectors of functions to vectors of values."
(and (&/= (&;vector non-member) (&/wrap non-member))
- (&/= (&/map inc+ sample)
- (&/apply (&/wrap inc+) sample))))
+ (&/= (&/map inc+ sample) (&/apply (&/wrap inc+) sample))))
(assert "Vector concatenation is a monad."
(&/= (&/append sample other-sample)
diff --git a/stdlib/test/tests.lux b/stdlib/test/tests.lux
index 7b760c0f1..94148e1d7 100644
--- a/stdlib/test/tests.lux
+++ b/stdlib/test/tests.lux
@@ -23,7 +23,8 @@
[product]
[sum]
[text]
- [text/format]
+ (error [exception])
+ (format [json])
(struct [array]
[dict]
[list]
@@ -34,6 +35,7 @@
[vector]
[zipper]
)
+ (text [format])
)
## (codata ["_;" io]
## [env]