aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/paradigm/object.lux
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--stdlib/source/lux/paradigm/object.lux380
1 files changed, 334 insertions, 46 deletions
diff --git a/stdlib/source/lux/paradigm/object.lux b/stdlib/source/lux/paradigm/object.lux
index f215e4071..c7cdcb4d3 100644
--- a/stdlib/source/lux/paradigm/object.lux
+++ b/stdlib/source/lux/paradigm/object.lux
@@ -6,6 +6,7 @@
text/format
[product]
maybe
+ [ident #+ "Ident/" Eq<Ident>]
(coll [list "L/" Functor<List> Fold<List> Monoid<List>]
[set #+ Set]))
[macro #+ Monad<Lux> "Lux/" Monad<Lux>]
@@ -14,12 +15,299 @@
(syntax ["cs" common]
(common ["csr" reader]
["csw" writer])))
- [type])
- (. ["./c" common]
- ["./n" notation]
- ["./i" inheritance]
- ["./m" method]))
+ [type]))
+## [Common]
+(type: Declaration
+ [Text (List Text)])
+
+(type: Alias Text)
+
+(def: default-alias Alias "@")
+
+(def: (var-set vars)
+ (-> (List Text) (Set Text))
+ (set;from-list text;Hash<Text> vars))
+
+(def: (unique-type-vars parser)
+ (-> (s;Syntax (List Text)) (s;Syntax (List Text)))
+ (do p;Monad<Parser>
+ [raw parser
+ _ (p;assert "Cannot repeat the names of type variables/parameters."
+ (n.= (set;size (var-set raw))
+ (list;size raw)))]
+ (wrap raw)))
+
+(def: (safe-type-vars exclusions)
+ (-> (Set Text) (s;Syntax Text))
+ (do p;Monad<Parser>
+ [raw s;local-symbol
+ _ (p;assert "Cannot re-use names between method type-variables and interface type-parameters."
+ (|> raw (set;member? exclusions) not))]
+ (wrap raw)))
+
+(def: declarationS
+ (s;Syntax Declaration)
+ (p;either (s;form (p;seq s;local-symbol
+ (unique-type-vars (p;some s;local-symbol))))
+ (p;seq s;local-symbol
+ (p/wrap (list)))))
+
+(def: aliasS
+ (s;Syntax Alias)
+ (|> s;local-symbol
+ (p;after (s;this (' #as)))
+ (p;default default-alias)))
+
+(def: (ancestor-inputs ancestors)
+ (-> (List Ident) (List Code))
+ (if (list;empty? ancestors)
+ (list)
+ (|> (list;size ancestors)
+ n.dec
+ (list;n.range +0)
+ (L/map (|>. %n (format "ancestor") code;local-symbol)))))
+
+## [Methods]
+(type: Method
+ {#type-vars (List Text)
+ #name Text
+ #inputs (List Code)
+ #output Code})
+
+(def: (method exclusions)
+ (-> (Set Text) (s;Syntax Method))
+ (s;form ($_ p;seq
+ (p;either (unique-type-vars (s;tuple (p;some (safe-type-vars exclusions))))
+ (p/wrap (list)))
+ s;local-symbol
+ (s;tuple (p;some s;any))
+ s;any)))
+
+(def: (declarationM g!self (^open))
+ (-> Code Method Code)
+ (let [g!type-vars (L/map code;local-symbol type-vars)
+ g!method (code;local-symbol name)]
+ (` (: (All [(~@ g!type-vars)]
+ (-> (~@ inputs) (~ g!self) (~ output)))
+ (~ g!method)))))
+
+(def: (definition export [interface parameters] g!self-object g!ext g!states (^open))
+ (-> (Maybe cs;Export) Declaration Code Code (List Code) Method Code)
+ (let [g!method (code;local-symbol name)
+ g!parameters (L/map code;local-symbol parameters)
+ g!type-vars (L/map code;local-symbol type-vars)
+ g!_temp (code;symbol ["" "_temp"])
+ g!_object (code;symbol ["" "_object"])
+ g!_behavior (code;symbol ["" "_behavior"])
+ g!_state (code;symbol ["" "_state"])
+ g!_extension (code;symbol ["" "_extension"])
+ g!_args (L/map (|>. product;left nat-to-int %i (format "_") code;local-symbol)
+ (list;enumerate inputs))
+ g!destructuring (L/fold (function [_ g!bottom] (` [(~ g!_temp) (~ g!_temp) (~ g!bottom)]))
+ (` [(~ g!_behavior) (~ g!_state) (~ g!_extension)])
+ (default g!states (list;tail g!states)))]
+ (` (def: (~@ (csw;export export)) ((~ g!method) (~@ g!_args) (~ g!_object))
+ (All [(~@ g!parameters) (~ g!ext) (~@ g!states) (~@ g!type-vars)]
+ (-> (~@ inputs) (~ g!self-object) (~ output)))
+ (let [(~ g!destructuring) (~ g!_object)]
+ (:: (~ g!_behavior) (~ g!method) (~@ g!_args) (~ g!_object)))))))
+
+## [Inheritance]
+(type: Reference
+ [Ident (List Code)])
+
+(def: no-parent Ident ["" ""])
+
+(def: (no-parent? parent)
+ (-> Ident Bool)
+ (Ident/= no-parent parent))
+
+(def: (with-interface parent interface)
+ (-> Ident Ident cs;Annotations cs;Annotations)
+ (|>. (#;Cons [(ident-for #;;interface-name)
+ (code;tag interface)])
+ (#;Cons [(ident-for #;;interface-parent)
+ (code;tag parent)])))
+
+(def: (with-class interface parent class)
+ (-> Ident Ident Ident cs;Annotations cs;Annotations)
+ (|>. (#;Cons [(ident-for #;;class-interface)
+ (code;tag interface)])
+ (#;Cons [(ident-for #;;class-parent)
+ (code;tag parent)])
+ (#;Cons [(ident-for #;;class-name)
+ (code;tag class)])))
+
+(do-template [<name> <name-tag> <parent-tag> <desc>]
+ [(def: (<name> name)
+ (-> Ident (Lux [Ident (List Ident)]))
+ (do Monad<Lux>
+ [name (macro;normalize name)
+ [_ annotations _] (macro;find-def name)]
+ (case [(macro;get-ident-ann (ident-for <name-tag>) annotations)
+ (macro;get-ident-ann (ident-for <parent-tag>) annotations)]
+ [(#;Some real-name) (#;Some parent)]
+ (if (Ident/= no-parent parent)
+ (wrap [real-name (list)])
+ (do @
+ [[_ ancestors] (<name> parent)]
+ (wrap [real-name (#;Cons parent ancestors)])))
+
+ _
+ (macro;fail (format "Wrong format for " <desc> " lineage.")))))]
+
+ [interfaceN #;;interface-name #;;interface-parent "interface"]
+ [classN #;;class-name #;;class-parent "class"]
+ )
+
+(def: (extract newT)
+ (-> Type (Lux [Nat (List Type)]))
+ (loop [depth +0
+ currentT newT]
+ (case currentT
+ (#;UnivQ _ bodyT)
+ (recur (n.inc depth) bodyT)
+
+ (#;Function inputT outputT)
+ (let [[stateT+ objectT] (type;flatten-function currentT)]
+ (Lux/wrap [depth stateT+]))
+
+ _
+ (macro;fail (format "Cannot extract inheritance from type: " (type;to-text newT))))))
+
+(def: (specialize mappings typeC)
+ (-> (List Code) Code Code)
+ (case (list;size mappings)
+ +0
+ typeC
+
+ size
+ (|> (n.dec size)
+ (list;n.range +0)
+ (L/map (|>. (n.* +2) n.inc code;nat (~) #;Bound (`)))
+ (list;zip2 (list;reverse mappings))
+ (L/fold (function [[mappingC boundC] genericC]
+ (code;replace boundC mappingC genericC))
+ typeC))))
+
+(def: referenceS
+ (s;Syntax Reference)
+ (p;either (s;form (p;seq s;symbol
+ (p;some s;any)))
+ (p;seq s;symbol
+ (p/wrap (list)))))
+
+(do-template [<name> <keyword>]
+ [(def: <name>
+ (s;Syntax Reference)
+ (|> referenceS
+ (p;after (s;this (' <keyword>)))))]
+
+ [extension #super]
+ [inheritance #super]
+ )
+
+## [Notation]
+## Utils
+(def: (nest ancestors bottom)
+ (-> (List Code) Code Code)
+ (L/fold (function [[level _] g!bottom]
+ (let [g!_behavior' (code;local-symbol (format "_behavior" (%n level)))
+ g!_state' (code;local-symbol (format "_state" (%n level)))]
+ (` [(~ g!_behavior') (~ g!_state') (~ g!bottom)])))
+ bottom
+ (list;enumerate ancestors)))
+
+## Names
+(do-template [<name> <category>]
+ [(def: (<name> base)
+ (-> Text Text)
+ (|> base (format <category> "@")))]
+
+ [newN "new"]
+ [getN "get"]
+ [setN "set"]
+ [updateN "update"]
+ )
+
+(do-template [<name> <category>]
+ [(def: (<name> raw)
+ (-> Text Text)
+ (format raw "//OOP:" <category>))]
+
+ [signatureN "Signature"]
+ [stateN "State"]
+ [structN "Struct"]
+ )
+
+(def: (getterN export interface g!parameters g!ext g!child ancestors)
+ (-> (Maybe cs;Export) Text (List Code) Code Code (List Ident)
+ Code)
+ (let [g!get (code;local-symbol (getN interface))
+ g!interface (code;local-symbol interface)
+ g!_object (' _object)
+ g!_behavior (' _behavior)
+ g!_state (' _state)
+ g!_extension (' _extension)
+ g!ancestors (ancestor-inputs ancestors)
+ g!object (` ((~ g!interface) (~@ g!parameters) (~ g!ext) (~@ g!ancestors) (~ g!child)))
+ g!tear-down (nest g!ancestors
+ (` [(~ g!_behavior) (~ g!_state) (~ g!_extension)]))]
+ (` (def: (~@ (csw;export export)) ((~ g!get) (~ g!_object))
+ (All [(~@ g!parameters) (~ g!ext) (~@ g!ancestors) (~ g!child)]
+ (-> (~ g!object) (~ g!child)))
+ (let [(~ g!tear-down) (~ g!_object)]
+ (~ g!_state))))))
+
+(def: (setterN export interface g!parameters g!ext g!child ancestors)
+ (-> (Maybe cs;Export) Text (List Code) Code Code (List Ident)
+ Code)
+ (let [g!set (code;local-symbol (setN interface))
+ g!interface (code;local-symbol interface)
+ g!_object (' _object)
+ g!_behavior (' _behavior)
+ g!_state (' _state)
+ g!_extension (' _extension)
+ g!_input (' _input)
+ g!ancestors (ancestor-inputs ancestors)
+ g!object (` ((~ g!interface) (~@ g!parameters) (~ g!ext) (~@ g!ancestors) (~ g!child)))
+ g!tear-down (nest g!ancestors
+ (` [(~ g!_behavior) (~ g!_state) (~ g!_extension)]))
+ g!build-up (nest g!ancestors
+ (` [(~ g!_behavior) (~ g!_input) (~ g!_extension)]))]
+ (` (def: (~@ (csw;export export))
+ ((~ g!set) (~ g!_input) (~ g!_object))
+ (All [(~@ g!parameters) (~ g!ext) (~@ g!ancestors) (~ g!child)]
+ (-> (~ g!child) (~ g!object) (~ g!object)))
+ (let [(~ g!tear-down) (~ g!_object)]
+ (~ g!build-up))))))
+
+(def: (updaterN export interface g!parameters g!ext g!child ancestors)
+ (-> (Maybe cs;Export) Text (List Code) Code Code (List Ident)
+ Code)
+ (let [g!update (code;local-symbol (updateN interface))
+ g!interface (code;local-symbol interface)
+ g!_object (' _object)
+ g!_behavior (' _behavior)
+ g!_state (' _state)
+ g!_extension (' _extension)
+ g!_change (' _change)
+ g!ancestors (ancestor-inputs ancestors)
+ g!object (` ((~ g!interface) (~@ g!parameters) (~ g!ext) (~@ g!ancestors) (~ g!child)))
+ g!tear-down (nest g!ancestors
+ (` [(~ g!_behavior) (~ g!_state) (~ g!_extension)]))
+ g!build-up (nest g!ancestors
+ (` [(~ g!_behavior) ((~ g!_change) (~ g!_state)) (~ g!_extension)]))]
+ (` (def: (~@ (csw;export export))
+ ((~ g!update) (~ g!_change) (~ g!_object))
+ (All [(~@ g!parameters) (~ g!ext) (~@ g!ancestors) (~ g!child)]
+ (-> (-> (~ g!child) (~ g!child))
+ (-> (~ g!object) (~ g!object))))
+ (let [(~ g!tear-down) (~ g!_object)]
+ (~ g!build-up))))))
+
+## [Macros]
(def: (type-to-code type)
(-> Type (Lux Code))
(case type
@@ -71,37 +359,37 @@
(macro;fail (format "Cannot convert type to code: " (type;to-text type)))))
(syntax: #export (interface: [export csr;export]
- [(^@ decl [interface parameters]) ./c;declaration]
- [?extends (p;opt ./i;extension)]
- [alias ./c;alias]
+ [(^@ decl [interface parameters]) declarationS]
+ [?extends (p;opt extension)]
+ [alias aliasS]
[annotations (p;default cs;empty-annotations csr;annotations)]
- [methods (p;many (./m;method (./c;var-set parameters)))])
+ [methods (p;many (method (var-set parameters)))])
(macro;with-gensyms [g!self-class g!child g!ext]
(do @
[module macro;current-module-name
[parent ancestors mappings] (: (Lux [Ident (List Ident) (List Code)])
(case ?extends
#;None
- (wrap [./i;no-parent (list) (list)])
+ (wrap [no-parent (list) (list)])
(#;Some [super mappings])
(do @
- [[parent ancestors] (./i;interface super)]
+ [[parent ancestors] (interfaceN super)]
(wrap [parent (list& parent ancestors) mappings]))))
- #let [g!signature (code;local-symbol (./n;signature interface))
+ #let [g!signature (code;local-symbol (signatureN interface))
g!interface (code;local-symbol interface)
g!parameters (L/map code;local-symbol parameters)
g!self-ref (if (list;empty? g!parameters)
(list g!interface)
(list))
- g!interface-def (if (./i;no-parent? parent)
+ g!interface-def (if (no-parent? parent)
(let [g!recur (` ((~ g!interface) (~@ g!parameters) (~ g!ext) (~ g!child)))]
(` (Ex (~@ g!self-ref) [(~ g!ext) (~ g!child)]
[((~ g!signature) (~@ g!parameters) (~ g!recur))
(~ g!child)
(~ g!ext)])))
(let [g!parent (code;symbol parent)
- g!ancestors (./c;ancestor-inputs ancestors)
+ g!ancestors (ancestor-inputs ancestors)
g!recur (` ((~ g!interface) (~@ g!parameters) (~ g!ext) (~@ g!ancestors) (~ g!child)))]
(` (Ex (~@ g!self-ref) [(~ g!ext) (~@ g!ancestors) (~ g!child)]
((~ g!parent) (~@ mappings)
@@ -112,78 +400,78 @@
(wrap (list& (` (sig: (~@ (csw;export export))
((~ g!signature) (~@ g!parameters) (~ g!self-class))
(~@ (let [de-alias (code;replace (code;local-symbol alias) g!self-class)]
- (L/map (|>. (update@ #./m;inputs (L/map de-alias))
- (update@ #./m;output de-alias)
- (./m;declaration g!self-class))
+ (L/map (|>. (update@ #inputs (L/map de-alias))
+ (update@ #output de-alias)
+ (declarationM g!self-class))
methods)))))
(` (type: (~@ (csw;export export)) ((~ g!interface) (~@ g!parameters))
(~ (|> annotations
- (./i;with-interface parent [module interface])
+ (with-interface parent [module interface])
csw;annotations))
(~ g!interface-def)))
- (./n;getter export interface g!parameters g!ext g!child ancestors)
- (./n;setter export interface g!parameters g!ext g!child ancestors)
- (./n;updater export interface g!parameters g!ext g!child ancestors)
+ (getterN export interface g!parameters g!ext g!child ancestors)
+ (setterN export interface g!parameters g!ext g!child ancestors)
+ (updaterN export interface g!parameters g!ext g!child ancestors)
- (let [g!ancestors (./c;ancestor-inputs ancestors)
+ (let [g!ancestors (ancestor-inputs ancestors)
g!states (L/append g!ancestors (list g!child))
g!self-object (` ((~ g!interface) (~@ g!parameters) (~ g!ext) (~@ g!ancestors) (~ g!child)))
de-alias (code;replace (code;symbol ["" alias]) g!self-object)]
- (L/map (|>. (update@ #./m;inputs (L/map de-alias))
- (update@ #./m;output de-alias)
- (./m;definition export decl g!self-object g!ext g!states))
+ (L/map (|>. (update@ #inputs (L/map de-alias))
+ (update@ #output de-alias)
+ (definition export decl g!self-object g!ext g!states))
methods))))
)))
(syntax: #export (class: [export csr;export]
- [[instance parameters] ./c;declaration]
+ [[instance parameters] declarationS]
[annotations (p;default cs;empty-annotations csr;annotations)]
- [[interface interface-mappings] ./i;reference]
- [super (p;opt ./i;inheritance)]
+ [[interface interface-mappings] referenceS]
+ [super (p;opt inheritance)]
state-type
[impls (p;many s;any)])
(macro;with-gensyms [g!init g!extension]
(do @
[module macro;current-module-name
- [interface _] (./i;interface interface)
+ [interface _] (interfaceN interface)
[parent ancestors parent-mappings] (: (Lux [Ident (List Ident) (List Code)])
(case super
(#;Some [super-class super-mappings])
(do @
- [[parent ancestors] (./i;class super-class)]
+ [[parent ancestors] (classN super-class)]
(wrap [parent ancestors super-mappings]))
-
+
#;None
- (wrap [./i;no-parent (list) (list)])))
+ (wrap [no-parent (list) (list)])))
g!inheritance (: (Lux (List Code))
- (if (./i;no-parent? parent)
+ (if (no-parent? parent)
(wrap (list))
(do @
- [newT (macro;find-def-type (product;both id ./n;new parent))
- [depth rawT+] (./i;extract newT)
+ [newT (macro;find-def-type (product;both id newN parent))
+ [depth rawT+] (extract newT)
codeT+ (M;map @ type-to-code rawT+)]
- (wrap (L/map (./i;specialize parent-mappings) codeT+)))))
+ (wrap (L/map (specialize parent-mappings) codeT+)))))
#let [g!parameters (L/map code;local-symbol parameters)
-
- g!state (code;local-symbol (./n;state instance))
- g!struct (code;local-symbol (./n;struct instance))
+
+ g!state (code;local-symbol (stateN instance))
+ g!struct (code;local-symbol (structN instance))
g!class (code;local-symbol instance)
- g!signature (code;symbol (product;both id ./n;signature interface))
+ g!signature (code;symbol (product;both id signatureN interface))
g!interface (code;symbol interface)
- g!parent-structs (if (./i;no-parent? parent)
+ g!parent-structs (if (no-parent? parent)
(list)
- (L/map (|>. (product;both id ./n;struct) code;symbol) (list& parent ancestors)))]
+ (L/map (|>. (product;both id structN) code;symbol) (list& parent ancestors)))]
g!parent-inits (M;map @ (function [_] (macro;gensym "parent-init"))
g!parent-structs)
#let [g!full-init (L/fold (function [[parent-struct parent-state] child]
(` [(~ parent-struct) (~ parent-state) (~ child)]))
(` [(~ g!struct) (~ g!init) []])
(list;zip2 g!parent-structs g!parent-inits))
- g!new (code;local-symbol (./n;new instance))
+ g!new (code;local-symbol (newN instance))
g!recur (` ((~ g!class) (~@ g!parameters) (~ g!extension)))
g!rec (if (list;empty? g!parameters)
(list (' #rec))
@@ -194,10 +482,10 @@
(` (type: (~@ (csw;export export)) (~@ g!rec) ((~ g!class) (~@ g!parameters))
(~ (|> annotations
- (./i;with-class interface parent [module instance])
+ (with-class interface parent [module instance])
csw;annotations))
(Ex [(~ g!extension)]
- (~ (if (./i;no-parent? parent)
+ (~ (if (no-parent? parent)
(` ((~ g!interface) (~@ interface-mappings)
(~ g!extension)
((~ g!state) (~@ g!parameters))))
@@ -215,7 +503,7 @@
(~@ g!inheritance)
((~ g!state) (~@ g!parameters)))))
(~@ impls)))
-
+
(` (def: (~@ (csw;export export)) ((~ g!new) (~@ g!parent-inits) (~ g!init))
(All [(~@ g!parameters)]
(-> (~@ g!inheritance)