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)))
(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
(doc no-echo "Turn off debug printing in the compiler.")
(defndynamic no-echo []

View File

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

View File

@ -30,6 +30,13 @@
(defmacro test-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
(assert-true test
(test-function? foo)
@ -49,6 +56,10 @@
(assert-true test
(test-module? Qux)
"module? works as expected")
(assert-equal test
&[@"x"]
&(test-arguments foo)
"arguments works as expected")
(assert-equal test
1
(test-arity foo)