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