jitcraft/API.cpp
author David Anderson <dvander@alliedmods.net>
Sun Jul 08 11:33:12 2012 -0700 (2012-07-08)
changeset 61 864e4b02a4c1
parent 60 581a9c793062
child 62 e04c5be84792
permissions -rw-r--r--
Added global root API.
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@61
    33
Ke::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@61
    42
Ke::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@61
    71
template <typename From, typename To> static inline Ke::Local<To>
dvander@61
    72
ToLocal(Handle<From> from)
dvander@61
    73
{
dvander@61
    74
    return Ke::Local<To>(reinterpret_cast<To *>(Ke::HandleScope::CreateHandle(from)));
dvander@61
    75
}
dvander@61
    76
dvander@61
    77
static ke::Module *
dvander@61
    78
CompileFromSource(CompileContext &cc, const char *path, const char *stream, size_t length)
dvander@61
    79
{
dvander@61
    80
    Parser parser(ZONE(), cc, stream, length);
dvander@61
    81
    ParseTree *tree = parser.parse();
dvander@61
    82
    if (!tree)
dvander@61
    83
        return NULL;
dvander@61
    84
    tree->dump(stdout);
dvander@61
    85
dvander@61
    86
    if (!Scope::Bind(tree))
dvander@61
    87
        return NULL;
dvander@61
    88
dvander@61
    89
    SemanticAnalysis semantics(ZONE(), cc, tree);
dvander@61
    90
    if (!semantics.analyze())
dvander@61
    91
        return NULL;
dvander@61
    92
dvander@61
    93
    Scope::Allocate(tree);
dvander@61
    94
dvander@61
    95
    BytecodeCompiler compiler(ZONE(), tree, NULL);
dvander@61
    96
    return compiler.compile();
dvander@61
    97
}
dvander@61
    98
dvander@61
    99
Ke::Local<Ke::Module>
dvander@61
   100
Ke::Compile(const char *path)
dvander@61
   101
{
dvander@61
   102
    RootScope roots(ZONE());
dvander@61
   103
    CompileContext cc(ZONE());
dvander@61
   104
dvander@61
   105
    char *bytes = NULL;
dvander@61
   106
    size_t length;
dvander@61
   107
    {
dvander@61
   108
        FILE *fp = fopen(path, "rb");
dvander@61
   109
        if (!fp) {
dvander@61
   110
            cc.reportError(SourcePosition(), Message_CantOpenFile);
dvander@61
   111
            return Ke::Local<Ke::Module>();
dvander@61
   112
        }
dvander@61
   113
dvander@61
   114
        if (fseek(fp, 0, SEEK_END)) {
dvander@61
   115
            cc.reportError(SourcePosition(), Message_ErrorSeekingFile);
dvander@61
   116
            fclose(fp);
dvander@61
   117
            return Ke::Local<Ke::Module>();;
dvander@61
   118
        }
dvander@61
   119
        long size = ftell(fp);
dvander@61
   120
        if (size < 0) {
dvander@61
   121
            cc.reportError(SourcePosition(), Message_ErrorSeekingFile);
dvander@61
   122
            fclose(fp);
dvander@61
   123
            return Ke::Local<Ke::Module>();;
dvander@61
   124
        }
dvander@61
   125
        rewind(fp);
dvander@61
   126
        length = size_t(size);
dvander@61
   127
        bytes = new char[length + 1];
dvander@61
   128
        if (fread(bytes, 1, length, fp) != length) {
dvander@61
   129
            cc.reportError(SourcePosition(), Message_ErrorReadingFile);
dvander@61
   130
            fclose(fp);
dvander@61
   131
            delete [] bytes;
dvander@61
   132
            return Ke::Local<Ke::Module>();;
dvander@61
   133
        }
dvander@61
   134
        fclose(fp);
dvander@61
   135
    }
dvander@61
   136
dvander@61
   137
    ke::Local<ke::Module> module(ZONE(),  CompileFromSource(cc, path, bytes, length));
dvander@61
   138
    delete [] bytes;
dvander@61
   139
    if (!module)
dvander@61
   140
        return Ke::Local<Ke::Module>();
dvander@61
   141
dvander@61
   142
    return ToLocal<ke::Module, Ke::Module>(module);
dvander@61
   143
}
dvander@61
   144
dvander@61
   145
static inline ke::HeapRoot *
dvander@61
   146
FromAPI(ke::HeapRoot *from)
dvander@61
   147
{
dvander@61
   148
    ke::Address address = reinterpret_cast<ke::Address>(from);
dvander@61
   149
    address -= offsetof(ke::HeapRoot, obj);
dvander@61
   150
    return reinterpret_cast<ke::HeapRoot *>(address);
dvander@61
   151
}
dvander@61
   152
dvander@61
   153
ke::HeapRoot *
dvander@61
   154
Ke::Internals::NewHeapRoot(ke::Object **ptr)
dvander@61
   155
{
dvander@61
   156
    ke::Local<ke::Object> obj(ZONE(), *ptr);
dvander@61
   157
    ke::HeapRoot *root = ke::ZONE()->globalRoots()->create(obj);
dvander@61
   158
    if (!root)
dvander@61
   159
        return NULL;
dvander@61
   160
dvander@61
   161
    // Compute an interior pointer, so it looks like a Handle to an object.
dvander@61
   162
    return reinterpret_cast<ke::HeapRoot *>(&root->obj);
dvander@61
   163
}
dvander@61
   164
dvander@61
   165
void
dvander@61
   166
Ke::Internals::IncRef(ke::HeapRoot *root)
dvander@61
   167
{
dvander@61
   168
    ZONE()->globalRoots()->incref(FromAPI(root));
dvander@61
   169
}
dvander@61
   170
dvander@61
   171
void
dvander@61
   172
Ke::Internals::DecRef(ke::HeapRoot *root)
dvander@61
   173
{
dvander@61
   174
    ZONE()->globalRoots()->decref(FromAPI(root));
dvander@61
   175
}