jitcraft/API.cpp
author David Anderson <dvander@alliedmods.net>
Sun Jul 08 17:57:44 2012 -0700 (2012-07-08)
changeset 64 11c81eb30246
parent 62 e04c5be84792
child 65 7c942b5adebc
permissions -rw-r--r--
Added API for looking at module public functions.
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
 */
dvander@61
    19
#include "../include/keima.h"
dvander@61
    20
#include "Zone.h"
dvander@61
    21
#include "RootScopes.h"
dvander@61
    22
#include "CompileContext.h"
dvander@61
    23
#include "Parser.h"
dvander@61
    24
#include "Scopes.h"
dvander@61
    25
#include "SemanticAnalysis.h"
dvander@61
    26
#include "BytecodeCompiler.h"
dvander@61
    27
#include "Modules.h"
dvander@61
    28
#include "GlobalRoots.h"
dvander@61
    29
dvander@61
    30
using namespace ke;
dvander@61
    31
dvander@61
    32
bool
dvander@62
    33
Ke::Keima::Initialize()
dvander@61
    34
{
dvander@61
    35
    SingleThreadedZone = new Zone();
dvander@61
    36
    if (!SingleThreadedZone || !SingleThreadedZone->initialize())
dvander@61
    37
        return false;
dvander@61
    38
    return true;
dvander@61
    39
}
dvander@61
    40
dvander@61
    41
void
dvander@62
    42
Ke::Keima::Shutdown()
dvander@61
    43
{
dvander@61
    44
    delete SingleThreadedZone;
dvander@61
    45
    SingleThreadedZone = NULL;
dvander@61
    46
}
dvander@61
    47
dvander@60
    48
Ke::HandleScope::HandleScope()
dvander@60
    49
  : zone_(ke::ZONE()),
dvander@60
    50
    position_(zone_->rootScopes().position()),
dvander@60
    51
    prev_(*zone_->rootScopes().scope())
dvander@60
    52
{
dvander@60
    53
    *zone_->rootScopes().scope() = this;
dvander@60
    54
}
dvander@60
    55
dvander@61
    56
Ke::HandleScope::~HandleScope()
dvander@61
    57
{
dvander@61
    58
    zone_->rootScopes().unwind(position_);
dvander@61
    59
    *zone_->rootScopes().scope() = prev_;
dvander@61
    60
}
dvander@61
    61
dvander@61
    62
ke::Object **
dvander@61
    63
Ke::HandleScope::CreateHandle(ke::Object *obj)
dvander@61
    64
{
dvander@61
    65
    if (!obj)
dvander@61
    66
        return NULL;
dvander@61
    67
dvander@61
    68
    return ZONE()->rootScopes().make(obj);
dvander@61
    69
}
dvander@61
    70
dvander@62
    71
template <typename From, typename To> static inline To *
dvander@62
    72
Open(Ke::Handle<From> from)
dvander@62
    73
{
dvander@62
    74
    return *reinterpret_cast<To **>(*from);
dvander@62
    75
}
dvander@62
    76
dvander@64
    77
template <typename From, typename To> static inline To *
dvander@64
    78
Open(From *from)
dvander@64
    79
{
dvander@64
    80
    return *reinterpret_cast<To **>(from);
dvander@64
    81
}
dvander@64
    82
dvander@61
    83
template <typename From, typename To> static inline Ke::Local<To>
dvander@64
    84
ToLocal(From *from)
dvander@61
    85
{
dvander@61
    86
    return Ke::Local<To>(reinterpret_cast<To *>(Ke::HandleScope::CreateHandle(from)));
dvander@61
    87
}
dvander@61
    88
dvander@61
    89
static ke::Module *
dvander@61
    90
CompileFromSource(CompileContext &cc, const char *path, const char *stream, size_t length)
dvander@61
    91
{
dvander@61
    92
    Parser parser(ZONE(), cc, stream, length);
dvander@61
    93
    ParseTree *tree = parser.parse();
dvander@61
    94
    if (!tree)
dvander@61
    95
        return NULL;
dvander@61
    96
    tree->dump(stdout);
dvander@61
    97
dvander@61
    98
    if (!Scope::Bind(tree))
dvander@61
    99
        return NULL;
dvander@61
   100
dvander@61
   101
    SemanticAnalysis semantics(ZONE(), cc, tree);
dvander@61
   102
    if (!semantics.analyze())
dvander@61
   103
        return NULL;
dvander@61
   104
dvander@61
   105
    Scope::Allocate(tree);
dvander@61
   106
dvander@61
   107
    BytecodeCompiler compiler(ZONE(), tree, NULL);
dvander@61
   108
    return compiler.compile();
dvander@61
   109
}
dvander@61
   110
dvander@61
   111
Ke::Local<Ke::Module>
dvander@61
   112
Ke::Compile(const char *path)
dvander@61
   113
{
dvander@61
   114
    RootScope roots(ZONE());
dvander@61
   115
    CompileContext cc(ZONE());
dvander@61
   116
dvander@61
   117
    char *bytes = NULL;
dvander@61
   118
    size_t length;
dvander@61
   119
    {
dvander@61
   120
        FILE *fp = fopen(path, "rb");
dvander@61
   121
        if (!fp) {
dvander@61
   122
            cc.reportError(SourcePosition(), Message_CantOpenFile);
dvander@61
   123
            return Ke::Local<Ke::Module>();
dvander@61
   124
        }
dvander@61
   125
dvander@61
   126
        if (fseek(fp, 0, SEEK_END)) {
dvander@61
   127
            cc.reportError(SourcePosition(), Message_ErrorSeekingFile);
dvander@61
   128
            fclose(fp);
dvander@61
   129
            return Ke::Local<Ke::Module>();;
dvander@61
   130
        }
dvander@61
   131
        long size = ftell(fp);
dvander@61
   132
        if (size < 0) {
dvander@61
   133
            cc.reportError(SourcePosition(), Message_ErrorSeekingFile);
dvander@61
   134
            fclose(fp);
dvander@61
   135
            return Ke::Local<Ke::Module>();;
dvander@61
   136
        }
dvander@61
   137
        rewind(fp);
dvander@61
   138
        length = size_t(size);
dvander@61
   139
        bytes = new char[length + 1];
dvander@61
   140
        if (fread(bytes, 1, length, fp) != length) {
dvander@61
   141
            cc.reportError(SourcePosition(), Message_ErrorReadingFile);
dvander@61
   142
            fclose(fp);
dvander@61
   143
            delete [] bytes;
dvander@61
   144
            return Ke::Local<Ke::Module>();;
dvander@61
   145
        }
dvander@61
   146
        fclose(fp);
dvander@61
   147
    }
dvander@61
   148
dvander@61
   149
    ke::Local<ke::Module> module(ZONE(),  CompileFromSource(cc, path, bytes, length));
dvander@61
   150
    delete [] bytes;
dvander@61
   151
    if (!module)
dvander@61
   152
        return Ke::Local<Ke::Module>();
dvander@61
   153
dvander@61
   154
    return ToLocal<ke::Module, Ke::Module>(module);
dvander@61
   155
}
dvander@61
   156
dvander@61
   157
static inline ke::HeapRoot *
dvander@61
   158
FromAPI(ke::HeapRoot *from)
dvander@61
   159
{
dvander@61
   160
    ke::Address address = reinterpret_cast<ke::Address>(from);
dvander@61
   161
    address -= offsetof(ke::HeapRoot, obj);
dvander@61
   162
    return reinterpret_cast<ke::HeapRoot *>(address);
dvander@61
   163
}
dvander@61
   164
dvander@61
   165
ke::HeapRoot *
dvander@61
   166
Ke::Internals::NewHeapRoot(ke::Object **ptr)
dvander@61
   167
{
dvander@61
   168
    ke::Local<ke::Object> obj(ZONE(), *ptr);
dvander@61
   169
    ke::HeapRoot *root = ke::ZONE()->globalRoots()->create(obj);
dvander@61
   170
    if (!root)
dvander@61
   171
        return NULL;
dvander@61
   172
dvander@61
   173
    // Compute an interior pointer, so it looks like a Handle to an object.
dvander@61
   174
    return reinterpret_cast<ke::HeapRoot *>(&root->obj);
dvander@61
   175
}
dvander@61
   176
dvander@61
   177
void
dvander@61
   178
Ke::Internals::IncRef(ke::HeapRoot *root)
dvander@61
   179
{
dvander@61
   180
    ZONE()->globalRoots()->incref(FromAPI(root));
dvander@61
   181
}
dvander@61
   182
dvander@61
   183
void
dvander@61
   184
Ke::Internals::DecRef(ke::HeapRoot *root)
dvander@61
   185
{
dvander@61
   186
    ZONE()->globalRoots()->decref(FromAPI(root));
dvander@61
   187
}
dvander@62
   188
dvander@62
   189
bool
dvander@62
   190
Ke::Keima::IsInCallStack(Handle<Module> argModule)
dvander@62
   191
{
dvander@62
   192
    ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(argModule));
dvander@62
   193
    return ZONE()->stack().isInCallStack(module);
dvander@62
   194
}
dvander@62
   195
dvander@62
   196
void
dvander@62
   197
Ke::Keima::CollectGarbage()
dvander@62
   198
{
dvander@62
   199
    ke::ZONE()->heap().reclaim();
dvander@62
   200
}
dvander@64
   201
dvander@64
   202
unsigned
dvander@64
   203
Ke::Module::numPublics()
dvander@64
   204
{
dvander@64
   205
    ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
dvander@64
   206
    return module->publics()->length();
dvander@64
   207
}
dvander@64
   208
dvander@64
   209
Ke::Local<Ke::Function>
dvander@64
   210
Ke::Module::getPublic(unsigned index)
dvander@64
   211
{
dvander@64
   212
    ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
dvander@64
   213
    ke::Local<ke::Function> fun(ke::ZONE(), ke::Function::cast(module->publics()->at(index)));
dvander@64
   214
    return ToLocal<ke::Function, Ke::Function>(fun);
dvander@64
   215
}
dvander@64
   216
dvander@64
   217
unsigned
dvander@64
   218
Ke::String::length()
dvander@64
   219
{
dvander@64
   220
    ke::Local<ke::String> obj(ke::ZONE(), Open<Ke::String, ke::String>(this));
dvander@64
   221
    return obj->length();
dvander@64
   222
}
dvander@64
   223
dvander@64
   224
const char *
dvander@64
   225
Ke::String::chars()
dvander@64
   226
{
dvander@64
   227
    ke::Local<ke::String> obj(ke::ZONE(), Open<Ke::String, ke::String>(this));
dvander@64
   228
    return obj->chars();
dvander@64
   229
}
dvander@64
   230
dvander@64
   231
Ke::Local<Ke::String>
dvander@64
   232
Ke::Function::name()
dvander@64
   233
{
dvander@64
   234
    ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(this));
dvander@64
   235
    return ToLocal<ke::String, Ke::String>(fun->name());
dvander@64
   236
}