diff -r 6eed87ebc5ce -r 86b368a4d80d src/API.cpp --- a/src/API.cpp Sun Jul 29 12:24:00 2012 -0700 +++ b/src/API.cpp Sun Jul 29 12:24:49 2012 -0700 @@ -265,6 +265,12 @@ ke::ZONE()->heap().reclaim(); } +void +Ke::Keima::ClearPendingException() +{ + ke::ZONE()->clearPendingException(); +} + unsigned Ke::Module::numPublics() { @@ -341,6 +347,44 @@ native->bind(function); } +// :TODO: this leaks an interior pointer. +static const char * +GetTypeName(Type *type) +{ + if (type->isArray()) + return "array"; + if (type->isFunction()) + return "function"; + if (type->isVoid()) + return "void"; + if (type->isReference()) + type = type->contained(); + if (type->tag()) + return type->tag()->chars(); + return "int"; +} + +static inline const char * +GetInvokeTypeName(Ke::Parameter::Type type) +{ + switch (type) { + case Ke::Parameter::Array: + return "array"; + case Ke::Parameter::CharArray: + return "String"; + case Ke::Parameter::Float: + return "Float"; + case Ke::Parameter::FloatRef: + return "&Float"; + case Ke::Parameter::Int: + return "int"; + case Ke::Parameter::IntRef: + return "&int"; + default: + return ""; + } +} + static inline bool CheckInvokeType(const Ke::Parameter ¶m, Type *type) { @@ -365,8 +409,8 @@ } } -bool -Ke::Keima::CheckInvokeTypes(Ke::Handle argFun, const Ke::Parameter *params, unsigned nparams) +static bool +CheckInvokeTypes(Ke::Handle argFun, const Ke::Parameter *params, unsigned nparams) { ke::Local fun(ke::ZONE(), Open(argFun)); @@ -374,20 +418,27 @@ return false; for (unsigned i = 0; i < nparams; i++) { - if (!CheckInvokeType(params[i], fun->argType(i))) + if (!CheckInvokeType(params[i], fun->argType(i))) { + ke::ZONE()->reportError(Message_TypeMismatchDuringInvoke, + GetInvokeTypeName(params[i].type()), + GetTypeName(fun->argType(i))); return false; + } } // Functions can only return tagged cells, for ISPE1-compatible Invoke(). ke::Local returnType(ke::ZONE(), fun->type()->returnType()); - if ((!returnType->isPrimitive() && !returnType->isVoid()) || returnType->isTraceable()) + if (!returnType->isPrimitive() && !returnType->isVoid()) { + ke::ZONE()->reportError(Message_CannotInvokeReturnType, GetTypeName(returnType)); return false; + } return true; } bool -Ke::Keima::Invoke(Handle argFun, const Parameter *params, unsigned nparams, int *retval) +Ke::Keima::Invoke(Handle argFun, const Parameter *params, unsigned nparams, + bool checkTypes, int *retval) { assert(CheckInvokeTypes(argFun, params, nparams)); @@ -403,6 +454,9 @@ if (!ke::ZONE()->stack().pushInvokeFrame(fun, args)) return false; + if (checkTypes && !CheckInvokeTypes(argFun, params, nparams)) + return false; + for (unsigned i = 0; i < nparams; i++) { ke::LocalSlot &slot = args.arg(i); switch (params[i].type()) {