include/keima.h
author David Anderson <dvander@alliedmods.net>
Sat Jul 28 21:55:52 2012 -0700 (2012-07-28)
changeset 119 ac72cd783392
parent 96 9d341206620f
child 129 86b368a4d80d
permissions -rw-r--r--
trigger build
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2004-2012 David Anderson
     4  *
     5  * This file is part of SourcePawn.
     6  *
     7  * SourcePawn is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * SourcePawn. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #ifndef _include_sourcepawn2_api_h_
    20 #define _include_sourcepawn2_api_h_
    21 
    22 #include <assert.h>
    23 #include <stddef.h>
    24 #include "../include/keima_util.h"
    25 
    26 namespace ke {
    27 
    28 class Zone;
    29 class Object;
    30 class HandleScope;
    31 class HeapRoot;
    32 
    33 }
    34 
    35 namespace Ke {
    36 
    37 class Function;
    38 
    39 /*
    40  * A Handle is a safe pointer that holds an object reference, such that it
    41  * can be scanned and potentially moved by the garbage collector.
    42  */
    43 template <typename T>
    44 class Handle
    45 {
    46   protected:
    47     template <typename S> void typeCheck() {
    48         while (false) {
    49             T *v1 = NULL;
    50             S *v2 = NULL;
    51             v1 = v2;
    52             (void)v1;
    53         }
    54     }
    55 
    56   public:
    57     Handle()
    58       : obj_(NULL)
    59     {
    60     }
    61 
    62     template <typename S> Handle(Handle<S> other)
    63       : obj_(reinterpret_cast<S *>(*other))
    64     {
    65         typeCheck<S>();
    66     }
    67  
    68     explicit Handle(T *obj)
    69       : obj_(obj)
    70     {
    71     }
    72 
    73     T *operator ->() const {
    74         return obj_;
    75     }
    76     T *operator *() const {
    77         return obj_;
    78     }
    79     operator bool () const {
    80         return !!obj_;
    81     }
    82 
    83   protected:
    84     T *obj_;
    85 };
    86 
    87 /*
    88  * A local variable that roots an object. Locals are owned by the nearest
    89  * HandleScope, and as soon as that HandleScope dies, all its Locals are
    90  * no longer available.
    91  */
    92 template <typename T>
    93 class Local : public Handle<T>
    94 {
    95   public:
    96     Local()
    97       : Handle<T>()
    98     {
    99     }
   100 
   101     template <typename S> Local(Local<S> other)
   102       : Handle<T>(reinterpret_cast<T *>(*other))
   103     {
   104         this->template typeCheck<S>();
   105     }
   106 
   107     template <typename S> Local(S *other)
   108       : Handle<T>(other)
   109     {
   110     }
   111 };
   112 
   113 /*
   114  * A non-local variable that outlives HandleScopes. A Root is reference-
   115  * counted. When its reference count reaches 0, the Root is removed.
   116  */
   117 template <typename T>
   118 class Root : public Handle<T>
   119 {
   120   public:
   121     Root<T>()
   122       : Handle<T>()
   123     {
   124     }
   125 
   126     Root<T>(const Root<T> &other)
   127       : Handle<T>(reinterpret_cast<T *>(*other))
   128     {
   129         incref();
   130     }
   131 
   132     explicit Root(ke::HeapRoot *obj)
   133       : Handle<T>(reinterpret_cast<T *>(obj))
   134     {
   135 incref();
   136     }
   137 
   138     static inline Root<T> New(Handle<T> other);
   139 
   140     ~Root() {
   141         decref();
   142     }
   143 
   144     Root<T> &operator =(const Root<T> &other) {
   145         decref();
   146         this->obj_ = other.obj_;
   147         incref();
   148         return *this;
   149     }
   150 
   151   private:
   152     void incref();
   153     void decref();
   154 };
   155 
   156 /*
   157  * A HandleScope is where Local roots are allcoated. When the HandleScope
   158  * is destroyed, all Handles created under it are also destroyed. HandleScopes
   159  * may only be allocated on the stack, in LIFO order.
   160  */
   161 class HandleScope
   162 {
   163   protected:
   164     ke::Zone *zone_;
   165     ke::Object **position_;
   166     HandleScope *prev_;
   167 
   168     HandleScope(ke::Zone *zone, ke::Object **position, HandleScope *prev)
   169       : zone_(zone),
   170         position_(position),
   171         prev_(prev)
   172     {
   173     }
   174 
   175   public:
   176     HandleScope();
   177     ~HandleScope();
   178 
   179     static ke::Object **CreateHandle(ke::Object *obj);
   180 
   181   private:
   182     // Disallow silly stuff.
   183     HandleScope(const HandleScope &);
   184     void operator =(const HandleScope &);
   185     void *operator new (size_t size);
   186     void operator delete(void *, size_t);
   187 };
   188 
   189 class Parameter;
   190 
   191 // Error messages are pumped through this interface.
   192 class IMessageReporter
   193 {
   194   public:
   195     virtual void onOutOfMemory() {
   196     }
   197     virtual void onUncaughtException(const char *message) {
   198     }
   199     virtual void beginCompilationErrors(const char *file) {
   200     }
   201     virtual void reportCompilationError(const char *message, unsigned line, unsigned col) {
   202     }
   203     virtual void endCompilationErrors() {
   204     }
   205 };
   206 
   207 // For the purposes of error reporting, very basic information can be queried
   208 // about the stack frame. This structure may be used to retrieve such
   209 // information. During iteration, it is illegal to re-enter any scripted code
   210 // or call any Keima functions that may cause garbage collection.
   211 class IStackFrameIterator
   212 {
   213   public:
   214     virtual ~IStackFrameIterator() { }
   215 
   216     // Returns true if there are more frames, false otherwise.
   217     virtual bool done() = 0;
   218 
   219     // Returns the name of the current function. This may be NULL if the
   220     // function is anonymous.
   221     virtual const char *function() = 0;
   222 
   223     // Returns the file of the current function. This will return an invalid
   224     // path for C++ functions (for example, "<native>").
   225     virtual const char *source() = 0;
   226 
   227     // Returns the line number currently executing on this frame. For C++
   228     // functions, this is always 0.
   229     virtual unsigned lineNumber() = 0;
   230 
   231     // Advance to the previous frame in the call stack.
   232     virtual void prev() = 0;
   233 };
   234 
   235 // A string is an immutable UTF8 buffer.
   236 class KE_EXPORT String
   237 {
   238   public:
   239     // Returns the length of the string, in bytes.
   240     unsigned length();
   241 
   242     // Returns the character buffer of the string, or NULL on failure. If the
   243     // string is interned, chars() is guaranteed to succeed.
   244     const char *chars();
   245 };
   246 
   247 // A function is an executable unit of code.
   248 class KE_EXPORT Function
   249 {
   250   public:
   251     // Returns the name of a function, which may be NULL. If not NULL, the
   252     // string is guaranteed to be interned.
   253     Local<String> name();
   254 };
   255 
   256 // A native is an ISourcePawnEngine-compatible function provided by C++.
   257 class KE_EXPORT Native
   258 {
   259   public:
   260     // Returns the name of a native, which is never NULL. The string is
   261     // guaranteed to be interned.
   262     Local<String> name();
   263 
   264     // Returns the function pointer of the native.
   265     void *function();
   266 
   267     // Sets the function pointer of the native.
   268     void bind(void *function);
   269 };
   270 
   271 // A module represents a single compiled file, and contains functions and
   272 // global variables for that file (as well as exported types).
   273 class KE_EXPORT Module
   274 {
   275   public:
   276     // Returns publics that are based on forwards.
   277     unsigned numPublics();
   278     Local<Function> getPublic(unsigned index);
   279 
   280     // Returns natives.
   281     unsigned numNatives();
   282     Local<Native> getNative(unsigned index);
   283 
   284     // Sets the native identity pointer, which is passed as the first argument
   285     // to natives.
   286     void setNativeIdentity(void *ptr);
   287 };
   288 
   289 class Keima
   290 {
   291   public:
   292     /*
   293      * Initializes the Keima engine. This must be called exactly once before any
   294      * other Keima functions are called. After this, it is safe to use Keima
   295      * on the calling thread.
   296      */
   297     static bool Initialize();
   298 
   299     /*
   300      * Shuts down the Keima engine and frees data structures on all threads.
   301      */
   302     static void Shutdown();
   303 
   304     /*
   305      * Searches the call stack and returns true if the given module has any
   306      * active code running. This is an O(n) algorithm.
   307      */
   308     static bool IsInCallStack(Handle<Module> module);
   309 
   310     /*
   311      * Reclaim as much memory as possible. This pauses the calling thread
   312      * until garbage collection completes.
   313      */
   314     static void CollectGarbage();
   315 
   316     /*
   317      * Clear any pending exception.
   318      */
   319     static void ClearPendingException();
   320 
   321     /*
   322      * Type checks a function against given parameters.
   323      */
   324     static bool CheckInvokeTypes(Handle<Function> fun, const Parameter *params, unsigned nparams);
   325 
   326     /*
   327      * Executes a function with the given parameters. This interface is
   328      * intended for compatibility with SourceMod's ISourcePawnEngine2 and
   329      * should not be used otherwise, since it is intended to support only
   330      * a small subset of the core language.
   331      */
   332     static bool Invoke(Handle<Function> fun, const Parameter *params, unsigned nparams, int *result);
   333 
   334     /*
   335      * Sets the global message handler through which errors will be reported
   336      */
   337     static void InstallMessageReporter(IMessageReporter *reporter);
   338 
   339     static IStackFrameIterator *NewStackFrameIterator();
   340 };
   341 
   342 /*
   343  * Suppresses exceptions. This is useful for calling API functions. When this
   344  * in scope, errors will be reported, but the exception will be cleared after.
   345  */
   346 class AutoClearExceptions
   347 {
   348   public:
   349     ~AutoClearExceptions()
   350     {
   351         Keima::ClearPendingException();
   352     }
   353 };
   354 
   355 // Argument-passing interface for Invoke().
   356 class Parameter
   357 {
   358   public:
   359     enum Type {
   360         Int,
   361         Float,
   362         IntRef,
   363         FloatRef,
   364         Array,
   365         CharArray
   366     };
   367 
   368     Parameter()
   369     {
   370     }
   371 
   372     Parameter(int i)
   373       : type_(Int)
   374     {
   375         u.i = i;
   376     }
   377 
   378     Parameter(int *i, bool writeback)
   379       : type_(IntRef),
   380         writeback_(writeback)
   381     {
   382         u.ip = i;
   383     }
   384 
   385     Parameter(float f)
   386       : type_(Float)
   387     {
   388         u.f = f;
   389     }
   390 
   391     Parameter(float *f, bool writeback)
   392       : type_(FloatRef),
   393         writeback_(writeback)
   394     {
   395         u.fp = f;
   396     }
   397 
   398     Parameter(Type type, void *buffer, size_t length, bool writeback)
   399       : type_(type),
   400         writeback_(writeback),
   401         length_(length)
   402     {
   403         assert(type == Array || type == CharArray);
   404         u.buffer = buffer;
   405     }
   406 
   407     Type type() const {
   408         return type_;
   409     }
   410 
   411     int i32() const {
   412         assert(type() == Int);
   413         return u.i;
   414     }
   415     float f() const {
   416         assert(type() == Float);
   417         return u.f;
   418     }
   419     int *i32p() const {
   420         assert(type() == IntRef);
   421         return u.ip;
   422     }
   423     float *fp() const {
   424         assert(type() == FloatRef);
   425         return u.fp;
   426     }
   427     bool writeback() const {
   428         assert(type() >= IntRef && type() <= CharArray);
   429         return writeback_;
   430     }
   431     size_t length() const {
   432         return length_;
   433     }
   434     void *buffer() const {
   435         assert(type() == Array || type() == CharArray);
   436         return u.buffer;
   437     }
   438 
   439   private:
   440     Type type_;
   441     bool writeback_;
   442     size_t length_;
   443 
   444     union {
   445         int i;
   446         float f;
   447         int *ip;
   448         float *fp;
   449         void *buffer;
   450     } u;
   451 };
   452 
   453 /*
   454  * Compiles a file and returns a Module.
   455  */
   456 extern Local<Module> Compile(const char *path);
   457 
   458 class Internals
   459 {
   460     template <typename T> friend class Root;
   461 
   462   private:
   463     static ke::HeapRoot *NewHeapRoot(ke::Object **objp);
   464     static void IncRef(ke::HeapRoot *root);
   465     static void DecRef(ke::HeapRoot *root);
   466 };
   467 
   468 template <typename T> Root<T>
   469 Root<T>::New(Handle<T> other)
   470 {
   471     if (!other)
   472         return Root<T>();
   473     ke::Object **ptr = reinterpret_cast<ke::Object **>(*other);
   474     return Root<T>(Internals::NewHeapRoot(ptr));
   475 }
   476 
   477 template <typename T> void
   478 Root<T>::incref()
   479 {
   480     if (!*this)
   481         return;
   482     ke::HeapRoot *ptr = reinterpret_cast<ke::HeapRoot *>(**this);
   483     Internals::IncRef(ptr);
   484 }
   485 
   486 template <typename T> void
   487 Root<T>::decref()
   488 {
   489     if (!*this)
   490         return;
   491     ke::HeapRoot *ptr = reinterpret_cast<ke::HeapRoot *>(**this);
   492     Internals::DecRef(ptr);
   493 }
   494 
   495 }
   496 
   497 #endif // _include_sourcepawn2_api_h_