~subsetpark/fugue

a2d871e9b8ad582644eb5d737095748c259d0f66 — Zach Smith 6 months ago 34a4a09
Some refactors and reorg
2 files changed, 55 insertions(+), 57 deletions(-)

M README.md
M fugue.janet
M README.md => README.md +20 -24
@@ 64,12 64,12 @@ be selected for any descendent prototype instances.
**table**  | [source][1]

```janet
@{:new <function new-from-root> :_meta @{ :object-type :prototype :fields () :prototype_allocations @{} :object-id :top_000002} :_name "Prototype" :_after-init <function identity>}
@{:new <function new-from-root> :_meta @{ :object-type :prototype :fields () :prototype_allocations @{} :object-id :top_000000} :_name "Prototype" :_after-init <function identity>}
```

Root of the Fugue object hierarchy.


[1]: fugue.janet#L1
[1]: fugue.janet#L15

## allocate



@@ 84,7 84,7 @@ specific prototype for this key, then `fugue/allocate` will put `value`
at `key` in the appropriate prototype, and it will be inherited by
all descendents of that prototype.

[2]: fugue.janet#L255
[2]: fugue.janet#L287

## declare-open-multi



@@ 100,7 100,7 @@ Extending an open multimethod (see `extend-multi`) from any other
environment makes the case extension available wherever the
multimethod has been imported.

[3]: fugue.janet#L593
[3]: fugue.janet#L625

## defgeneric



@@ 115,7 115,7 @@ first argument has a method corresponding to the name of the
function, call that object 's method with the arguments. Otherwise,
evaluate `body`.

[4]: fugue.janet#L289
[4]: fugue.janet#L321

## defmethod



@@ 133,7 133,7 @@ Defines a few symbols for reference in the body of the method.
`__parent` - Bound to the parent of `proto`.
`__super` - Bound to the method at `name` within `__parent`.

[5]: fugue.janet#L300
[5]: fugue.janet#L332

## defmulti



@@ 205,7 205,7 @@ repl:12:> (cat "hello" 100)
"hello #100"
```

[6]: fugue.janet#L517
[6]: fugue.janet#L549

## defproto



@@ 215,12 215,7 @@ repl:12:> (cat "hello" 100)
(defproto name parent-name & fields)
```

CLOS-style prototype definition.

This attempts to provide much of the same functionality as CLOS's
`defclass`. However, Janet OO is powered by prototypal inheritance,
not class-based inheritance, so it's important not to assume that it
should be used in the same fashion.
Object prototype definition.

## Usage



@@ 251,7 246,8 @@ inherit it.
field (by default, has the same name as the field). Specify `false`
to prevent a getter from being defined.

`defproto` will define a getter function for each of the defined fields.
`defproto` will define a getter function for each of the defined
fields, unless `:getter` is false.

`defproto` will also create a `:new` method in the created
prototype. This will take as positional arguments all of the fields


@@ 260,9 256,9 @@ other fields defined on this protoype.

The special method ` :_after-init` will be called as the last step
in the `:new` conststructor. It can be defined for a prototype (see
`defmethod`) to take the prototype and a new instance and to make
any arbitrary mutations on either as part of object
instantiation. By default it is a no-op.
`defmethod`) to take a new instance and to make any arbitrary
mutations on the instance or prototype as part of object
instantiation. By default it simply returns the instance.

If `fields` is not of an even length, it wil be taken as an error.



@@ 279,7 275,7 @@ repl:47:> (speak (:new Pekingese))
"My name is Fido and I am Extremely Small"
```

[7]: fugue.janet#L52
[7]: fugue.janet#L199

## extend-multi



@@ 297,7 293,7 @@ See that function's documentation for full usage reference.
Whenever a case is added to `multi`, that case is available
wherever the multimethod is imported.

[8]: fugue.janet#L606
[8]: fugue.janet#L638

## fields



@@ 310,7 306,7 @@ wherever the multimethod is imported.
Return all the defined fields for `obj` and its prototype
hierarchy.

[9]: fugue.janet#L327
[9]: fugue.janet#L359

## get-type-or-proto-id



@@ 323,7 319,7 @@ hierarchy.
Return the prototype of `obj`, if it has one, otherwise the keyword
output of `type`.

[10]: fugue.janet#L345
[10]: fugue.janet#L377

## multimethod-types-match?



@@ 337,7 333,7 @@ Check to see if the types `args` match the sequence `arg-types`,
according to multimethod rules (ie, following prototype membership
and using `:_` as a fallback)

[11]: fugue.janet#L446
[11]: fugue.janet#L478

## prototype?



@@ 349,5 345,5 @@ and using `:_` as a fallback)

Is `obj` the result of a `defproto ` call? 

[12]: fugue.janet#L248
[12]: fugue.janet#L280


M fugue.janet => fugue.janet +35 -33
@@ 1,15 1,30 @@
(var Root nil)

(def- after-init-identity identity)
#
# Bootstrapping
#

(defn- bare-proto
  "Basic prototype table."
  [object-id name defined-fields]
  @{:_meta @{:object-type :prototype
             :fields defined-fields
             :prototype_allocations @{}
             :object-id object-id}
    :_name name
    :_after-init after-init-identity})
    :_after-init identity})

(def Root
  "Root of the Fugue object hierarchy."
  (let [top (keyword "top" (gensym))]
    (bare-proto top "Prototype" [])))

(put Root :new
     (fn new-from-root
       [self &keys attrs]
       (let [meta @{:object-type :instance
                    :object-id (keyword :Root (gensym))}
             inst @{:_meta meta}]
         (merge-into inst attrs)
         (table/setproto inst self))))

#
# Defaults Handling


@@ 47,7 62,7 @@
      (set-allocated-value parent-sym field-name proto-value))))

#
#
# defproto Forms
#

(defn- make-copy


@@ 183,12 198,7 @@

(defmacro defproto
  ````
  CLOS-style prototype definition.

  This attempts to provide much of the same functionality as CLOS's
  `defclass`. However, Janet OO is powered by prototypal inheritance,
  not class-based inheritance, so it's important not to assume that it
  should be used in the same fashion.
  Object prototype definition.

  ## Usage
  


@@ 219,7 229,8 @@
  field (by default, has the same name as the field). Specify `false`
  to prevent a getter from being defined.

  `defproto` will define a getter function for each of the defined fields.
  `defproto` will define a getter function for each of the defined
  fields, unless `:getter` is false.

  `defproto` will also create a `:new` method in the created
  prototype. This will take as positional arguments all of the fields


@@ 228,9 239,9 @@

  The special method ` :_after-init` will be called as the last step
  in the `:new` conststructor. It can be defined for a prototype (see
  `defmethod`) to take the prototype and a new instance and to make
  any arbitrary mutations on either as part of object
  instantiation. By default it is a no-op.
  `defmethod`) to take a new instance and to make any arbitrary
  mutations on the instance or prototype as part of object
  instantiation. By default it simply returns the instance.
  
  If `fields` is not of an even length, it wil be taken as an error.



@@ 248,6 259,10 @@
  ```
  ````
  [name parent-name & fields]
  
  (unless (zero? (mod (length fields) 2))
    (error "defproto received odd number of fields"))
  
  (let [fields (partition 2 fields)
        [parent parent-sym-base] (if (not (symbol? parent-name))
                                   [(fn [] Root) "Root"]


@@ 256,24 271,11 @@
        [init-args proto-allocated-fields] (field-definitions name fields parent-sym)]
    (populate-runtime-info! fields parent-sym)
    (array/push
      (getters name fields)
      (proto-form name parent parent-sym fields proto-allocated-fields)
      (init-form name init-args)
      (pred-form name parent-sym)
      (pred*-form name parent-sym))))

# Establish root of object hierarchy.
(set Root
     (let [top (keyword "top" (gensym))]
       (bare-proto top "Prototype" [])))

(put Root :new (fn new-from-root
                 [self &keys attrs]
                 (let [meta @{:object-type :instance
                              :object-id (keyword :Root (gensym))}
                       inst @{:_meta meta}]
                   (merge-into inst attrs)
                   (table/setproto inst self))))
     (getters name fields)
     (proto-form name parent parent-sym fields proto-allocated-fields)
     (init-form name init-args)
     (pred-form name parent-sym)
     (pred*-form name parent-sym))))

(defn prototype?
  ```