Fix various error reporting bugs related to Invoke.
Fix various error reporting bugs related to Invoke.
1.1 --- a/include/keima.h Sun Jul 29 12:24:00 2012 -0700
1.2 +++ b/include/keima.h Sun Jul 29 12:24:49 2012 -0700
1.3 @@ -319,17 +319,13 @@
1.4 static void ClearPendingException();
1.5
1.6 /*
1.7 - * Type checks a function against given parameters.
1.8 - */
1.9 - static bool CheckInvokeTypes(Handle<Function> fun, const Parameter *params, unsigned nparams);
1.10 -
1.11 - /*
1.12 * Executes a function with the given parameters. This interface is
1.13 * intended for compatibility with SourceMod's ISourcePawnEngine2 and
1.14 * should not be used otherwise, since it is intended to support only
1.15 * a small subset of the core language.
1.16 */
1.17 - static bool Invoke(Handle<Function> fun, const Parameter *params, unsigned nparams, int *result);
1.18 + static bool Invoke(Handle<Function> fun, const Parameter *params, unsigned nparams,
1.19 + bool checkTypes, int *result);
1.20
1.21 /*
1.22 * Sets the global message handler through which errors will be reported
2.1 --- a/src/API.cpp Sun Jul 29 12:24:00 2012 -0700
2.2 +++ b/src/API.cpp Sun Jul 29 12:24:49 2012 -0700
2.3 @@ -265,6 +265,12 @@
2.4 ke::ZONE()->heap().reclaim();
2.5 }
2.6
2.7 +void
2.8 +Ke::Keima::ClearPendingException()
2.9 +{
2.10 + ke::ZONE()->clearPendingException();
2.11 +}
2.12 +
2.13 unsigned
2.14 Ke::Module::numPublics()
2.15 {
2.16 @@ -341,6 +347,44 @@
2.17 native->bind(function);
2.18 }
2.19
2.20 +// :TODO: this leaks an interior pointer.
2.21 +static const char *
2.22 +GetTypeName(Type *type)
2.23 +{
2.24 + if (type->isArray())
2.25 + return "array";
2.26 + if (type->isFunction())
2.27 + return "function";
2.28 + if (type->isVoid())
2.29 + return "void";
2.30 + if (type->isReference())
2.31 + type = type->contained();
2.32 + if (type->tag())
2.33 + return type->tag()->chars();
2.34 + return "int";
2.35 +}
2.36 +
2.37 +static inline const char *
2.38 +GetInvokeTypeName(Ke::Parameter::Type type)
2.39 +{
2.40 + switch (type) {
2.41 + case Ke::Parameter::Array:
2.42 + return "array";
2.43 + case Ke::Parameter::CharArray:
2.44 + return "String";
2.45 + case Ke::Parameter::Float:
2.46 + return "Float";
2.47 + case Ke::Parameter::FloatRef:
2.48 + return "&Float";
2.49 + case Ke::Parameter::Int:
2.50 + return "int";
2.51 + case Ke::Parameter::IntRef:
2.52 + return "&int";
2.53 + default:
2.54 + return "<unknown>";
2.55 + }
2.56 +}
2.57 +
2.58 static inline bool
2.59 CheckInvokeType(const Ke::Parameter ¶m, Type *type)
2.60 {
2.61 @@ -365,8 +409,8 @@
2.62 }
2.63 }
2.64
2.65 -bool
2.66 -Ke::Keima::CheckInvokeTypes(Ke::Handle<Ke::Function> argFun, const Ke::Parameter *params, unsigned nparams)
2.67 +static bool
2.68 +CheckInvokeTypes(Ke::Handle<Ke::Function> argFun, const Ke::Parameter *params, unsigned nparams)
2.69 {
2.70 ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(argFun));
2.71
2.72 @@ -374,20 +418,27 @@
2.73 return false;
2.74
2.75 for (unsigned i = 0; i < nparams; i++) {
2.76 - if (!CheckInvokeType(params[i], fun->argType(i)))
2.77 + if (!CheckInvokeType(params[i], fun->argType(i))) {
2.78 + ke::ZONE()->reportError(Message_TypeMismatchDuringInvoke,
2.79 + GetInvokeTypeName(params[i].type()),
2.80 + GetTypeName(fun->argType(i)));
2.81 return false;
2.82 + }
2.83 }
2.84
2.85 // Functions can only return tagged cells, for ISPE1-compatible Invoke().
2.86 ke::Local<ke::Type> returnType(ke::ZONE(), fun->type()->returnType());
2.87 - if ((!returnType->isPrimitive() && !returnType->isVoid()) || returnType->isTraceable())
2.88 + if (!returnType->isPrimitive() && !returnType->isVoid()) {
2.89 + ke::ZONE()->reportError(Message_CannotInvokeReturnType, GetTypeName(returnType));
2.90 return false;
2.91 + }
2.92
2.93 return true;
2.94 }
2.95
2.96 bool
2.97 -Ke::Keima::Invoke(Handle<Function> argFun, const Parameter *params, unsigned nparams, int *retval)
2.98 +Ke::Keima::Invoke(Handle<Function> argFun, const Parameter *params, unsigned nparams,
2.99 + bool checkTypes, int *retval)
2.100 {
2.101 assert(CheckInvokeTypes(argFun, params, nparams));
2.102
2.103 @@ -403,6 +454,9 @@
2.104 if (!ke::ZONE()->stack().pushInvokeFrame(fun, args))
2.105 return false;
2.106
2.107 + if (checkTypes && !CheckInvokeTypes(argFun, params, nparams))
2.108 + return false;
2.109 +
2.110 for (unsigned i = 0; i < nparams; i++) {
2.111 ke::LocalSlot &slot = args.arg(i);
2.112 switch (params[i].type()) {
3.1 --- a/src/Messages.tbl Sun Jul 29 12:24:00 2012 -0700
3.2 +++ b/src/Messages.tbl Sun Jul 29 12:24:49 2012 -0700
3.3 @@ -59,4 +59,7 @@
3.4 MSG(NotAllPathsReturnValue, SyntaxError, "not all paths through function return a value")
3.5 MSG(UsedVoidReturn, SyntaxError, "return value expected, but function does not return a value")
3.6 MSG(FunctionDoesNotReturnValue, SyntaxError, "cannot use the result of a function with no return value")
3.7 -MSG(IdentifierNotFound, SyntaxError, "identifier '%s' could not be found")
3.8 \ No newline at end of file
3.9 +MSG(IdentifierNotFound, SyntaxError, "identifier '%s' could not be found")
3.10 +MSG(TypeMismatchDuringInvoke, SyntaxError, "incoming type '%s' does not match signature type '%s'")
3.11 +MSG(CannotInvokeReturnType, SyntaxError, "cannot invoke function with return type '%s'")
3.12 +
4.1 --- a/src/SemanticAnalysis.cpp Sun Jul 29 12:24:00 2012 -0700
4.2 +++ b/src/SemanticAnalysis.cpp Sun Jul 29 12:24:49 2012 -0700
4.3 @@ -170,6 +170,8 @@
4.4 return "array";
4.5 if (type->isFunction())
4.6 return "function";
4.7 + if (type->isVoid())
4.8 + return "void";
4.9 if (type->isReference())
4.10 type = type->contained();
4.11 if (type->tag())
5.1 --- a/src/Zone.cpp Sun Jul 29 12:24:00 2012 -0700
5.2 +++ b/src/Zone.cpp Sun Jul 29 12:24:49 2012 -0700
5.3 @@ -312,3 +312,10 @@
5.4 {
5.5 ZONE()->reportError(Message_AllocationOverflow);
5.6 }
5.7 +
5.8 +void
5.9 +Zone::clearPendingException()
5.10 +{
5.11 + hasPendingException_ = false;
5.12 +}
5.13 +
6.1 --- a/src/Zone.h Sun Jul 29 12:24:00 2012 -0700
6.2 +++ b/src/Zone.h Sun Jul 29 12:24:49 2012 -0700
6.3 @@ -126,6 +126,7 @@
6.4 void reportError(Message message, ...);
6.5 void reportErrorVA(Message message, va_list ap);
6.6 bool hasPendingException();
6.7 + void clearPendingException();
6.8 void installErrorReporter(Ke::IMessageReporter *reporter);
6.9 void beginCompilationErrors(const char *file);
6.10 void reportCompilationError(Message message, unsigned line, unsigned col, va_list ap);
6.11 @@ -153,6 +154,7 @@
6.12 }
6.13
6.14 template <typename T>
6.15 +
6.16 Local<T>::~Local()
6.17 {
6.18 assert(*zone_->lastLocalRoot() == toRaw());
7.1 --- a/src/main.cpp Sun Jul 29 12:24:00 2012 -0700
7.2 +++ b/src/main.cpp Sun Jul 29 12:24:49 2012 -0700
7.3 @@ -126,7 +126,7 @@
7.4
7.5 int result;
7.6 Ke::Local<Ke::Function> fun = module->getPublic(0);
7.7 - if (Ke::Keima::Invoke(fun, NULL, 0, &result))
7.8 + if (Ke::Keima::Invoke(fun, NULL, 0, true, &result))
7.9 printf("%d\n", result);
7.10 }
7.11