summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2014-02-05 17:10:11 -0800
committerKaz Kylheku <kaz@kylheku.com>2014-02-05 17:10:11 -0800
commit04a75123fc2f6135850a811bf7477ed97fdcdc83 (patch)
treee98d53b542ff02cb9d1f3673606d41acdf304858
parent227f0d19dc5313edbebbb56ba6b4966012a2370e (diff)
downloadtxr-04a75123fc2f6135850a811bf7477ed97fdcdc83.tar.gz
txr-04a75123fc2f6135850a811bf7477ed97fdcdc83.tar.bz2
txr-04a75123fc2f6135850a811bf7477ed97fdcdc83.zip
Allow sequences and hashes to be called as functions.
This is already supported in the DWIM operator. * eval.c (apply): If object isn't a function, gather the arguments into an array and delegate to generic_funcall. * lib.c (generic_funcall): Changed from static to external linkage. Supports sequences and hashes as functions. Error messages fixed not to refer to "funcall". (funcall, funcall1, funcall2, funcall3, funcall4): Do not throw exception if fun is not of FUN type; instead, delegate to generic_funcall. Error messages fixed not to refer to "funcall". * lib.h (generic_function): Declared.
-rw-r--r--ChangeLog17
-rw-r--r--eval.c10
-rw-r--r--lib.c76
-rw-r--r--lib.h1
4 files changed, 79 insertions, 25 deletions
diff --git a/ChangeLog b/ChangeLog
index b205fcd7..9db42ac8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
2014-02-05 Kaz Kylheku <kaz@kylheku.com>
+ Allow sequences and hashes to be called as functions.
+ This is already supported in the DWIM operator.
+
+ * eval.c (apply): If object isn't a function, gather the
+ arguments into an array and delegate to generic_funcall.
+
+ * lib.c (generic_funcall): Changed from static to external linkage.
+ Supports sequences and hashes as functions. Error messages
+ fixed not to refer to "funcall".
+ (funcall, funcall1, funcall2, funcall3, funcall4): Do not throw
+ exception if fun is not of FUN type; instead, delegate
+ to generic_funcall. Error messages fixed not to refer to "funcall".
+
+ * lib.h (generic_function): Declared.
+
+2014-02-05 Kaz Kylheku <kaz@kylheku.com>
+
* arith.c (lognot): Conform to new scheme for defaulting optional args.
* eval.c (apply): Unconditionally use colon_k for missing optional
diff --git a/eval.c b/eval.c
index 61459838..a70d8474 100644
--- a/eval.c
+++ b/eval.c
@@ -340,6 +340,16 @@ val apply(val fun, val arglist, val ctx_form)
fun = cdr(binding);
}
+ if (!functionp(fun)) {
+ for (nargs = 0;
+ (p < arg + 32) && consp(arglist);
+ nargs++, p++, arglist = cdr(arglist))
+ {
+ *p = car(arglist);
+ }
+ return generic_funcall(fun, arg, nargs);
+ }
+
type_check (fun, FUN);
if (!listp(arglist)) {
diff --git a/lib.c b/lib.c
index ea3df4b9..771bb46d 100644
--- a/lib.c
+++ b/lib.c
@@ -3230,11 +3230,47 @@ val interp_fun_p(val obj)
return (functionp(obj) && obj->f.functype == FINTERP) ? t : nil;
}
-static val generic_funcall(val fun, val arg[], int nargs)
+val generic_funcall(val fun, val arg[], int nargs)
{
int variadic, fixparam, reqargs;
- type_check (fun, FUN);
+ switch (type(fun)) {
+ case FUN:
+ break;
+ case NIL:
+ case CONS:
+ case LCONS:
+ case VEC:
+ case STR:
+ case LIT:
+ case LSTR:
+ switch (nargs) {
+ case 0:
+ uw_throw(error_s, lit("call: missing required arguments"));
+ case 1:
+ return ref(fun, arg[0]);
+ case 2:
+ return sub(fun, arg[0], arg[1]);
+ default:
+ uw_throw(error_s, lit("call: too many arguments"));
+ }
+ case COBJ:
+ if (fun->co.cls == hash_s) {
+ switch (nargs) {
+ case 0:
+ uw_throw(error_s, lit("call: missing required arguments"));
+ case 1:
+ return gethash(fun, arg[0]);
+ case 2:
+ return gethash_n(fun, arg[0], arg[1]);
+ default:
+ uw_throw(error_s, lit("call: too many arguments"));
+ }
+ }
+ /* fallthrough */
+ default:
+ type_mismatch(lit("call: ~s is not callable"), fun, nao);
+ }
variadic = fun->f.variadic;
fixparam = fun->f.fixparam;
@@ -3242,10 +3278,10 @@ static val generic_funcall(val fun, val arg[], int nargs)
if (!variadic) {
if (nargs < reqargs)
- uw_throw(error_s, lit("funcall: missing required arguments"));
+ uw_throw(error_s, lit("call: missing required arguments"));
if (nargs > fixparam)
- uw_throw(error_s, lit("funcall: too many arguments"));
+ uw_throw(error_s, lit("call: too many arguments"));
for (; nargs < fixparam; )
arg[nargs++] = colon_k;
@@ -3287,7 +3323,7 @@ static val generic_funcall(val fun, val arg[], int nargs)
nargs = fixparam;
if (nargs < reqargs)
- uw_throw(error_s, lit("funcall: missing required arguments"));
+ uw_throw(error_s, lit("call: missing required arguments"));
for (; nargs < fixparam; )
arg[nargs++] = colon_k;
@@ -3332,9 +3368,7 @@ static val generic_funcall(val fun, val arg[], int nargs)
val funcall(val fun)
{
- type_check(fun, FUN);
-
- if (fun->f.optargs) {
+ if (fun->f.optargs || type(fun) != FUN) {
val arg[32] = { nil };
return generic_funcall(fun, arg, 0);
}
@@ -3360,14 +3394,12 @@ val funcall(val fun)
break;
}
}
- uw_throw(error_s, lit("funcall: wrong number of arguments"));
+ uw_throw(error_s, lit("call: wrong number of arguments"));
}
val funcall1(val fun, val arg)
{
- type_check(fun, FUN);
-
- if (fun->f.optargs) {
+ if (fun->f.optargs || type(fun) != FUN) {
val args[32];
args[0] = arg;
return generic_funcall(fun, args, 1);
@@ -3398,14 +3430,12 @@ val funcall1(val fun, val arg)
break;
}
}
- uw_throw(error_s, lit("funcall1: wrong number of arguments"));
+ uw_throw(error_s, lit("call: wrong number of arguments"));
}
val funcall2(val fun, val arg1, val arg2)
{
- type_check(fun, FUN);
-
- if (fun->f.optargs) {
+ if (fun->f.optargs || type(fun) != FUN) {
val arg[32];
arg[0] = arg1;
arg[1] = arg2;
@@ -3442,14 +3472,12 @@ val funcall2(val fun, val arg1, val arg2)
break;
}
}
- uw_throw(error_s, lit("funcall2: wrong number of arguments"));
+ uw_throw(error_s, lit("call: wrong number of arguments"));
}
val funcall3(val fun, val arg1, val arg2, val arg3)
{
- type_check(fun, FUN);
-
- if (fun->f.optargs) {
+ if (fun->f.optargs || type(fun) != FUN) {
val arg[32];
arg[0] = arg1;
arg[1] = arg2;
@@ -3491,14 +3519,12 @@ val funcall3(val fun, val arg1, val arg2, val arg3)
break;
}
}
- uw_throw(error_s, lit("funcall3: wrong number of arguments"));
+ uw_throw(error_s, lit("call: wrong number of arguments"));
}
val funcall4(val fun, val arg1, val arg2, val arg3, val arg4)
{
- type_check(fun, FUN);
-
- if (fun->f.optargs) {
+ if (fun->f.optargs || type(fun) != FUN) {
val arg[32];
arg[0] = arg1;
arg[1] = arg2;
@@ -3545,7 +3571,7 @@ val funcall4(val fun, val arg1, val arg2, val arg3, val arg4)
break;
}
}
- uw_throw(error_s, lit("funcall4: wrong number of arguments"));
+ uw_throw(error_s, lit("call: wrong number of arguments"));
}
val reduce_left(val fun, val list, val init, val key)
diff --git a/lib.h b/lib.h
index 1fc95a00..00fb35e5 100644
--- a/lib.h
+++ b/lib.h
@@ -603,6 +603,7 @@ val func_get_env(val fun);
val func_set_env(val fun, val env);
val functionp(val);
val interp_fun_p(val);
+val generic_funcall(val fun, val arg[], int nargs);
val funcall(val fun);
val funcall1(val fun, val arg);
val funcall2(val fun, val arg1, val arg2);