feat: add Introspect.arguments (#1163)

* feat: add Introspect.arguments

* fix: fix struct case of Introspect.arguments
This commit is contained in:
Veit Heller 2021-02-01 17:03:38 +01:00 committed by GitHub
parent 59d43abf74
commit e42922e96e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 16 deletions

View File

@ -20,6 +20,14 @@
(set! m (- m b))) (set! m (- m b)))
(if (< a 0) (neg m) m))) (if (< a 0) (neg m) m)))
(defmodule List
(doc pairs "makes a list of pairs out of a list `l`. If the number of
elements is uneven, the trailing element will be discarded.")
(defndynamic pairs [l]
(if (< (length l) 2)
'()
(cons `(%(car l) %(cadr l)) (List.pairs (cddr l))))))
(defmodule Project (defmodule Project
(doc no-echo "Turn off debug printing in the compiler.") (doc no-echo "Turn off debug printing in the compiler.")
(defndynamic no-echo [] (defndynamic no-echo []

View File

@ -83,30 +83,48 @@
(doc arity (doc arity
"What's the arity of this binding? "What's the arity of this binding?
- When `binding` is a function, returns the number of arguments. - When `binding` is a function, returns the number of arguments.
- When `binding` is a command, returns the number of arguments. - When `binding` is a command, returns the number of arguments.
- When `binding` is a primitive, returns the number of arguments. - When `binding` is a primitive, returns the number of arguments.
- When `binding` is an interface, returns the number of arguments. - When `binding` is an interface, returns the number of arguments.
- When `binding` is a struct, returns the number of fields. - When `binding` is a struct, returns the number of fields.
- When `binding` is a sumtype, returns a list of the number of type - When `binding` is a sumtype, returns a list of the number of type
arguments of each constructor.") arguments of each constructor.
- Otherwise it returns 0.")
(defndynamic arity [binding] (defndynamic arity [binding]
(let [args (arguments binding)]
(if (Introspect.sumtype? binding)
(map length args)
(length args))))
(doc arguments
"What are the arguments to this binding?
- When `binding` is a function, returns the argument array.
- When `binding` is a command, returns the argument array.
- When `binding` is a primitive, returns the argument array.
- When `binding` is an interface, returns the argument array.
- When `binding` is a struct, returns the fields.
- When `binding` is a sumtype, returns a list of the type arguments of each
constructor.
- Otherwise it returns an empty list.")
(defndynamic arguments [binding]
(let [s (s-expr binding)] (let [s (s-expr binding)]
(if (empty? s) (if (empty? s)
0 0
(cond (cond
(Introspect.external? binding) (Introspect.external? binding)
(if (list? (caddr s)) (if (list? (caddr s))
(length (car (cdaddr s))) (car (cdaddr s))
0) '())
(Introspect.command? binding) (length (caddr s)) (Introspect.command? binding) (caddr s)
(Introspect.primitive? binding) (length (caddr s)) (Introspect.primitive? binding) (caddr s)
(Introspect.interface? binding) (length (car (cdaddr s))) (Introspect.interface? binding) (car (cdaddr s))
(Introspect.function? binding) (length (caddr s)) (Introspect.function? binding) (caddr s)
(Introspect.struct? binding) (/ (length (caddr s)) 2) (Introspect.struct? binding) (map car (List.pairs (caddr s)))
(Introspect.sumtype? binding) (map (fn [arr] (Introspect.sumtype? binding) (map (fn [arr]
(length (cadr arr))) (cddr s)) (cadr arr)) (cddr s))
0)))) '()))))
(doc macro? (doc macro?
"Is this binding a macro?") "Is this binding a macro?")

View File

@ -30,6 +30,13 @@
(defmacro test-arity [x] (defmacro test-arity [x]
(eval (list 'Introspect.arity x))) (eval (list 'Introspect.arity x)))
(defmacro test-arguments [x]
(collect-into
(map
(fn [arg] `(copy %(str arg)))
(eval `(Introspect.arguments %x)))
array))
(deftest test (deftest test
(assert-true test (assert-true test
(test-function? foo) (test-function? foo)
@ -49,6 +56,10 @@
(assert-true test (assert-true test
(test-module? Qux) (test-module? Qux)
"module? works as expected") "module? works as expected")
(assert-equal test
&[@"x"]
&(test-arguments foo)
"arguments works as expected")
(assert-equal test (assert-equal test
1 1
(test-arity foo) (test-arity foo)