diff --git a/core/Dynamic.carp b/core/Dynamic.carp index 2e7017e2..9cac0eee 100644 --- a/core/Dynamic.carp +++ b/core/Dynamic.carp @@ -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 [] diff --git a/core/Introspect.carp b/core/Introspect.carp index 7eece087..756dac1c 100644 --- a/core/Introspect.carp +++ b/core/Introspect.carp @@ -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?") diff --git a/test/introspect.carp b/test/introspect.carp index 024a2dd1..89fd3b7d 100644 --- a/test/introspect.carp +++ b/test/introspect.carp @@ -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)