aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/type/opaque.lux
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/source/lux/type/opaque.lux')
-rw-r--r--stdlib/source/lux/type/opaque.lux164
1 files changed, 164 insertions, 0 deletions
diff --git a/stdlib/source/lux/type/opaque.lux b/stdlib/source/lux/type/opaque.lux
new file mode 100644
index 000000000..acd73d6a4
--- /dev/null
+++ b/stdlib/source/lux/type/opaque.lux
@@ -0,0 +1,164 @@
+(;module:
+ lux
+ (lux (control [applicative]
+ [monad #+ do Monad]
+ ["p" parser])
+ (data [text "text/" Eq<Text> Monoid<Text>]
+ ["E" error]
+ (coll [list "list/" Functor<List> Monoid<List>]))
+ [meta]
+ (meta [code]
+ ["s" syntax #+ syntax:]
+ (syntax ["cs" common]
+ (common ["csr" reader]
+ ["csw" writer])))))
+
+(def: (get k plist)
+ (All [a]
+ (-> Text (List [Text a]) (Maybe a)))
+ (case plist
+ #;Nil
+ #;None
+
+ (#;Cons [k' v] plist')
+ (if (text/= k k')
+ (#;Some v)
+ (get k plist'))))
+
+(def: (put k v plist)
+ (All [a]
+ (-> Text a (List [Text a]) (List [Text a])))
+ (case plist
+ #;Nil
+ (list [k v])
+
+ (#;Cons [k' v'] plist')
+ (if (text/= k k')
+ (#;Cons [k' v] plist')
+ (#;Cons [k' v'] (put k v plist')))))
+
+(def: (remove k plist)
+ (All [a]
+ (-> Text (List [Text a]) (List [Text a])))
+ (case plist
+ #;Nil
+ #;Nil
+
+ (#;Cons [k' v'] plist')
+ (if (text/= k k')
+ plist'
+ (#;Cons [k' v'] (remove k plist')))))
+
+(def: down-cast Text "@opaque")
+(def: up-cast Text "@repr")
+(def: macro-anns Code (' {#;macro? true}))
+
+(def: representation-name
+ (-> Text Text)
+ (|>. ($_ text/compose "{" kind "@" module "}")
+ (let [[module kind] (ident-for #;;Representation)])))
+
+(def: (install-casts' this-module-name name type-vars)
+ (-> Text Text (List Text) (Meta Unit))
+ (do meta;Monad<Meta>
+ [this-module (meta;find-module this-module-name)
+ #let [type-varsC (list/map code;local-symbol type-vars)
+ opaque-declaration (` ((~ (code;local-symbol name)) (~@ type-varsC)))
+ representation-declaration (` ((~ (code;local-symbol (representation-name name))) (~@ type-varsC)))
+ this-module (|> this-module
+ (update@ #;defs (put down-cast (: Def
+ [Macro macro-anns
+ (function [tokens]
+ (case tokens
+ (^ (list value))
+ (wrap (list (` ((: (All [(~@ type-varsC)]
+ (-> (~ representation-declaration) (~ opaque-declaration)))
+ (|>. :!!))
+ (~ value)))))
+
+ _
+ (meta;fail ($_ text/compose "Wrong syntax for " down-cast))))])))
+ (update@ #;defs (put up-cast (: Def
+ [Macro macro-anns
+ (function [tokens]
+ (case tokens
+ (^ (list value))
+ (wrap (list (` ((: (All [(~@ type-varsC)]
+ (-> (~ opaque-declaration) (~ representation-declaration)))
+ (|>. :!!))
+ (~ value)))))
+
+ _
+ (meta;fail ($_ text/compose "Wrong syntax for " up-cast))))]))))]]
+ (function [compiler]
+ (#E;Success [(update@ #;modules (put this-module-name this-module) compiler)
+ []]))))
+
+(def: (un-install-casts' this-module-name)
+ (-> Text (Meta Unit))
+ (do meta;Monad<Meta>
+ [this-module (meta;find-module this-module-name)
+ #let [this-module (|> this-module
+ (update@ #;defs (remove down-cast))
+ (update@ #;defs (remove up-cast)))]]
+ (function [compiler]
+ (#E;Success [(update@ #;modules (put this-module-name this-module) compiler)
+ []]))))
+
+(syntax: #hidden (install-casts [name s;local-symbol]
+ [type-vars (s;tuple (p;some s;local-symbol))])
+ (do @
+ [this-module-name meta;current-module-name
+ ?down-cast (meta;find-macro [this-module-name down-cast])
+ ?up-cast (meta;find-macro [this-module-name up-cast])]
+ (case [?down-cast ?up-cast]
+ [#;None #;None]
+ (do @
+ [_ (install-casts' this-module-name name type-vars)]
+ (wrap (list)))
+
+ _
+ (meta;fail ($_ text/compose
+ "Cannot temporarily define casting functions ("
+ down-cast " & " up-cast
+ ") because definitions like that already exist.")))))
+
+(syntax: #hidden (un-install-casts)
+ (do meta;Monad<Meta>
+ [this-module-name meta;current-module-name
+ ?down-cast (meta;find-macro [this-module-name down-cast])
+ ?up-cast (meta;find-macro [this-module-name up-cast])]
+ (case [?down-cast ?up-cast]
+ [(#;Some _) (#;Some _)]
+ (do @
+ [_ (un-install-casts' this-module-name)]
+ (wrap (list)))
+
+ _
+ (meta;fail ($_ text/compose
+ "Cannot un-define casting functions ("
+ down-cast " & " up-cast
+ ") because they do not exist.")))))
+
+(def: declaration
+ (s;Syntax [Text (List Text)])
+ (p;either (s;form (p;seq s;local-symbol (p;some s;local-symbol)))
+ (p;seq s;local-symbol (:: p;Monad<Parser> wrap (list)))))
+
+(syntax: #export (opaque: [export csr;export]
+ [[name type-vars] declaration]
+ [annotations (p;default cs;empty-annotations csr;annotations)]
+ representation-type
+ [primitives (p;some s;any)])
+ (let [hidden-name (code;local-symbol (representation-name name))
+ type-varsC (list/map code;local-symbol type-vars)
+ opaque-declaration (` ((~ (code;local-symbol name)) (~@ type-varsC)))
+ representation-declaration (` ((~ hidden-name) (~@ type-varsC)))]
+ (wrap (list& (` (type: (~@ (csw;export export)) (~ opaque-declaration)
+ (~ (csw;annotations annotations))
+ (primitive (~ hidden-name) [(~@ type-varsC)])))
+ (` (type: (~@ (csw;export export)) (~ representation-declaration)
+ (~ representation-type)))
+ (` (install-casts (~ (code;local-symbol name)) [(~@ type-varsC)]))
+ (list/compose primitives
+ (list (` (un-install-casts))))))))