src/API.cpp
author David Anderson <dvander@alliedmods.net>
Sun Jul 29 12:24:49 2012 -0700 (2012-07-29)
changeset 129 86b368a4d80d
parent 92 e3974e7360e9
child 145 e9d804821c48
permissions -rw-r--r--
Fix various error reporting bugs related to Invoke.
dvander@61
     1
/* vim: set ts=4 sw=4 tw=99 et:
dvander@61
     2
 *
dvander@61
     3
 * Copyright (C) 2012 David Anderson
dvander@61
     4
 *
dvander@61
     5
 * This file is part of JITCraft.
dvander@61
     6
 *
dvander@61
     7
 * JITCraft is free software: you can redistribute it and/or modify it under
dvander@61
     8
 * the terms of the GNU General Public License as published by the Free
dvander@61
     9
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@61
    10
 * any later version.
dvander@61
    11
 * 
dvander@61
    12
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@61
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@61
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@61
    15
 *
dvander@61
    16
 * You should have received a copy of the GNU General Public License along with
dvander@61
    17
 * JITCraft. If not, see http://www.gnu.org/licenses/.
dvander@61
    18
 */
danderson@92
    19
#include <string.h>
dvander@61
    20
#include "../include/keima.h"
dvander@61
    21
#include "Zone.h"
dvander@61
    22
#include "RootScopes.h"
dvander@61
    23
#include "CompileContext.h"
dvander@61
    24
#include "Parser.h"
dvander@61
    25
#include "Scopes.h"
dvander@61
    26
#include "SemanticAnalysis.h"
dvander@61
    27
#include "BytecodeCompiler.h"
dvander@61
    28
#include "Modules.h"
dvander@61
    29
#include "GlobalRoots.h"
dvander@65
    30
#include "Reference.h"
dvander@65
    31
#include "Array.h"
dvander@65
    32
#include "Interpreter.h"
dvander@69
    33
#include "Stack.h"
dvander@70
    34
#include "Strings.h"
danderson@92
    35
#include "Spaces-inl.h"
danderson@92
    36
#include "Heap-inl.h"
dvander@61
    37
dvander@61
    38
using namespace ke;
dvander@61
    39
dvander@61
    40
bool
dvander@62
    41
Ke::Keima::Initialize()
dvander@61
    42
{
dvander@61
    43
    SingleThreadedZone = new Zone();
dvander@61
    44
    if (!SingleThreadedZone || !SingleThreadedZone->initialize())
dvander@61
    45
        return false;
dvander@61
    46
    return true;
dvander@61
    47
}
dvander@61
    48
dvander@61
    49
void
dvander@62
    50
Ke::Keima::Shutdown()
dvander@61
    51
{
dvander@61
    52
    delete SingleThreadedZone;
dvander@61
    53
    SingleThreadedZone = NULL;
dvander@61
    54
}
dvander@61
    55
dvander@60
    56
Ke::HandleScope::HandleScope()
dvander@60
    57
  : zone_(ke::ZONE()),
dvander@60
    58
    position_(zone_->rootScopes().position()),
dvander@60
    59
    prev_(*zone_->rootScopes().scope())
dvander@60
    60
{
dvander@60
    61
    *zone_->rootScopes().scope() = this;
dvander@60
    62
}
dvander@60
    63
dvander@61
    64
Ke::HandleScope::~HandleScope()
dvander@61
    65
{
dvander@61
    66
    zone_->rootScopes().unwind(position_);
dvander@61
    67
    *zone_->rootScopes().scope() = prev_;
dvander@61
    68
}
dvander@61
    69
dvander@61
    70
ke::Object **
dvander@61
    71
Ke::HandleScope::CreateHandle(ke::Object *obj)
dvander@61
    72
{
dvander@61
    73
    if (!obj)
dvander@61
    74
        return NULL;
dvander@61
    75
dvander@61
    76
    return ZONE()->rootScopes().make(obj);
dvander@61
    77
}
dvander@61
    78
dvander@62
    79
template <typename From, typename To> static inline To *
dvander@62
    80
Open(Ke::Handle<From> from)
dvander@62
    81
{
dvander@62
    82
    return *reinterpret_cast<To **>(*from);
dvander@62
    83
}
dvander@62
    84
dvander@64
    85
template <typename From, typename To> static inline To *
dvander@64
    86
Open(From *from)
dvander@64
    87
{
dvander@64
    88
    return *reinterpret_cast<To **>(from);
dvander@64
    89
}
dvander@64
    90
dvander@61
    91
template <typename From, typename To> static inline Ke::Local<To>
dvander@64
    92
ToLocal(From *from)
dvander@61
    93
{
dvander@61
    94
    return Ke::Local<To>(reinterpret_cast<To *>(Ke::HandleScope::CreateHandle(from)));
dvander@61
    95
}
dvander@61
    96
dvander@61
    97
static ke::Module *
dvander@61
    98
CompileFromSource(CompileContext &cc, const char *path, const char *stream, size_t length)
dvander@61
    99
{
dvander@61
   100
    Parser parser(ZONE(), cc, stream, length);
dvander@61
   101
    ParseTree *tree = parser.parse();
dvander@61
   102
    if (!tree)
dvander@61
   103
        return NULL;
dvander@61
   104
    tree->dump(stdout);
dvander@61
   105
dvander@84
   106
    if (!Scope::Bind(cc, tree))
dvander@61
   107
        return NULL;
dvander@61
   108
dvander@61
   109
    SemanticAnalysis semantics(ZONE(), cc, tree);
dvander@61
   110
    if (!semantics.analyze())
dvander@61
   111
        return NULL;
dvander@61
   112
dvander@61
   113
    Scope::Allocate(tree);
dvander@61
   114
dvander@61
   115
    BytecodeCompiler compiler(ZONE(), tree, NULL);
dvander@85
   116
    ke::Local<Module> module(ke::ZONE(), compiler.compile());
dvander@85
   117
    if (!module)
dvander@85
   118
        return NULL;
dvander@85
   119
dvander@85
   120
    ke::InvokeArgs args;
dvander@85
   121
    if (!ke::ZONE()->stack().pushModuleFrame(module, args))
dvander@85
   122
        return NULL;
dvander@85
   123
    if (!ke::Interpret(ke::ZONE(), NULL, NULL))
dvander@85
   124
        return NULL;
dvander@85
   125
dvander@85
   126
    return module;
dvander@61
   127
}
dvander@61
   128
dvander@61
   129
Ke::Local<Ke::Module>
dvander@61
   130
Ke::Compile(const char *path)
dvander@61
   131
{
dvander@61
   132
    RootScope roots(ZONE());
dvander@69
   133
    CompileContext cc(ZONE(), path);
dvander@61
   134
dvander@61
   135
    char *bytes = NULL;
dvander@61
   136
    size_t length;
dvander@61
   137
    {
dvander@61
   138
        FILE *fp = fopen(path, "rb");
dvander@61
   139
        if (!fp) {
dvander@61
   140
            cc.reportError(SourcePosition(), Message_CantOpenFile);
dvander@61
   141
            return Ke::Local<Ke::Module>();
dvander@61
   142
        }
dvander@61
   143
dvander@61
   144
        if (fseek(fp, 0, SEEK_END)) {
dvander@61
   145
            cc.reportError(SourcePosition(), Message_ErrorSeekingFile);
dvander@61
   146
            fclose(fp);
dvander@61
   147
            return Ke::Local<Ke::Module>();;
dvander@61
   148
        }
dvander@61
   149
        long size = ftell(fp);
dvander@61
   150
        if (size < 0) {
dvander@61
   151
            cc.reportError(SourcePosition(), Message_ErrorSeekingFile);
dvander@61
   152
            fclose(fp);
dvander@61
   153
            return Ke::Local<Ke::Module>();;
dvander@61
   154
        }
dvander@61
   155
        rewind(fp);
dvander@61
   156
        length = size_t(size);
dvander@61
   157
        bytes = new char[length + 1];
dvander@61
   158
        if (fread(bytes, 1, length, fp) != length) {
dvander@61
   159
            cc.reportError(SourcePosition(), Message_ErrorReadingFile);
dvander@61
   160
            fclose(fp);
dvander@61
   161
            delete [] bytes;
dvander@61
   162
            return Ke::Local<Ke::Module>();;
dvander@61
   163
        }
dvander@61
   164
        fclose(fp);
dvander@61
   165
    }
dvander@61
   166
dvander@61
   167
    ke::Local<ke::Module> module(ZONE(),  CompileFromSource(cc, path, bytes, length));
dvander@61
   168
    delete [] bytes;
dvander@61
   169
    if (!module)
dvander@61
   170
        return Ke::Local<Ke::Module>();
dvander@61
   171
dvander@70
   172
    ke::Local<ke::String> pathstr(ZONE(), ke::String::New(ZONE(), path, Heap::Tenure_Old));
dvander@70
   173
    if (!pathstr)
dvander@70
   174
        return Ke::Local<Ke::Module>();
dvander@70
   175
dvander@70
   176
    module->setPath(pathstr);
dvander@61
   177
    return ToLocal<ke::Module, Ke::Module>(module);
dvander@61
   178
}
dvander@61
   179
dvander@69
   180
void
dvander@69
   181
Ke::Keima::InstallMessageReporter(Ke::IMessageReporter *reporter)
dvander@69
   182
{
dvander@69
   183
    ZONE()->installErrorReporter(reporter);
dvander@69
   184
}
dvander@69
   185
dvander@69
   186
class StackFrameIterator : public Ke::IStackFrameIterator
dvander@69
   187
{
dvander@69
   188
    StackIter iter_;
dvander@69
   189
dvander@69
   190
  public:
dvander@69
   191
    StackFrameIterator()
dvander@69
   192
      : iter_(ZONE())
dvander@69
   193
    {
dvander@69
   194
    }
dvander@69
   195
dvander@69
   196
    virtual bool done() {
dvander@69
   197
        return iter_.done();
dvander@69
   198
    }
dvander@69
   199
dvander@69
   200
    const char *function() {
dvander@69
   201
        return iter_.function();
dvander@69
   202
    }
dvander@69
   203
dvander@69
   204
    const char *source() {
dvander@69
   205
        return iter_.source();
dvander@69
   206
    }
dvander@69
   207
dvander@69
   208
    unsigned lineNumber() {
dvander@69
   209
        return iter_.lineNumber();
dvander@69
   210
    }
dvander@69
   211
dvander@69
   212
    void prev() {
dvander@69
   213
        iter_.prev();
dvander@69
   214
    }
dvander@69
   215
};
dvander@69
   216
dvander@69
   217
Ke::IStackFrameIterator *
dvander@69
   218
Ke::Keima::NewStackFrameIterator()
dvander@69
   219
{
dvander@69
   220
    return new StackFrameIterator();
dvander@69
   221
}
dvander@69
   222
dvander@61
   223
static inline ke::HeapRoot *
dvander@61
   224
FromAPI(ke::HeapRoot *from)
dvander@61
   225
{
dvander@61
   226
    ke::Address address = reinterpret_cast<ke::Address>(from);
dvander@61
   227
    address -= offsetof(ke::HeapRoot, obj);
dvander@61
   228
    return reinterpret_cast<ke::HeapRoot *>(address);
dvander@61
   229
}
dvander@61
   230
dvander@61
   231
ke::HeapRoot *
dvander@61
   232
Ke::Internals::NewHeapRoot(ke::Object **ptr)
dvander@61
   233
{
dvander@61
   234
    ke::Local<ke::Object> obj(ZONE(), *ptr);
dvander@61
   235
    ke::HeapRoot *root = ke::ZONE()->globalRoots()->create(obj);
dvander@61
   236
    if (!root)
dvander@61
   237
        return NULL;
dvander@61
   238
dvander@61
   239
    // Compute an interior pointer, so it looks like a Handle to an object.
dvander@61
   240
    return reinterpret_cast<ke::HeapRoot *>(&root->obj);
dvander@61
   241
}
dvander@61
   242
dvander@61
   243
void
dvander@61
   244
Ke::Internals::IncRef(ke::HeapRoot *root)
dvander@61
   245
{
dvander@61
   246
    ZONE()->globalRoots()->incref(FromAPI(root));
dvander@61
   247
}
dvander@61
   248
dvander@61
   249
void
dvander@61
   250
Ke::Internals::DecRef(ke::HeapRoot *root)
dvander@61
   251
{
dvander@61
   252
    ZONE()->globalRoots()->decref(FromAPI(root));
dvander@61
   253
}
dvander@62
   254
dvander@62
   255
bool
dvander@62
   256
Ke::Keima::IsInCallStack(Handle<Module> argModule)
dvander@62
   257
{
dvander@62
   258
    ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(argModule));
dvander@62
   259
    return ZONE()->stack().isInCallStack(module);
dvander@62
   260
}
dvander@62
   261
dvander@62
   262
void
dvander@62
   263
Ke::Keima::CollectGarbage()
dvander@62
   264
{
dvander@62
   265
    ke::ZONE()->heap().reclaim();
dvander@62
   266
}
dvander@64
   267
dvander@129
   268
void
dvander@129
   269
Ke::Keima::ClearPendingException()
dvander@129
   270
{
dvander@129
   271
    ke::ZONE()->clearPendingException();
dvander@129
   272
}
dvander@129
   273
dvander@64
   274
unsigned
dvander@64
   275
Ke::Module::numPublics()
dvander@64
   276
{
dvander@64
   277
    ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
dvander@65
   278
    if (!module->publics())
dvander@65
   279
        return 0;
dvander@64
   280
    return module->publics()->length();
dvander@64
   281
}
dvander@64
   282
dvander@64
   283
Ke::Local<Ke::Function>
dvander@64
   284
Ke::Module::getPublic(unsigned index)
dvander@64
   285
{
dvander@64
   286
    ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
dvander@64
   287
    ke::Local<ke::Function> fun(ke::ZONE(), ke::Function::cast(module->publics()->at(index)));
dvander@64
   288
    return ToLocal<ke::Function, Ke::Function>(fun);
dvander@64
   289
}
dvander@64
   290
dvander@64
   291
unsigned
dvander@68
   292
Ke::Module::numNatives()
dvander@68
   293
{
dvander@68
   294
    ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
dvander@68
   295
    if (!module->natives())
dvander@68
   296
        return 0;
dvander@68
   297
    return module->natives()->length();
dvander@68
   298
}
dvander@68
   299
dvander@68
   300
Ke::Local<Ke::Native>
dvander@68
   301
Ke::Module::getNative(unsigned index)
dvander@68
   302
{
dvander@68
   303
    ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
dvander@68
   304
    ke::Local<ke::Native> fun(ke::ZONE(), ke::Native::cast(module->natives()->at(index)));
dvander@68
   305
    return ToLocal<ke::Native, Ke::Native>(fun);
dvander@68
   306
}
dvander@68
   307
dvander@68
   308
void
dvander@68
   309
Ke::Module::setNativeIdentity(void *identity)
dvander@68
   310
{
dvander@68
   311
    ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
dvander@68
   312
    module->setNativeIdentity(identity);
dvander@68
   313
}
dvander@68
   314
dvander@68
   315
unsigned
dvander@64
   316
Ke::String::length()
dvander@64
   317
{
dvander@64
   318
    ke::Local<ke::String> obj(ke::ZONE(), Open<Ke::String, ke::String>(this));
dvander@64
   319
    return obj->length();
dvander@64
   320
}
dvander@64
   321
dvander@64
   322
const char *
dvander@64
   323
Ke::String::chars()
dvander@64
   324
{
dvander@64
   325
    ke::Local<ke::String> obj(ke::ZONE(), Open<Ke::String, ke::String>(this));
dvander@64
   326
    return obj->chars();
dvander@64
   327
}
dvander@64
   328
dvander@64
   329
Ke::Local<Ke::String>
dvander@64
   330
Ke::Function::name()
dvander@64
   331
{
dvander@64
   332
    ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(this));
dvander@64
   333
    return ToLocal<ke::String, Ke::String>(fun->name());
dvander@64
   334
}
dvander@65
   335
dvander@68
   336
Ke::Local<Ke::String>
dvander@68
   337
Ke::Native::name()
dvander@68
   338
{
dvander@68
   339
    ke::Local<ke::Native> native(ke::ZONE(), Open<Ke::Native, ke::Native>(this));
dvander@68
   340
    return ToLocal<ke::String, Ke::String>(native->name());
dvander@68
   341
}
dvander@68
   342
dvander@68
   343
void
dvander@68
   344
Ke::Native::bind(void *function)
dvander@68
   345
{
dvander@68
   346
    ke::Local<ke::Native> native(ke::ZONE(), Open<Ke::Native, ke::Native>(this));
dvander@68
   347
    native->bind(function);
dvander@68
   348
}
dvander@68
   349
dvander@129
   350
// :TODO: this leaks an interior pointer.
dvander@129
   351
static const char *
dvander@129
   352
GetTypeName(Type *type)
dvander@129
   353
{
dvander@129
   354
    if (type->isArray())
dvander@129
   355
        return "array";
dvander@129
   356
    if (type->isFunction())
dvander@129
   357
        return "function";
dvander@129
   358
    if (type->isVoid())
dvander@129
   359
        return "void";
dvander@129
   360
    if (type->isReference())
dvander@129
   361
        type = type->contained();
dvander@129
   362
    if (type->tag())
dvander@129
   363
        return type->tag()->chars();
dvander@129
   364
    return "int";
dvander@129
   365
}
dvander@129
   366
dvander@129
   367
static inline const char *
dvander@129
   368
GetInvokeTypeName(Ke::Parameter::Type type)
dvander@129
   369
{
dvander@129
   370
    switch (type) {
dvander@129
   371
      case Ke::Parameter::Array:
dvander@129
   372
        return "array";
dvander@129
   373
      case Ke::Parameter::CharArray:
dvander@129
   374
        return "String";
dvander@129
   375
      case Ke::Parameter::Float:
dvander@129
   376
        return "Float";
dvander@129
   377
      case Ke::Parameter::FloatRef:
dvander@129
   378
        return "&Float";
dvander@129
   379
      case Ke::Parameter::Int:
dvander@129
   380
        return "int";
dvander@129
   381
      case Ke::Parameter::IntRef:
dvander@129
   382
        return "&int";
dvander@129
   383
      default:
dvander@129
   384
        return "<unknown>";
dvander@129
   385
    }
dvander@129
   386
}
dvander@129
   387
dvander@65
   388
static inline bool
dvander@65
   389
CheckInvokeType(const Ke::Parameter &param, Type *type)
dvander@65
   390
{
dvander@65
   391
    switch (param.type()) {
dvander@65
   392
      case Ke::Parameter::Array:
dvander@65
   393
        return type->isArray() &&
dvander@65
   394
               type->levels() == 1 &&
dvander@65
   395
               type->contained()->isPrimitive() &&
dvander@65
   396
               (type->contained()->primitive() != PrimitiveType_Char);
dvander@65
   397
      case Ke::Parameter::CharArray:
dvander@65
   398
        return type->isCharArray();
dvander@65
   399
      case Ke::Parameter::Float:
dvander@65
   400
        return type->isFloat();
dvander@65
   401
      case Ke::Parameter::FloatRef:
dvander@65
   402
        return type->isReference() && type->contained()->isFloat();
dvander@65
   403
      case Ke::Parameter::Int:
dvander@65
   404
        return type->isInt32();
dvander@65
   405
      case Ke::Parameter::IntRef:
dvander@65
   406
       return type->isReference() && type->contained()->isInt32();
dvander@65
   407
      default:
dvander@65
   408
        return false;
dvander@65
   409
    }
dvander@65
   410
}
dvander@65
   411
dvander@129
   412
static bool
dvander@129
   413
CheckInvokeTypes(Ke::Handle<Ke::Function> argFun, const Ke::Parameter *params, unsigned nparams)
dvander@65
   414
{
dvander@65
   415
    ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(argFun));
dvander@65
   416
dvander@65
   417
    if (fun->nargs() != nparams)
dvander@65
   418
        return false;
dvander@65
   419
dvander@65
   420
    for (unsigned i = 0; i < nparams; i++) {
dvander@129
   421
        if (!CheckInvokeType(params[i], fun->argType(i))) {
dvander@129
   422
            ke::ZONE()->reportError(Message_TypeMismatchDuringInvoke,
dvander@129
   423
                                    GetInvokeTypeName(params[i].type()),
dvander@129
   424
                                    GetTypeName(fun->argType(i)));
dvander@65
   425
            return false;
dvander@129
   426
        }
dvander@65
   427
    }
dvander@65
   428
dvander@65
   429
    // Functions can only return tagged cells, for ISPE1-compatible Invoke().
dvander@72
   430
    ke::Local<ke::Type> returnType(ke::ZONE(), fun->type()->returnType());
dvander@129
   431
    if (!returnType->isPrimitive() && !returnType->isVoid()) {
dvander@129
   432
        ke::ZONE()->reportError(Message_CannotInvokeReturnType, GetTypeName(returnType));
dvander@65
   433
        return false;
dvander@129
   434
    }
dvander@65
   435
dvander@65
   436
    return true;
dvander@65
   437
}
dvander@65
   438
dvander@65
   439
bool
dvander@129
   440
Ke::Keima::Invoke(Handle<Function> argFun, const Parameter *params, unsigned nparams,
dvander@129
   441
                  bool checkTypes, int *retval)
dvander@65
   442
{
dvander@65
   443
    assert(CheckInvokeTypes(argFun, params, nparams));
dvander@65
   444
dvander@65
   445
    ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(argFun));
dvander@65
   446
dvander@65
   447
    if (fun->nargs() != nparams) {
dvander@65
   448
        // :TODO: report error
dvander@65
   449
        assert(false);
dvander@65
   450
        return false;
dvander@65
   451
    }
dvander@65
   452
dvander@65
   453
    ke::InvokeArgs args;
dvander@65
   454
    if (!ke::ZONE()->stack().pushInvokeFrame(fun, args))
dvander@65
   455
        return false;
dvander@65
   456
dvander@129
   457
    if (checkTypes && !CheckInvokeTypes(argFun, params, nparams))
dvander@129
   458
        return false;
dvander@129
   459
dvander@65
   460
    for (unsigned i = 0; i < nparams; i++) {
dvander@65
   461
        ke::LocalSlot &slot = args.arg(i);
dvander@65
   462
        switch (params[i].type()) {
dvander@65
   463
          case Ke::Parameter::Int:
dvander@65
   464
            slot.i32 = params[i].i32();
dvander@65
   465
            break;
dvander@65
   466
dvander@65
   467
          case Ke::Parameter::Float:
dvander@65
   468
            slot.f = params[i].f();
dvander@65
   469
            break;
dvander@65
   470
dvander@65
   471
          case Ke::Parameter::IntRef:
dvander@65
   472
            if (params[i].writeback()) {
dvander@65
   473
                slot.ref = Reference::NewStack(ke::ZONE(), params[i].i32p(), Heap::Tenure_Stack);
dvander@65
   474
            } else {
dvander@65
   475
                LocalSlot other;
dvander@65
   476
                other.i32 = *params[i].i32p();
dvander@65
   477
                slot.ref = Reference::NewStack(ke::ZONE(), other, Heap::Tenure_Stack);
dvander@65
   478
            }
dvander@65
   479
            if (!slot.ref)
dvander@65
   480
                return false;
dvander@65
   481
            break;
dvander@65
   482
dvander@65
   483
          case Ke::Parameter::FloatRef:
dvander@65
   484
            if (params[i].writeback()) {
dvander@65
   485
                slot.ref = Reference::NewStack(ke::ZONE(), params[i].fp(), Heap::Tenure_Stack);
dvander@65
   486
            } else {
dvander@65
   487
                LocalSlot other;
dvander@65
   488
                other.f = *params[i].fp();
dvander@65
   489
                slot.ref = Reference::NewStack(ke::ZONE(), other, Heap::Tenure_Stack);
dvander@65
   490
            }
dvander@65
   491
            if (!slot.ref)
dvander@65
   492
                return false;
dvander@65
   493
            break;
dvander@65
   494
dvander@65
   495
          case Ke::Parameter::Array:
dvander@65
   496
          {
dvander@65
   497
            ke::Local<ke::ArrayMap> map(ke::ZONE(), ke::ZONE()->genericArrayMap());
dvander@65
   498
            if (params[i].writeback()) {
dvander@65
   499
                slot.obj = Array::NewExternal(ke::ZONE(), map, params[i].length(),
dvander@65
   500
                                              params[i].buffer(), Heap::Tenure_Stack);
dvander@65
   501
                if (!slot.obj)
dvander@65
   502
                    return false;
dvander@65
   503
            } else {
dvander@65
   504
                Array *array = Array::New(ke::ZONE(), map, params[i].length(), Heap::Tenure_Stack);
dvander@65
   505
                if (!slot.obj)
dvander@65
   506
                    return false;
dvander@65
   507
                memcpy(array->vec(), params[i].buffer(), params[i].length() * sizeof(int));
dvander@65
   508
            }
dvander@65
   509
            break;
dvander@65
   510
          }
dvander@65
   511
dvander@65
   512
          case Ke::Parameter::CharArray:
dvander@65
   513
          {
dvander@65
   514
            ke::Local<ke::ArrayMap> map(ke::ZONE(), ke::ZONE()->charArrayMap());
dvander@65
   515
            if (params[i].writeback()) {
dvander@65
   516
                slot.obj = Array::NewExternal(ke::ZONE(), map, params[i].length(),
dvander@65
   517
                                              params[i].buffer(), Heap::Tenure_Stack);
dvander@65
   518
                if (!slot.obj)
dvander@65
   519
                    return false;
dvander@65
   520
            } else {
dvander@65
   521
                Array *array = Array::New(ke::ZONE(), map, params[i].length(), Heap::Tenure_Stack);
dvander@65
   522
                if (!slot.obj)
dvander@65
   523
                    return false;
dvander@65
   524
                memcpy(array->vec(), params[i].buffer(), params[i].length() * sizeof(char));
dvander@65
   525
            }
dvander@65
   526
            break;
dvander@65
   527
          }
dvander@65
   528
        }
dvander@65
   529
    }
dvander@65
   530
dvander@65
   531
    LocalSlot result;
dvander@65
   532
    if (!Interpret(ke::ZONE(), NULL, &result))
dvander@65
   533
        return false;
dvander@65
   534
dvander@72
   535
    if (fun->type()->returnType()->isVoid())
dvander@72
   536
        result.i32 = 0;
dvander@72
   537
dvander@65
   538
    *retval = result.i32;
dvander@65
   539
    return true;
dvander@65
   540
}