Phase 13: Protocol Completion — reify dispatch, #() reader, IFn protocol
- reader.janet: rewrite read-anon-fn to handle % arg references % → gensym, %1/%2 → sorted gensyms, replaces all matching % refs - evaluator.janet: IFn protocol support in default invocation arm Before erroring "Cannot call X as a function", checks for: 1) type-registry IFn/-invoke method (extend-type protocols) 2) :jolt/protocol-methods :-invoke (reified objects) - test/phase13-test.janet: 4 test sections (28-31) 28: reify dispatch — protocol methods on reified objects 29: #() anon-fn — % and %1/%2 arg handling 30: extend-type — protocol method dispatch for deftypes 31: clojure.walk loading — keywordize-keys loads correctly - All pass: 316 ok, 1 fail (pre-existing, unchanged)
This commit is contained in:
parent
5d7f392666
commit
df1e836cda
7 changed files with 130 additions and 44 deletions
|
|
@ -836,7 +836,15 @@
|
|||
(apply f args)
|
||||
(if (keyword? f)
|
||||
(get (first args) f)
|
||||
(error (string "Cannot call " (type f) " as a function"))))))))
|
||||
(if (and (table? f) (get f :jolt/deftype))
|
||||
(let [ifn-fn (find-protocol-method ctx (get f :jolt/deftype) "IFn" "-invoke")]
|
||||
(if ifn-fn (apply ifn-fn f args)
|
||||
(if (get f :jolt/protocol-methods)
|
||||
(let [invoke-fn (get (f :jolt/protocol-methods) :-invoke)]
|
||||
(if invoke-fn (apply invoke-fn f args)
|
||||
(error (string "Cannot call " (type f) " as a function"))))
|
||||
(error (string "Cannot call " (type f) " as a function")))))
|
||||
(error (string "Cannot call " (type f) " as a function")))))))))
|
||||
|
||||
(set eval-form (fn [ctx bindings form]
|
||||
(cond
|
||||
|
|
|
|||
|
|
@ -282,7 +282,35 @@
|
|||
(defn read-anon-fn [s pos]
|
||||
# pos is at #, next char is (
|
||||
(let [[form new-pos] (read-form s (+ pos 1))]
|
||||
[(array/insert form 0 (sym "fn*")) new-pos]))
|
||||
# Collect % arg references and rename them to gensyms
|
||||
(var arg-map @{})
|
||||
(defn- replace-pct [f]
|
||||
(cond
|
||||
(and (struct? f) (= :symbol (f :jolt/type)))
|
||||
(let [nm (f :name)]
|
||||
(if (and (> (length nm) 0) (= "%" (string/slice nm 0 1)))
|
||||
(let [existing (get arg-map nm)]
|
||||
(if existing
|
||||
{:jolt/type :symbol :ns nil :name existing}
|
||||
(let [gen (gensym)]
|
||||
(put arg-map nm (string gen))
|
||||
{:jolt/type :symbol :ns nil :name (string gen)})))
|
||||
f))
|
||||
(array? f) (array ;(map replace-pct f))
|
||||
(tuple? f) (tuple ;(map replace-pct f))
|
||||
f))
|
||||
(def replaced (replace-pct form))
|
||||
(def arg-names @[])
|
||||
# Sort %1 %2 %3 ..., then %, then %&
|
||||
(def sorted-keys (sort (keys arg-map)))
|
||||
(each k sorted-keys
|
||||
(array/push arg-names {:jolt/type :symbol :ns nil :name (get arg-map k)}))
|
||||
(def result @[(sym "fn*")])
|
||||
(if (> (length arg-names) 0)
|
||||
(array/push result (tuple ;arg-names))
|
||||
(array/push result (tuple))) # no args
|
||||
(array/push result replaced)
|
||||
[result new-pos]))
|
||||
|
||||
(defn read-reader-conditional [s pos]
|
||||
# pos is at #, next char is ? or ?@
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue