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