aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/macro/poly/equality.lux
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/source/lux/macro/poly/equality.lux')
-rw-r--r--stdlib/source/lux/macro/poly/equality.lux150
1 files changed, 150 insertions, 0 deletions
diff --git a/stdlib/source/lux/macro/poly/equality.lux b/stdlib/source/lux/macro/poly/equality.lux
new file mode 100644
index 000000000..4cf8b2de0
--- /dev/null
+++ b/stdlib/source/lux/macro/poly/equality.lux
@@ -0,0 +1,150 @@
+(.module:
+ lux
+ (lux (control [monad #+ do Monad]
+ ["eq" equality]
+ ["p" parser])
+ (data [text "text/" Monoid<Text>]
+ text/format
+ (coll [list "list/" Monad<List>]
+ [sequence]
+ [array]
+ [queue]
+ (set ["set" unordered])
+ (dictionary ["dict" unordered #+ Dict])
+ (tree [rose]))
+ [number "nat/" Codec<Text,Nat>]
+ [product]
+ [bool]
+ [maybe])
+ (time ["du" duration]
+ ["da" date]
+ ["i" instant])
+ [macro]
+ (macro [code]
+ [syntax #+ syntax: Syntax]
+ (syntax [common])
+ [poly #+ poly:])
+ (type [unit])
+ (lang [type])
+ ))
+
+## [Derivers]
+(poly: #export Eq<?>
+ (`` (do @
+ [#let [g!_ (code.local-symbol "_____________")]
+ *env* poly.env
+ inputT poly.peek
+ #let [@Eq (: (-> Type Code)
+ (function (_ type)
+ (` (eq.Eq (~ (poly.to-code *env* type))))))]]
+ ($_ p.either
+ ## Basic types
+ (~~ (do-template [<matcher> <eq>]
+ [(do @
+ [_ <matcher>]
+ (wrap (` (: (~ (@Eq inputT))
+ <eq>))))]
+
+ [(poly.this Top) (function ((~ g!_) (~ g!_) (~ g!_)) true)]
+ [(poly.like Bool) bool.Eq<Bool>]
+ [(poly.like Nat) number.Eq<Nat>]
+ [(poly.like Int) number.Eq<Int>]
+ [(poly.like Deg) number.Eq<Deg>]
+ [(poly.like Frac) number.Eq<Frac>]
+ [(poly.like Text) text.Eq<Text>]))
+ ## Composite types
+ (~~ (do-template [<name> <eq>]
+ [(do @
+ [[_ argC] (poly.apply (p.seq (poly.this <name>)
+ Eq<?>))]
+ (wrap (` (: (~ (@Eq inputT))
+ (<eq> (~ argC))))))]
+
+ [.Maybe maybe.Eq<Maybe>]
+ [.List list.Eq<List>]
+ [sequence.Sequence sequence.Eq<Sequence>]
+ [.Array array.Eq<Array>]
+ [queue.Queue queue.Eq<Queue>]
+ [set.Set set.Eq<Set>]
+ [rose.Tree rose.Eq<Tree>]
+ ))
+ (do @
+ [[_ _ valC] (poly.apply ($_ p.seq
+ (poly.this dict.Dict)
+ poly.any
+ Eq<?>))]
+ (wrap (` (: (~ (@Eq inputT))
+ (dict.Eq<Dict> (~ valC))))))
+ ## Models
+ (~~ (do-template [<type> <eq>]
+ [(do @
+ [_ (poly.this <type>)]
+ (wrap (` (: (~ (@Eq inputT))
+ <eq>))))]
+
+ [du.Duration du.Eq<Duration>]
+ [i.Instant i.Eq<Instant>]
+ [da.Date da.Eq<Date>]
+ [da.Day da.Eq<Day>]
+ [da.Month da.Eq<Month>]))
+ (do @
+ [_ (poly.apply (p.seq (poly.this unit.Qty)
+ poly.any))]
+ (wrap (` (: (~ (@Eq inputT))
+ unit.Eq<Qty>))))
+ ## Variants
+ (do @
+ [members (poly.variant (p.many Eq<?>))
+ #let [g!_ (code.local-symbol "_____________")
+ g!left (code.local-symbol "_____________left")
+ g!right (code.local-symbol "_____________right")]]
+ (wrap (` (: (~ (@Eq inputT))
+ (function ((~ g!_) (~ g!left) (~ g!right))
+ (case [(~ g!left) (~ g!right)]
+ (~+ (list/join (list/map (function (_ [tag g!eq])
+ (list (` [((~ (code.nat tag)) (~ g!left))
+ ((~ (code.nat tag)) (~ g!right))])
+ (` ((~ g!eq) (~ g!left) (~ g!right)))))
+ (list.enumerate members))))
+ (~ g!_)
+ false))))))
+ ## Tuples
+ (do @
+ [g!eqs (poly.tuple (p.many Eq<?>))
+ #let [g!_ (code.local-symbol "_____________")
+ indices (|> (list.size g!eqs) dec (list.n/range +0))
+ g!lefts (list/map (|>> nat/encode (text/compose "left") code.local-symbol) indices)
+ g!rights (list/map (|>> nat/encode (text/compose "right") code.local-symbol) indices)]]
+ (wrap (` (: (~ (@Eq inputT))
+ (function ((~ g!_) [(~+ g!lefts)] [(~+ g!rights)])
+ (and (~+ (|> (list.zip3 g!eqs g!lefts g!rights)
+ (list/map (function (_ [g!eq g!left g!right])
+ (` ((~ g!eq) (~ g!left) (~ g!right)))))))))))))
+ ## Type recursion
+ (do @
+ [[g!self bodyC] (poly.recursive Eq<?>)
+ #let [g!_ (code.local-symbol "_____________")]]
+ (wrap (` (: (~ (@Eq inputT))
+ (eq.rec (.function ((~ g!_) (~ g!self))
+ (~ bodyC)))))))
+ poly.recursive-self
+ ## Type applications
+ (do @
+ [[funcC argsC] (poly.apply (p.seq Eq<?> (p.many Eq<?>)))]
+ (wrap (` ((~ funcC) (~+ argsC)))))
+ ## Bound type-vars
+ poly.bound
+ ## Polymorphism
+ (do @
+ [[funcC varsC bodyC] (poly.polymorphic Eq<?>)]
+ (wrap (` (: (All [(~+ varsC)]
+ (-> (~+ (list/map (|>> (~) eq.Eq (`)) varsC))
+ (eq.Eq ((~ (poly.to-code *env* inputT)) (~+ varsC)))))
+ (function ((~ funcC) (~+ varsC))
+ (~ bodyC))))))
+ poly.recursive-call
+ ## If all else fails...
+ (|> poly.any
+ (:: @ map (|>> %type (format "Cannot create Eq for: ") p.fail))
+ (:: @ join))
+ ))))