Fix various error reporting bugs related to Invoke.
authorDavid Anderson <dvander@alliedmods.net>
Sun Jul 29 12:24:49 2012 -0700 (2012-07-29)
changeset 12986b368a4d80d
parent 128 6eed87ebc5ce
child 130 dae60280a1f7
Fix various error reporting bugs related to Invoke.
include/keima.h
src/API.cpp
src/Messages.tbl
src/SemanticAnalysis.cpp
src/Zone.cpp
src/Zone.h
src/main.cpp
     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 &param, 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