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