Skip to content

Commit 5773d9c

Browse files
authored
Support for reify* form (#550)
* Support for reify* form * Some small things * Re-re-ify * Type check * r e f a c t o r * Do this thing * More tests * Do a test * proper-tee * mem-ber * Remove support for class/static methods on reify forms * Test xfer form meta * Logic is hard * Remove unnecessary lint suppression
1 parent e5187fa commit 5773d9c

File tree

8 files changed

+1481
-335
lines changed

8 files changed

+1481
-335
lines changed

Pipfile.lock

Lines changed: 143 additions & 154 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/basilisp/core.lpy

Lines changed: 75 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4544,7 +4544,7 @@
45444544
;;;;;;;;;;;;;;;;
45454545

45464546
(defn ^:private collect-methods
4547-
"Collect method and interface declarations for `deftype` and `defrecord`
4547+
"Collect method and interface declarations for `deftype`, `defrecord`, and `reify`
45484548
into a map containing `:interfaces` and `:methods` keys."
45494549
[method-impls]
45504550
(group-by (fn [v]
@@ -4574,18 +4574,28 @@
45744574

45754575
Interface or protocol implementations are declared as the name of the
45764576
interface or protocol as a symbol, followed by 1 or more method
4577-
definitions for that interface. Types are not required to declare
4578-
any interface implementations. Types which do declare interface
4579-
implementations are required to implement all interface methods. Failing
4580-
to implement all interface methods is a compile time error. Types
4581-
implementing `object` are not required to implement all `object` methods.
4577+
definitions for that interface. Types are not required to declare any
4578+
interface implementations. Types which do declare interface implementations
4579+
are required to implement all interface methods. Failing to implement all
4580+
interface methods is a compile time error. Types implementing `object` are
4581+
not required to implement all `object` methods.
45824582

45834583
Method declarations should appear as:
45844584

4585+
(method-name [arg1] & body)
45854586
(method-name [arg1 arg2 ...] & body)
45864587

4587-
Unlike in Clojure, interface and protocol methods are permitted to
4588-
include variadic arguments.
4588+
Unlike in Clojure, interface and protocol methods are permitted to include
4589+
variadic arguments. Single-arity methods may also declare support for
4590+
keyword arguments using either the `:apply` or `:collect` strategy on the
4591+
`:kwargs` metadata on the method name. Methods may be declared as static
4592+
(using the `:staticmethod`) or class methods (using the `:classmethod`)
4593+
metadata on the the name. Both static methods and class methods can be
4594+
declared with multiple arities or may be defined with a single arity and
4595+
keyword arguments. Finally, single-arity methods may be declared as Python
4596+
properties using the `:property` metadata on the method name. These facilities
4597+
are provided as a means to interoperate with Python code and their use is
4598+
discouraged in pure Basilisp code.
45894599

45904600
Type objects are created with sensible `object` defaults as by `attrs`.
45914601
New types may override `object` defaults. An `__init__` function is
@@ -4612,6 +4622,57 @@
46124622
(def ~ctor-name ~type-name)
46134623
~type-name)))
46144624

4625+
(defmacro reify
4626+
"Create a new Python object of an anonymous type which implements 0 or more
4627+
Python interfaces or Basilisp protocols.
4628+
4629+
Unlike types created via `deftype`, `reify` returns an object which implements
4630+
the named interfaces using the implementations provided. You may not provide
4631+
fields as such to `reify`, though `reify` closes over any local names defined
4632+
in the same lexical context. These fields may serve as private fields of the
4633+
created object.
4634+
4635+
Interface or protocol implementations are declared as the name of the
4636+
interface or protocol as a symbol, followed by 1 or more method
4637+
definitions for that interface. Types are not required to declare any
4638+
interface implementations. Types which do declare interface implementations
4639+
are required to implement all interface methods. Failing to implement all
4640+
interface methods is a compile time error. Types implementing `object` are
4641+
not required to implement all `object` methods.
4642+
4643+
Method declarations should appear as:
4644+
4645+
(method-name [arg1] & body)
4646+
(method-name [arg1 arg2 ...] & body)
4647+
4648+
Unlike in Clojure, interface and protocol methods are permitted to
4649+
include variadic arguments. Single-arity methods may also declare support for
4650+
keyword arguments using either the `:apply` or `:collect` strategy on the
4651+
`:kwargs` metadata on the method name. Finally, single-arity methods may be
4652+
declared as Python properties using the `:property` metadata on the method
4653+
name. These facilities are provided as a means to interoperate with Python
4654+
code and their use is discouraged in pure Basilisp code.
4655+
4656+
`reify` does not support class method or static method members and attempting
4657+
to declare `reify` members as class or static members will result in a
4658+
compile time error.
4659+
4660+
Type objects are created with sensible `object` defaults as by `attrs`.
4661+
New types may override `object` defaults.
4662+
4663+
Reified objects always implement `basilisp.lang.interfaces/IWithMeta` and
4664+
transfer the metadata from the form to the created object.
4665+
4666+
Methods must supply a `this` or `self` parameter. `recur` special forms
4667+
used in the body of a method should not include that parameter, as it
4668+
will be supplied automatically."
4669+
[& method-impls]
4670+
(let [{:keys [interfaces methods]} (collect-methods method-impls)]
4671+
(with-meta
4672+
`(reify* :implements [~@interfaces python/object]
4673+
~@methods)
4674+
(meta &form))))
4675+
46154676
;;;;;;;;;;;;;
46164677
;; Records ;;
46174678
;;;;;;;;;;;;;
@@ -4677,14 +4738,15 @@
46774738

46784739
Interface or protocol implementations are declared as the name of the
46794740
interface or protocol as a symbol, followed by 1 or more method
4680-
definitions for that interface. Records are not required to declare
4681-
any interface implementations. Records which do declare interface
4682-
implementations are required to implement all interface methods. Failing
4683-
to implement all interface methods is a compile time error. Records
4684-
implementing `object` are not required to implement all `object` methods.
4741+
definitions for that interface. Types are not required to declare any
4742+
interface implementations. Types which do declare interface implementations
4743+
are required to implement all interface methods. Failing to implement all
4744+
interface methods is a compile time error. Types implementing `object` are
4745+
not required to implement all `object` methods.
46854746

46864747
Method declarations should appear as:
46874748

4749+
(method-name [arg1] & body)
46884750
(method-name [arg1 arg2 ...] & body)
46894751

46904752
Records objects are created with sensible `object` defaults as by `attrs`.

0 commit comments

Comments
 (0)