1.1 --- a/src/API.cpp Sun Jul 29 12:24:00 2012 -0700
1.2 +++ b/src/API.cpp Sun Jul 29 12:24:49 2012 -0700
1.3 @@ -265,6 +265,12 @@
1.4 ke::ZONE()->heap().reclaim();
1.5 }
1.6
1.7 +void
1.8 +Ke::Keima::ClearPendingException()
1.9 +{
1.10 + ke::ZONE()->clearPendingException();
1.11 +}
1.12 +
1.13 unsigned
1.14 Ke::Module::numPublics()
1.15 {
1.16 @@ -341,6 +347,44 @@
1.17 native->bind(function);
1.18 }
1.19
1.20 +// :TODO: this leaks an interior pointer.
1.21 +static const char *
1.22 +GetTypeName(Type *type)
1.23 +{
1.24 + if (type->isArray())
1.25 + return "array";
1.26 + if (type->isFunction())
1.27 + return "function";
1.28 + if (type->isVoid())
1.29 + return "void";
1.30 + if (type->isReference())
1.31 + type = type->contained();
1.32 + if (type->tag())
1.33 + return type->tag()->chars();
1.34 + return "int";
1.35 +}
1.36 +
1.37 +static inline const char *
1.38 +GetInvokeTypeName(Ke::Parameter::Type type)
1.39 +{
1.40 + switch (type) {
1.41 + case Ke::Parameter::Array:
1.42 + return "array";
1.43 + case Ke::Parameter::CharArray:
1.44 + return "String";
1.45 + case Ke::Parameter::Float:
1.46 + return "Float";
1.47 + case Ke::Parameter::FloatRef:
1.48 + return "&Float";
1.49 + case Ke::Parameter::Int:
1.50 + return "int";
1.51 + case Ke::Parameter::IntRef:
1.52 + return "&int";
1.53 + default:
1.54 + return "<unknown>";
1.55 + }
1.56 +}
1.57 +
1.58 static inline bool
1.59 CheckInvokeType(const Ke::Parameter ¶m, Type *type)
1.60 {
1.61 @@ -365,8 +409,8 @@
1.62 }
1.63 }
1.64
1.65 -bool
1.66 -Ke::Keima::CheckInvokeTypes(Ke::Handle<Ke::Function> argFun, const Ke::Parameter *params, unsigned nparams)
1.67 +static bool
1.68 +CheckInvokeTypes(Ke::Handle<Ke::Function> argFun, const Ke::Parameter *params, unsigned nparams)
1.69 {
1.70 ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(argFun));
1.71
1.72 @@ -374,20 +418,27 @@
1.73 return false;
1.74
1.75 for (unsigned i = 0; i < nparams; i++) {
1.76 - if (!CheckInvokeType(params[i], fun->argType(i)))
1.77 + if (!CheckInvokeType(params[i], fun->argType(i))) {
1.78 + ke::ZONE()->reportError(Message_TypeMismatchDuringInvoke,
1.79 + GetInvokeTypeName(params[i].type()),
1.80 + GetTypeName(fun->argType(i)));
1.81 return false;
1.82 + }
1.83 }
1.84
1.85 // Functions can only return tagged cells, for ISPE1-compatible Invoke().
1.86 ke::Local<ke::Type> returnType(ke::ZONE(), fun->type()->returnType());
1.87 - if ((!returnType->isPrimitive() && !returnType->isVoid()) || returnType->isTraceable())
1.88 + if (!returnType->isPrimitive() && !returnType->isVoid()) {
1.89 + ke::ZONE()->reportError(Message_CannotInvokeReturnType, GetTypeName(returnType));
1.90 return false;
1.91 + }
1.92
1.93 return true;
1.94 }
1.95
1.96 bool
1.97 -Ke::Keima::Invoke(Handle<Function> argFun, const Parameter *params, unsigned nparams, int *retval)
1.98 +Ke::Keima::Invoke(Handle<Function> argFun, const Parameter *params, unsigned nparams,
1.99 + bool checkTypes, int *retval)
1.100 {
1.101 assert(CheckInvokeTypes(argFun, params, nparams));
1.102
1.103 @@ -403,6 +454,9 @@
1.104 if (!ke::ZONE()->stack().pushInvokeFrame(fun, args))
1.105 return false;
1.106
1.107 + if (checkTypes && !CheckInvokeTypes(argFun, params, nparams))
1.108 + return false;
1.109 +
1.110 for (unsigned i = 0; i < nparams; i++) {
1.111 ke::LocalSlot &slot = args.arg(i);
1.112 switch (params[i].type()) {