]> git.saurik.com Git - cycript.git/commitdiff
Factored out the execution engine from the compiler.
authorJay Freeman (saurik) <saurik@saurik.com>
Sun, 15 Nov 2009 22:51:29 +0000 (22:51 +0000)
committerJay Freeman (saurik) <saurik@saurik.com>
Sun, 15 Nov 2009 22:51:29 +0000 (22:51 +0000)
15 files changed:
Console.cpp
Cycript.y.in
Darwin-arm.mk
Darwin.mk
Error.hpp
Exception.hpp
Execute.cpp [new file with mode: 0644]
Execute.mk [new file with mode: 0644]
FreeBSD.mk
JavaScript.hpp
Library.cpp
Linux.mk
String.hpp
cycript.hpp
makefile

index 53571037ef6157d1e702462d2c474d938639204f..44cadc7ad470bb9c3584f26d8fc967ded222a752 100644 (file)
 
 #include "cycript.hpp"
 
+#ifdef CY_EXECUTE
+#include "JavaScript.hpp"
+#endif
+
 #include <cstdio>
 #include <sstream>
 
index e22535dc86c9ea2992b100a46ca28354e2b8d905..d4397730ebc88be855eee167ebe102bf8e319ca2 100644 (file)
@@ -324,7 +324,6 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %type <literal_> ArrayLiteral
 %type <expression_> AssigneeExpression
 %type <expression_> AssigneeExpressionNoBF
-%type <expression_> AssigneeExpressionNoRE
 %type <expression_> AssignmentExpression
 %type <assignment_> AssignmentExpression_
 %type <expression_> AssignmentExpressionNoBF
@@ -344,7 +343,6 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %type <statement_> BreakStatement
 %type <expression_> CallExpression
 %type <expression_> CallExpressionNoBF
-%type <expression_> CallExpressionNoRE
 %type <clause_> CaseBlock
 %type <clause_> CaseClause
 %type <clause_> CaseClausesOpt
@@ -397,7 +395,6 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %type <statement_> LabelledStatement
 %type <expression_> LeftHandSideExpression
 %type <expression_> LeftHandSideExpressionNoBF
-%type <expression_> LeftHandSideExpressionNoRE
 //%type <statement_> LetStatement
 %type <literal_> Literal
 %type <literal_> LiteralNoRE
@@ -412,18 +409,15 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %type <expression_> MemberExpression
 %type <expression_> MemberExpression_
 %type <expression_> MemberExpressionNoBF
-%type <expression_> MemberExpressionNoRE
 %type <expression_> MultiplicativeExpression
 %type <expression_> MultiplicativeExpressionNoBF
 %type <expression_> NewExpression
 %type <expression_> NewExpression_
 %type <expression_> NewExpressionNoBF
-%type <expression_> NewExpressionNoRE
 %type <null_> NullLiteral
 %type <literal_> ObjectLiteral
 %type <expression_> PostfixExpression
 %type <expression_> PostfixExpressionNoBF
-%type <expression_> PostfixExpressionNoRE
 %type <expression_> PrimaryExpression
 %type <expression_> PrimaryExpressionNo
 %type <expression_> PrimaryExpressionNoBF
@@ -453,11 +447,9 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %type <statement_> SwitchStatement
 %type <statement_> ThrowStatement
 %type <statement_> TryStatement
-%type <expression_> UnaryAssigneeExpression
 %type <expression_> UnaryExpression
 %type <expression_> UnaryExpression_
 %type <expression_> UnaryExpressionNoBF
-%type <expression_> UnaryExpressionNoRE
 %type <declaration_> VariableDeclaration
 %type <declaration_> VariableDeclarationNoIn
 %type <declarations_> VariableDeclarationList
@@ -468,6 +460,17 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %type <statement_> WhileStatement
 %type <statement_> WithStatement
 
+@begin C
+%type <expression_> AssigneeExpressionNoRE
+%type <expression_> CallExpressionNoRE
+%type <expression_> LeftHandSideExpressionNoRE
+%type <expression_> MemberExpressionNoRE
+%type <expression_> NewExpressionNoRE
+%type <expression_> PostfixExpressionNoRE
+%type <expression_> UnaryAssigneeExpression
+%type <expression_> UnaryExpressionNoRE
+@end
+
 @begin ObjectiveC
 %type <statement_> CategoryStatement
 %type <expression_> ClassExpression
@@ -792,12 +795,14 @@ MemberExpressionNoBF
     | MemberExpression_ { $$ = $1; }
     ;
 
+@begin C
 MemberExpressionNoRE
     : PrimaryExpressionNoRE { $$ = $1; }
     | FunctionExpression { $$ = $1; }
     | MemberExpressionNoRE MemberAccess { $2->SetLeft($1); $$ = $2; }
     | MemberExpression_ { $$ = $1; }
     ;
+@end
 
 NewExpression_
     : "new" NewExpression { $$ = new(driver.pool_) CYNew($2, NULL); }
@@ -813,10 +818,12 @@ NewExpressionNoBF
     | NewExpression_ { $$ = $1; }
     ;
 
+@begin C
 NewExpressionNoRE
     : MemberExpressionNoRE { $$ = $1; }
     | NewExpression_ { $$ = $1; }
     ;
+@end
 
 CallExpression
     : MemberExpression Arguments { $$ = new(driver.pool_) CYCall($1, $2); }
@@ -830,11 +837,13 @@ CallExpressionNoBF
     | CallExpressionNoBF MemberAccess { $2->SetLeft($1); $$ = $2; }
     ;
 
+@begin C
 CallExpressionNoRE
     : MemberExpressionNoRE Arguments { $$ = new(driver.pool_) CYCall($1, $2); }
     | CallExpressionNoRE Arguments { $$ = new(driver.pool_) CYCall($1, $2); }
     | CallExpressionNoRE MemberAccess { $2->SetLeft($1); $$ = $2; }
     ;
+@end
 
 ArgumentList_
     : "," ArgumentList { $$ = $2; }
@@ -864,10 +873,12 @@ LeftHandSideExpressionNoBF
     | CallExpressionNoBF { $$ = $1; }
     ;
 
+@begin C
 LeftHandSideExpressionNoRE
     : NewExpressionNoRE { $$ = $1; }
     | CallExpressionNoRE { $$ = $1; }
     ;
+@end
 /* }}} */
 /* 11.3 Postfix Expressions {{{ */
 PostfixExpression
@@ -882,11 +893,13 @@ PostfixExpressionNoBF
     | LeftHandSideExpressionNoBF "--" { $$ = new(driver.pool_) CYPostDecrement($1); }
     ;
 
+@begin C
 PostfixExpressionNoRE
     : AssigneeExpressionNoRE { $$ = $1; }
     | LeftHandSideExpressionNoRE "++" { $$ = new(driver.pool_) CYPostIncrement($1); }
     | LeftHandSideExpressionNoRE "--" { $$ = new(driver.pool_) CYPostDecrement($1); }
     ;
+@end
 /* }}} */
 /* 11.4 Unary Operators {{{ */
 UnaryExpression_
@@ -913,10 +926,12 @@ UnaryExpressionNoBF
     | UnaryExpression_ { $$ = $1; }
     ;
 
+@begin C
 UnaryExpressionNoRE
     : PostfixExpressionNoRE { $$ = $1; }
     | UnaryExpression_ { $$ = $1; }
     ;
+@end
 /* }}} */
 /* 11.5 Multiplicative Operators {{{ */
 MultiplicativeExpression
@@ -1126,18 +1141,24 @@ AssignmentExpression_
 
 AssigneeExpression
     : LeftHandSideExpression { $$ = $1; }
+@begin C
     | LexSetRegExp UnaryAssigneeExpression { $$ = $2; }
+@end
     ;
 
 AssigneeExpressionNoBF
     : LeftHandSideExpressionNoBF { $$ = $1; }
+@begin C
     | UnaryAssigneeExpression { $$ = $1; }
+@end
     ;
 
+@begin C
 AssigneeExpressionNoRE
     : LeftHandSideExpressionNoRE { $$ = $1; }
     | UnaryAssigneeExpression { $$ = $1; }
     ;
+@end
 
 AssignmentExpression
     : ConditionalExpression { $$ = $1; }
index 3ec4c811a18c5aeb098504456a4ac0daaa9489e9..4b0cdfb49d88b8a34d7d4d7f5351d4efd3870894 100644 (file)
@@ -18,7 +18,7 @@ cyrver: Server.o
            -lapr-1 -lsubstrate -framework CFNetwork
        $(ldid) $@
 
-extra:
+extra::
        sed -i -e '/^Depends: / s/\<mobilesubstrate\>/mobilesubstrate (>= 0.9.3072)/g' package/DEBIAN/control
        #mkdir -p package/System/Library/LaunchDaemons
        #cp -pR com.saurik.Cyrver.plist package/System/Library/LaunchDaemons
index af4bdc137445175826c8eb33427f33f943d45a80..86c7c8a5cccc94cc21ac0ee6e3c2c068851ab4bf 100644 (file)
--- a/Darwin.mk
+++ b/Darwin.mk
@@ -19,4 +19,5 @@ Mach/Inject.o: Trampoline.t.hpp Baton.hpp
 %.t.hpp: %.t.cpp
        $(target)gcc -c -fno-exceptions -Iinclude -o $*.t.o $< && { file=($$($(target)otool -l $*.t.o | sed -e 'x; /^1/ { x; /^ *filesize / { s/^.* //; p; }; /^ *fileoff / { s/^.* //; p; }; x; }; x; /^ *cmd LC_SEGMENT$$/ { s/.*/1/; x; }; d;')); od -t x1 -j $${file[0]} -N $${file[1]} $*.t.o | sed -e 's/^[^ ]*//' | tr $$'\n' ' ' | sed -e 's/  */ /g;s/^ *//;s/ $$//;s/ /,/g;s/\([^,][^,]\)/0x\1/g' | sed -e 's/^/static const char $*_[] = {/;s/$$/};/' && echo && echo "/*" && $(target)otool -vVt $*.t.o && echo "*/"; } >$@ && rm -f $*.t.o
 
+include Execute.mk
 include ObjectiveC.mk
index a87e855dbd62bcf1ac517c2ff45b03b57e5a072a..2fc9f49f7dfff982b75f290b1d43de43f4be0989 100644 (file)
--- a/Error.hpp
+++ b/Error.hpp
@@ -43,6 +43,7 @@
 #include "Pooling.hpp"
 #include "Exception.hpp"
 
+#ifdef CY_EXECUTE
 struct CYJSError :
     CYException
 {
@@ -60,6 +61,7 @@ struct CYJSError :
     virtual const char *PoolCString(apr_pool_t *pool) const;
     virtual JSValueRef CastJSValue(JSContextRef context) const;
 };
+#endif
 
 struct CYPoolError :
     CYException
@@ -71,7 +73,9 @@ struct CYPoolError :
     CYPoolError(const char *format, va_list args);
 
     virtual const char *PoolCString(apr_pool_t *pool) const;
+#ifdef CY_EXECUTE
     virtual JSValueRef CastJSValue(JSContextRef context) const;
+#endif
 };
 
 #endif/*CYCRIPT_ERROR_HPP*/
index 426cb2402e42e126b28bcb58a661c06b2858c2bb..a6aa5ef331c953d90779a7483170a2e01886fe43 100644 (file)
@@ -40,7 +40,9 @@
 #ifndef CYCRIPT_EXCEPTION_HPP
 #define CYCRIPT_EXCEPTION_HPP
 
+#ifdef CY_EXECUTE
 #include <JavaScriptCore/JSBase.h>
+#endif
 
 #include <apr_pools.h>
 #include "Standard.hpp"
@@ -50,11 +52,16 @@ struct CYException {
     }
 
     virtual const char *PoolCString(apr_pool_t *pool) const = 0;
+#ifdef CY_EXECUTE
     virtual JSValueRef CastJSValue(JSContextRef context) const = 0;
+#endif
 };
 
 void CYThrow(const char *format, ...) _noreturn;
+
+#ifdef CY_EXECUTE
 void CYThrow(JSContextRef context, JSValueRef value);
+#endif
 
 #define CYTry \
     try
diff --git a/Execute.cpp b/Execute.cpp
new file mode 100644 (file)
index 0000000..3135c2c
--- /dev/null
@@ -0,0 +1,1492 @@
+/* Cycript - Inlining/Optimizing JavaScript Compiler
+ * Copyright (C) 2009  Jay Freeman (saurik)
+*/
+
+/* Modified BSD License {{{ */
+/*
+ *        Redistribution and use in source and binary
+ * forms, with or without modification, are permitted
+ * provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the
+ *    above copyright notice, this list of conditions
+ *    and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the
+ *    above copyright notice, this list of conditions
+ *    and the following disclaimer in the documentation
+ *    and/or other materials provided with the
+ *    distribution.
+ * 3. The name of the author may not be used to endorse
+ *    or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/* }}} */
+
+#include <sqlite3.h>
+
+#include "Internal.hpp"
+
+#include <dlfcn.h>
+#include <iconv.h>
+
+#include "cycript.hpp"
+
+#include "sig/parse.hpp"
+#include "sig/ffi_type.hpp"
+
+#include "Pooling.hpp"
+
+#include <sys/mman.h>
+
+#include <iostream>
+#include <ext/stdio_filebuf.h>
+#include <set>
+#include <map>
+#include <iomanip>
+#include <sstream>
+#include <cmath>
+
+#include "Parser.hpp"
+#include "Cycript.tab.hh"
+
+#include "Error.hpp"
+#include "JavaScript.hpp"
+#include "String.hpp"
+
+char *sqlite3_column_pooled(apr_pool_t *pool, sqlite3_stmt *stmt, int n) {
+    if (const unsigned char *value = sqlite3_column_text(stmt, n))
+        return apr_pstrdup(pool, (const char *) value);
+    else return NULL;
+}
+
+struct CYHooks *hooks_;
+
+/* JavaScript Properties {{{ */
+JSValueRef CYGetProperty(JSContextRef context, JSObjectRef object, size_t index) {
+    JSValueRef exception(NULL);
+    JSValueRef value(JSObjectGetPropertyAtIndex(context, object, index, &exception));
+    CYThrow(context, exception);
+    return value;
+}
+
+JSValueRef CYGetProperty(JSContextRef context, JSObjectRef object, JSStringRef name) {
+    JSValueRef exception(NULL);
+    JSValueRef value(JSObjectGetProperty(context, object, name, &exception));
+    CYThrow(context, exception);
+    return value;
+}
+
+void CYSetProperty(JSContextRef context, JSObjectRef object, size_t index, JSValueRef value) {
+    JSValueRef exception(NULL);
+    JSObjectSetPropertyAtIndex(context, object, index, value, &exception);
+    CYThrow(context, exception);
+}
+
+void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef value, JSPropertyAttributes attributes) {
+    JSValueRef exception(NULL);
+    JSObjectSetProperty(context, object, name, value, attributes, &exception);
+    CYThrow(context, exception);
+}
+
+void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef (*callback)(JSContextRef, JSObjectRef, JSObjectRef, size_t, const JSValueRef[], JSValueRef *), JSPropertyAttributes attributes) {
+    CYSetProperty(context, object, name, JSObjectMakeFunctionWithCallback(context, name, callback), attributes);
+}
+/* }}} */
+/* JavaScript Strings {{{ */
+JSStringRef CYCopyJSString(const char *value) {
+    return value == NULL ? NULL : JSStringCreateWithUTF8CString(value);
+}
+
+JSStringRef CYCopyJSString(JSStringRef value) {
+    return value == NULL ? NULL : JSStringRetain(value);
+}
+
+JSStringRef CYCopyJSString(CYUTF8String value) {
+    // XXX: this is very wrong; it needs to convert to UTF16 and then create from there
+    return CYCopyJSString(value.data);
+}
+
+JSStringRef CYCopyJSString(JSContextRef context, JSValueRef value) {
+    if (JSValueIsNull(context, value))
+        return NULL;
+    JSValueRef exception(NULL);
+    JSStringRef string(JSValueToStringCopy(context, value, &exception));
+    CYThrow(context, exception);
+    return string;
+}
+
+static CYUTF16String CYCastUTF16String(JSStringRef value) {
+    return CYUTF16String(JSStringGetCharactersPtr(value), JSStringGetLength(value));
+}
+
+CYUTF8String CYPoolUTF8String(apr_pool_t *pool, JSContextRef context, JSStringRef value) {
+    return CYPoolUTF8String(pool, CYCastUTF16String(value));
+}
+
+const char *CYPoolCString(apr_pool_t *pool, JSContextRef context, JSStringRef value) {
+    CYUTF8String utf8(CYPoolUTF8String(pool, context, value));
+    _assert(memchr(utf8.data, '\0', utf8.size) == NULL);
+    return utf8.data;
+}
+
+const char *CYPoolCString(apr_pool_t *pool, JSContextRef context, JSValueRef value) {
+    return JSValueIsNull(context, value) ? NULL : CYPoolCString(pool, context, CYJSString(context, value));
+}
+/* }}} */
+/* Index Offsets {{{ */
+size_t CYGetIndex(apr_pool_t *pool, JSContextRef context, JSStringRef value) {
+    return CYGetIndex(CYPoolUTF8String(pool, context, value));
+}
+/* }}} */
+
+static JSClassRef All_;
+static JSClassRef Context_;
+static JSClassRef Functor_;
+static JSClassRef Global_;
+static JSClassRef Pointer_;
+static JSClassRef Struct_;
+
+JSStringRef Array_s;
+JSStringRef cy_s;
+JSStringRef length_s;
+JSStringRef message_s;
+JSStringRef name_s;
+JSStringRef pop_s;
+JSStringRef prototype_s;
+JSStringRef push_s;
+JSStringRef splice_s;
+JSStringRef toCYON_s;
+JSStringRef toJSON_s;
+
+static JSStringRef Result_;
+
+sqlite3 *Bridge_;
+
+void CYFinalize(JSObjectRef object) {
+    delete reinterpret_cast<CYData *>(JSObjectGetPrivate(object));
+}
+
+struct CStringMapLess :
+    std::binary_function<const char *, const char *, bool>
+{
+    _finline bool operator ()(const char *lhs, const char *rhs) const {
+        return strcmp(lhs, rhs) < 0;
+    }
+};
+
+void Structor_(apr_pool_t *pool, sig::Type *&type) {
+    if (
+        type->primitive == sig::pointer_P &&
+        type->data.data.type != NULL &&
+        type->data.data.type->primitive == sig::struct_P &&
+        strcmp(type->data.data.type->name, "_objc_class") == 0
+    ) {
+        type->primitive = sig::typename_P;
+        type->data.data.type = NULL;
+        return;
+    }
+
+    if (type->primitive != sig::struct_P || type->name == NULL)
+        return;
+
+    sqlite3_stmt *statement;
+
+    _sqlcall(sqlite3_prepare(Bridge_,
+        "select "
+            "\"bridge\".\"mode\", "
+            "\"bridge\".\"value\" "
+        "from \"bridge\" "
+        "where"
+            " \"bridge\".\"mode\" in (3, 4) and"
+            " \"bridge\".\"name\" = ?"
+        " limit 1"
+    , -1, &statement, NULL));
+
+    _sqlcall(sqlite3_bind_text(statement, 1, type->name, -1, SQLITE_STATIC));
+
+    int mode;
+    const char *value;
+
+    if (_sqlcall(sqlite3_step(statement)) == SQLITE_DONE) {
+        mode = -1;
+        value = NULL;
+    } else {
+        mode = sqlite3_column_int(statement, 0);
+        value = sqlite3_column_pooled(pool, statement, 1);
+    }
+
+    _sqlcall(sqlite3_finalize(statement));
+
+    switch (mode) {
+        default:
+            _assert(false);
+        case -1:
+            break;
+
+        case 3: {
+            sig::Parse(pool, &type->data.signature, value, &Structor_);
+        } break;
+
+        case 4: {
+            sig::Signature signature;
+            sig::Parse(pool, &signature, value, &Structor_);
+            type = signature.elements[0].type;
+        } break;
+    }
+}
+
+JSClassRef Type_privateData::Class_;
+
+struct Context :
+    CYData
+{
+    JSGlobalContextRef context_;
+
+    Context(JSGlobalContextRef context) :
+        context_(context)
+    {
+    }
+};
+
+struct Pointer :
+    CYOwned
+{
+    Type_privateData *type_;
+    size_t length_;
+
+    Pointer(void *value, JSContextRef context, JSObjectRef owner, size_t length, sig::Type *type) :
+        CYOwned(value, context, owner),
+        type_(new(pool_) Type_privateData(type)),
+        length_(length)
+    {
+    }
+};
+
+struct Struct_privateData :
+    CYOwned
+{
+    Type_privateData *type_;
+
+    Struct_privateData(JSContextRef context, JSObjectRef owner) :
+        CYOwned(NULL, context, owner)
+    {
+    }
+};
+
+typedef std::map<const char *, Type_privateData *, CStringMapLess> TypeMap;
+static TypeMap Types_;
+
+JSObjectRef CYMakeStruct(JSContextRef context, void *data, sig::Type *type, ffi_type *ffi, JSObjectRef owner) {
+    Struct_privateData *internal(new Struct_privateData(context, owner));
+    apr_pool_t *pool(internal->pool_);
+    Type_privateData *typical(new(pool) Type_privateData(type, ffi));
+    internal->type_ = typical;
+
+    if (owner != NULL)
+        internal->value_ = data;
+    else {
+        size_t size(typical->GetFFI()->size);
+        void *copy(apr_palloc(internal->pool_, size));
+        memcpy(copy, data, size);
+        internal->value_ = copy;
+    }
+
+    return JSObjectMake(context, Struct_, internal);
+}
+
+JSValueRef CYCastJSValue(JSContextRef context, bool value) {
+    return JSValueMakeBoolean(context, value);
+}
+
+JSValueRef CYCastJSValue(JSContextRef context, double value) {
+    return JSValueMakeNumber(context, value);
+}
+
+#define CYCastJSValue_(Type_) \
+    JSValueRef CYCastJSValue(JSContextRef context, Type_ value) { \
+        return JSValueMakeNumber(context, static_cast<double>(value)); \
+    }
+
+CYCastJSValue_(int)
+CYCastJSValue_(unsigned int)
+CYCastJSValue_(long int)
+CYCastJSValue_(long unsigned int)
+CYCastJSValue_(long long int)
+CYCastJSValue_(long long unsigned int)
+
+JSValueRef CYJSUndefined(JSContextRef context) {
+    return JSValueMakeUndefined(context);
+}
+
+double CYCastDouble(JSContextRef context, JSValueRef value) {
+    JSValueRef exception(NULL);
+    double number(JSValueToNumber(context, value, &exception));
+    CYThrow(context, exception);
+    return number;
+}
+
+bool CYCastBool(JSContextRef context, JSValueRef value) {
+    return JSValueToBoolean(context, value);
+}
+
+JSValueRef CYJSNull(JSContextRef context) {
+    return JSValueMakeNull(context);
+}
+
+JSValueRef CYCastJSValue(JSContextRef context, JSStringRef value) {
+    return value == NULL ? CYJSNull(context) : JSValueMakeString(context, value);
+}
+
+JSValueRef CYCastJSValue(JSContextRef context, const char *value) {
+    return CYCastJSValue(context, CYJSString(value));
+}
+
+JSObjectRef CYCastJSObject(JSContextRef context, JSValueRef value) {
+    JSValueRef exception(NULL);
+    JSObjectRef object(JSValueToObject(context, value, &exception));
+    CYThrow(context, exception);
+    return object;
+}
+
+JSValueRef CYCallAsFunction(JSContextRef context, JSObjectRef function, JSObjectRef _this, size_t count, const JSValueRef arguments[]) {
+    JSValueRef exception(NULL);
+    JSValueRef value(JSObjectCallAsFunction(context, function, _this, count, arguments, &exception));
+    CYThrow(context, exception);
+    return value;
+}
+
+bool CYIsCallable(JSContextRef context, JSValueRef value) {
+    return value != NULL && JSValueIsObject(context, value) && JSObjectIsFunction(context, (JSObjectRef) value);
+}
+
+static JSValueRef System_print(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    if (count == 0)
+        printf("\n");
+    else {
+        CYPool pool;
+        printf("%s\n", CYPoolCString(pool, context, arguments[0]));
+    }
+
+    return CYJSUndefined(context);
+} CYCatch }
+
+static size_t Nonce_(0);
+
+static JSValueRef $cyq(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
+    CYPool pool;
+    const char *name(apr_psprintf(pool, "%s%"APR_SIZE_T_FMT"", CYPoolCString(pool, context, arguments[0]), Nonce_++));
+    return CYCastJSValue(context, name);
+}
+
+static JSValueRef Cycript_gc_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
+    JSGarbageCollect(context);
+    return CYJSUndefined(context);
+}
+
+const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSValueRef value, JSValueRef *exception) { CYTry {
+    switch (JSType type = JSValueGetType(context, value)) {
+        case kJSTypeUndefined:
+            return "undefined";
+        case kJSTypeNull:
+            return "null";
+        case kJSTypeBoolean:
+            return CYCastBool(context, value) ? "true" : "false";
+
+        case kJSTypeNumber: {
+            std::ostringstream str;
+            CYNumerify(str, CYCastDouble(context, value));
+            std::string value(str.str());
+            return apr_pstrmemdup(pool, value.c_str(), value.size());
+        } break;
+
+        case kJSTypeString: {
+            std::ostringstream str;
+            CYUTF8String string(CYPoolUTF8String(pool, context, CYJSString(context, value)));
+            CYStringify(str, string.data, string.size);
+            std::string value(str.str());
+            return apr_pstrmemdup(pool, value.c_str(), value.size());
+        } break;
+
+        case kJSTypeObject:
+            return CYPoolCCYON(pool, context, (JSObjectRef) value);
+        default:
+            throw CYJSError(context, "JSValueGetType() == 0x%x", type);
+    }
+} CYCatch }
+
+const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSValueRef value) {
+    JSValueRef exception(NULL);
+    const char *cyon(CYPoolCCYON(pool, context, value, &exception));
+    CYThrow(context, exception);
+    return cyon;
+}
+
+const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSObjectRef object) {
+    JSValueRef toCYON(CYGetProperty(context, object, toCYON_s));
+    if (CYIsCallable(context, toCYON)) {
+        JSValueRef value(CYCallAsFunction(context, (JSObjectRef) toCYON, object, 0, NULL));
+        _assert(value != NULL);
+        return CYPoolCString(pool, context, value);
+    }
+
+    JSValueRef toJSON(CYGetProperty(context, object, toJSON_s));
+    if (CYIsCallable(context, toJSON)) {
+        JSValueRef arguments[1] = {CYCastJSValue(context, CYJSString(""))};
+        JSValueRef exception(NULL);
+        const char *cyon(CYPoolCCYON(pool, context, CYCallAsFunction(context, (JSObjectRef) toJSON, object, 1, arguments), &exception));
+        CYThrow(context, exception);
+        return cyon;
+    }
+
+    std::ostringstream str;
+
+    str << '{';
+
+    // XXX: this is, sadly, going to leak
+    JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context, object));
+
+    bool comma(false);
+
+    for (size_t index(0), count(JSPropertyNameArrayGetCount(names)); index != count; ++index) {
+        JSStringRef name(JSPropertyNameArrayGetNameAtIndex(names, index));
+        JSValueRef value(CYGetProperty(context, object, name));
+
+        if (comma)
+            str << ',';
+        else
+            comma = true;
+
+        CYUTF8String string(CYPoolUTF8String(pool, context, name));
+        if (CYIsKey(string))
+            str << string.data;
+        else
+            CYStringify(str, string.data, string.size);
+
+        str << ':' << CYPoolCCYON(pool, context, value);
+    }
+
+    str << '}';
+
+    JSPropertyNameArrayRelease(names);
+
+    std::string string(str.str());
+    return apr_pstrmemdup(pool, string.c_str(), string.size());
+}
+
+static JSValueRef Array_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    CYPool pool;
+    std::ostringstream str;
+
+    str << '[';
+
+    JSValueRef length(CYGetProperty(context, _this, length_s));
+    bool comma(false);
+
+    for (size_t index(0), count(CYCastDouble(context, length)); index != count; ++index) {
+        JSValueRef value(CYGetProperty(context, _this, index));
+
+        if (comma)
+            str << ',';
+        else
+            comma = true;
+
+        if (!JSValueIsUndefined(context, value))
+            str << CYPoolCCYON(pool, context, value);
+        else {
+            str << ',';
+            comma = false;
+        }
+    }
+
+    str << ']';
+
+    std::string value(str.str());
+    return CYCastJSValue(context, CYJSString(CYUTF8String(value.c_str(), value.size())));
+} CYCatch }
+
+JSObjectRef CYMakePointer(JSContextRef context, void *pointer, size_t length, sig::Type *type, ffi_type *ffi, JSObjectRef owner) {
+    Pointer *internal(new Pointer(pointer, context, owner, length, type));
+    return JSObjectMake(context, Pointer_, internal);
+}
+
+static JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), const char *type) {
+    cy::Functor *internal(new cy::Functor(type, function));
+    return JSObjectMake(context, Functor_, internal);
+}
+
+static bool CYGetOffset(apr_pool_t *pool, JSContextRef context, JSStringRef value, ssize_t &index) {
+    return CYGetOffset(CYPoolCString(pool, context, value), index);
+}
+
+void *CYCastPointer_(JSContextRef context, JSValueRef value) {
+    switch (JSValueGetType(context, value)) {
+        case kJSTypeNull:
+            return NULL;
+        /*case kJSTypeObject:
+            if (JSValueIsObjectOfClass(context, value, Pointer_)) {
+                Pointer *internal(reinterpret_cast<Pointer *>(JSObjectGetPrivate((JSObjectRef) value)));
+                return internal->value_;
+            }*/
+        default:
+            double number(CYCastDouble(context, value));
+            if (std::isnan(number))
+                throw CYJSError(context, "cannot convert value to pointer");
+            return reinterpret_cast<void *>(static_cast<uintptr_t>(static_cast<long long>(number)));
+    }
+}
+
+void CYPoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, JSValueRef value) {
+    switch (type->primitive) {
+        case sig::boolean_P:
+            *reinterpret_cast<bool *>(data) = JSValueToBoolean(context, value);
+        break;
+
+#define CYPoolFFI_(primitive, native) \
+        case sig::primitive ## _P: \
+            *reinterpret_cast<native *>(data) = CYCastDouble(context, value); \
+        break;
+
+        CYPoolFFI_(uchar, unsigned char)
+        CYPoolFFI_(char, char)
+        CYPoolFFI_(ushort, unsigned short)
+        CYPoolFFI_(short, short)
+        CYPoolFFI_(ulong, unsigned long)
+        CYPoolFFI_(long, long)
+        CYPoolFFI_(uint, unsigned int)
+        CYPoolFFI_(int, int)
+        CYPoolFFI_(ulonglong, unsigned long long)
+        CYPoolFFI_(longlong, long long)
+        CYPoolFFI_(float, float)
+        CYPoolFFI_(double, double)
+
+        case sig::array_P: {
+            uint8_t *base(reinterpret_cast<uint8_t *>(data));
+            JSObjectRef aggregate(JSValueIsObject(context, value) ? (JSObjectRef) value : NULL);
+            for (size_t index(0); index != type->data.data.size; ++index) {
+                ffi_type *field(ffi->elements[index]);
+
+                JSValueRef rhs;
+                if (aggregate == NULL)
+                    rhs = value;
+                else {
+                    rhs = CYGetProperty(context, aggregate, index);
+                    if (JSValueIsUndefined(context, rhs))
+                        throw CYJSError(context, "unable to extract array value");
+                }
+
+                CYPoolFFI(pool, context, type->data.data.type, field, base, rhs);
+                // XXX: alignment?
+                base += field->size;
+            }
+        } break;
+
+        case sig::pointer_P:
+            *reinterpret_cast<void **>(data) = CYCastPointer<void *>(context, value);
+        break;
+
+        case sig::string_P:
+            *reinterpret_cast<const char **>(data) = CYPoolCString(pool, context, value);
+        break;
+
+        case sig::struct_P: {
+            uint8_t *base(reinterpret_cast<uint8_t *>(data));
+            JSObjectRef aggregate(JSValueIsObject(context, value) ? (JSObjectRef) value : NULL);
+            for (size_t index(0); index != type->data.signature.count; ++index) {
+                sig::Element *element(&type->data.signature.elements[index]);
+                ffi_type *field(ffi->elements[index]);
+
+                JSValueRef rhs;
+                if (aggregate == NULL)
+                    rhs = value;
+                else {
+                    rhs = CYGetProperty(context, aggregate, index);
+                    if (JSValueIsUndefined(context, rhs)) {
+                        if (element->name != NULL)
+                            rhs = CYGetProperty(context, aggregate, CYJSString(element->name));
+                        else
+                            goto undefined;
+                        if (JSValueIsUndefined(context, rhs)) undefined:
+                            throw CYJSError(context, "unable to extract structure value");
+                    }
+                }
+
+                CYPoolFFI(pool, context, element->type, field, base, rhs);
+                // XXX: alignment?
+                base += field->size;
+            }
+        } break;
+
+        case sig::void_P:
+        break;
+
+        default:
+            if (hooks_ != NULL && hooks_->PoolFFI != NULL)
+                if ((*hooks_->PoolFFI)(pool, context, type, ffi, data, value))
+                    return;
+
+            CYThrow("unimplemented signature code: '%c''\n", type->primitive);
+    }
+}
+
+JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) {
+    switch (type->primitive) {
+        case sig::boolean_P:
+            return CYCastJSValue(context, *reinterpret_cast<bool *>(data));
+
+#define CYFromFFI_(primitive, native) \
+        case sig::primitive ## _P: \
+            return CYCastJSValue(context, *reinterpret_cast<native *>(data)); \
+
+        CYFromFFI_(uchar, unsigned char)
+        CYFromFFI_(char, char)
+        CYFromFFI_(ushort, unsigned short)
+        CYFromFFI_(short, short)
+        CYFromFFI_(ulong, unsigned long)
+        CYFromFFI_(long, long)
+        CYFromFFI_(uint, unsigned int)
+        CYFromFFI_(int, int)
+        CYFromFFI_(ulonglong, unsigned long long)
+        CYFromFFI_(longlong, long long)
+        CYFromFFI_(float, float)
+        CYFromFFI_(double, double)
+
+        case sig::array_P:
+            if (void *pointer = data)
+                return CYMakePointer(context, pointer, type->data.data.size, type->data.data.type, NULL, owner);
+            else goto null;
+
+        case sig::pointer_P:
+            if (void *pointer = *reinterpret_cast<void **>(data))
+                return CYMakePointer(context, pointer, _not(size_t), type->data.data.type, NULL, owner);
+            else goto null;
+
+        case sig::string_P:
+            if (char *utf8 = *reinterpret_cast<char **>(data))
+                return CYCastJSValue(context, utf8);
+            else goto null;
+
+        case sig::struct_P:
+            return CYMakeStruct(context, data, type, ffi, owner);
+        case sig::void_P:
+            return CYJSUndefined(context);
+
+        null:
+            return CYJSNull(context);
+        default:
+            if (hooks_ != NULL && hooks_->FromFFI != NULL)
+                if (JSValueRef value = (*hooks_->FromFFI)(context, type, ffi, data, initialize, owner))
+                    return value;
+
+            CYThrow("unimplemented signature code: '%c''\n", type->primitive);
+    }
+}
+
+static void FunctionClosure_(ffi_cif *cif, void *result, void **arguments, void *arg) {
+    Closure_privateData *internal(reinterpret_cast<Closure_privateData *>(arg));
+
+    JSContextRef context(internal->context_);
+
+    size_t count(internal->cif_.nargs);
+    JSValueRef values[count];
+
+    for (size_t index(0); index != count; ++index)
+        values[index] = CYFromFFI(context, internal->signature_.elements[1 + index].type, internal->cif_.arg_types[index], arguments[index]);
+
+    JSValueRef value(CYCallAsFunction(context, internal->function_, NULL, count, values));
+    CYPoolFFI(NULL, context, internal->signature_.elements[0].type, internal->cif_.rtype, result, value);
+}
+
+Closure_privateData *CYMakeFunctor_(JSContextRef context, JSObjectRef function, const char *type, void (*callback)(ffi_cif *, void *, void **, void *)) {
+    // XXX: in case of exceptions this will leak
+    // XXX: in point of fact, this may /need/ to leak :(
+    Closure_privateData *internal(new Closure_privateData(context, function, type));
+
+    ffi_closure *closure((ffi_closure *) _syscall(mmap(
+        NULL, sizeof(ffi_closure),
+        PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,
+        -1, 0
+    )));
+
+    ffi_status status(ffi_prep_closure(closure, &internal->cif_, callback, internal));
+    _assert(status == FFI_OK);
+
+    _syscall(mprotect(closure, sizeof(*closure), PROT_READ | PROT_EXEC));
+
+    internal->value_ = closure;
+
+    return internal;
+}
+
+static JSObjectRef CYMakeFunctor(JSContextRef context, JSObjectRef function, const char *type) {
+    Closure_privateData *internal(CYMakeFunctor_(context, function, type, &FunctionClosure_));
+    JSObjectRef object(JSObjectMake(context, Functor_, internal));
+    // XXX: see above notes about needing to leak
+    JSValueProtect(CYGetJSContext(context), object);
+    return object;
+}
+
+JSObjectRef CYGetCachedObject(JSContextRef context, JSStringRef name) {
+    return CYCastJSObject(context, CYGetProperty(context, CYCastJSObject(context, CYGetProperty(context, CYGetGlobalObject(context), cy_s)), name));
+}
+
+static JSObjectRef CYMakeFunctor(JSContextRef context, JSValueRef value, const char *type) {
+    JSObjectRef Function(CYGetCachedObject(context, CYJSString("Function")));
+
+    JSValueRef exception(NULL);
+    bool function(JSValueIsInstanceOfConstructor(context, value, Function, &exception));
+    CYThrow(context, exception);
+
+    if (function) {
+        JSObjectRef function(CYCastJSObject(context, value));
+        return CYMakeFunctor(context, function, type);
+    } else {
+        void (*function)()(CYCastPointer<void (*)()>(context, value));
+        return CYMakeFunctor(context, function, type);
+    }
+}
+
+static bool Index_(apr_pool_t *pool, JSContextRef context, Struct_privateData *internal, JSStringRef property, ssize_t &index, uint8_t *&base) {
+    Type_privateData *typical(internal->type_);
+    sig::Type *type(typical->type_);
+    if (type == NULL)
+        return false;
+
+    const char *name(CYPoolCString(pool, context, property));
+    size_t length(strlen(name));
+    double number(CYCastDouble(name, length));
+
+    size_t count(type->data.signature.count);
+
+    if (std::isnan(number)) {
+        if (property == NULL)
+            return false;
+
+        sig::Element *elements(type->data.signature.elements);
+
+        for (size_t local(0); local != count; ++local) {
+            sig::Element *element(&elements[local]);
+            if (element->name != NULL && strcmp(name, element->name) == 0) {
+                index = local;
+                goto base;
+            }
+        }
+
+        return false;
+    } else {
+        index = static_cast<ssize_t>(number);
+        if (index != number || index < 0 || static_cast<size_t>(index) >= count)
+            return false;
+    }
+
+  base:
+    ffi_type **elements(typical->GetFFI()->elements);
+
+    base = reinterpret_cast<uint8_t *>(internal->value_);
+    for (ssize_t local(0); local != index; ++local)
+        base += elements[local]->size;
+
+    return true;
+}
+
+static JSValueRef Pointer_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
+    CYPool pool;
+    Pointer *internal(reinterpret_cast<Pointer *>(JSObjectGetPrivate(object)));
+
+    if (JSStringIsEqual(property, length_s))
+        return internal->length_ == _not(size_t) ? CYJSUndefined(context) : CYCastJSValue(context, internal->length_);
+
+    Type_privateData *typical(internal->type_);
+
+    if (typical->type_ == NULL)
+        return NULL;
+
+    ssize_t offset;
+    if (JSStringIsEqualToUTF8CString(property, "$cyi"))
+        offset = 0;
+    else if (!CYGetOffset(pool, context, property, offset))
+        return NULL;
+
+    ffi_type *ffi(typical->GetFFI());
+
+    uint8_t *base(reinterpret_cast<uint8_t *>(internal->value_));
+    base += ffi->size * offset;
+
+    JSObjectRef owner(internal->GetOwner() ?: object);
+    return CYFromFFI(context, typical->type_, ffi, base, false, owner);
+} CYCatch }
+
+static bool Pointer_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry {
+    CYPool pool;
+    Pointer *internal(reinterpret_cast<Pointer *>(JSObjectGetPrivate(object)));
+    Type_privateData *typical(internal->type_);
+
+    if (typical->type_ == NULL)
+        return NULL;
+
+    ssize_t offset;
+    if (JSStringIsEqualToUTF8CString(property, "$cyi"))
+        offset = 0;
+    else if (!CYGetOffset(pool, context, property, offset))
+        return NULL;
+
+    ffi_type *ffi(typical->GetFFI());
+
+    uint8_t *base(reinterpret_cast<uint8_t *>(internal->value_));
+    base += ffi->size * offset;
+
+    CYPoolFFI(NULL, context, typical->type_, ffi, base, value);
+    return true;
+} CYCatch }
+
+static JSValueRef Struct_callAsFunction_$cya(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
+    Struct_privateData *internal(reinterpret_cast<Struct_privateData *>(JSObjectGetPrivate(_this)));
+    Type_privateData *typical(internal->type_);
+    return CYMakePointer(context, internal->value_, _not(size_t), typical->type_, typical->ffi_, _this);
+}
+
+static JSValueRef Struct_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
+    CYPool pool;
+    Struct_privateData *internal(reinterpret_cast<Struct_privateData *>(JSObjectGetPrivate(object)));
+    Type_privateData *typical(internal->type_);
+
+    ssize_t index;
+    uint8_t *base;
+
+    if (!Index_(pool, context, internal, property, index, base))
+        return NULL;
+
+    JSObjectRef owner(internal->GetOwner() ?: object);
+
+    return CYFromFFI(context, typical->type_->data.signature.elements[index].type, typical->GetFFI()->elements[index], base, false, owner);
+} CYCatch }
+
+static bool Struct_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry {
+    CYPool pool;
+    Struct_privateData *internal(reinterpret_cast<Struct_privateData *>(JSObjectGetPrivate(object)));
+    Type_privateData *typical(internal->type_);
+
+    ssize_t index;
+    uint8_t *base;
+
+    if (!Index_(pool, context, internal, property, index, base))
+        return false;
+
+    CYPoolFFI(NULL, context, typical->type_->data.signature.elements[index].type, typical->GetFFI()->elements[index], base, value);
+    return true;
+} CYCatch }
+
+static void Struct_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef names) {
+    Struct_privateData *internal(reinterpret_cast<Struct_privateData *>(JSObjectGetPrivate(object)));
+    Type_privateData *typical(internal->type_);
+    sig::Type *type(typical->type_);
+
+    if (type == NULL)
+        return;
+
+    size_t count(type->data.signature.count);
+    sig::Element *elements(type->data.signature.elements);
+
+    char number[32];
+
+    for (size_t index(0); index != count; ++index) {
+        const char *name;
+        name = elements[index].name;
+
+        if (name == NULL) {
+            sprintf(number, "%zu", index);
+            name = number;
+        }
+
+        JSPropertyNameAccumulatorAddName(names, CYJSString(name));
+    }
+}
+
+JSValueRef CYCallFunction(apr_pool_t *pool, JSContextRef context, size_t setups, void *setup[], size_t count, const JSValueRef arguments[], bool initialize, JSValueRef *exception, sig::Signature *signature, ffi_cif *cif, void (*function)()) { CYTry {
+    if (setups + count != signature->count - 1)
+        throw CYJSError(context, "incorrect number of arguments to ffi function");
+
+    size_t size(setups + count);
+    void *values[size];
+    memcpy(values, setup, sizeof(void *) * setups);
+
+    for (size_t index(setups); index != size; ++index) {
+        sig::Element *element(&signature->elements[index + 1]);
+        ffi_type *ffi(cif->arg_types[index]);
+        // XXX: alignment?
+        values[index] = new(pool) uint8_t[ffi->size];
+        CYPoolFFI(pool, context, element->type, ffi, values[index], arguments[index - setups]);
+    }
+
+    uint8_t value[cif->rtype->size];
+
+    if (hooks_ != NULL && hooks_->CallFunction != NULL)
+        (*hooks_->CallFunction)(context, cif, function, value, values);
+    else
+        ffi_call(cif, function, value, values);
+
+    return CYFromFFI(context, signature->elements[0].type, cif->rtype, value, initialize);
+} CYCatch }
+
+static JSValueRef Functor_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
+    CYPool pool;
+    cy::Functor *internal(reinterpret_cast<cy::Functor *>(JSObjectGetPrivate(object)));
+    return CYCallFunction(pool, context, 0, NULL, count, arguments, false, exception, &internal->signature_, &internal->cif_, internal->GetValue());
+}
+
+static JSObjectRef CYMakeType(JSContextRef context, const char *type) {
+    Type_privateData *internal(new Type_privateData(type));
+    return JSObjectMake(context, Type_privateData::Class_, internal);
+}
+
+static JSObjectRef CYMakeType(JSContextRef context, sig::Type *type) {
+    Type_privateData *internal(new Type_privateData(type));
+    return JSObjectMake(context, Type_privateData::Class_, internal);
+}
+
+static void *CYCastSymbol(const char *name) {
+    return dlsym(RTLD_DEFAULT, name);
+}
+
+static JSValueRef All_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
+    JSObjectRef global(CYGetGlobalObject(context));
+    JSObjectRef cycript(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Cycript"))));
+    if (JSValueRef value = CYGetProperty(context, cycript, property))
+        if (!JSValueIsUndefined(context, value))
+            return value;
+
+    CYPool pool;
+    CYUTF8String name(CYPoolUTF8String(pool, context, property));
+
+    if (hooks_ != NULL && hooks_->RuntimeProperty != NULL)
+        if (JSValueRef value = (*hooks_->RuntimeProperty)(context, name))
+            return value;
+
+    sqlite3_stmt *statement;
+
+    _sqlcall(sqlite3_prepare(Bridge_,
+        "select "
+            "\"bridge\".\"mode\", "
+            "\"bridge\".\"value\" "
+        "from \"bridge\" "
+        "where"
+            " \"bridge\".\"name\" = ?"
+        " limit 1"
+    , -1, &statement, NULL));
+
+    _sqlcall(sqlite3_bind_text(statement, 1, name.data, name.size, SQLITE_STATIC));
+
+    int mode;
+    const char *value;
+
+    if (_sqlcall(sqlite3_step(statement)) == SQLITE_DONE) {
+        mode = -1;
+        value = NULL;
+    } else {
+        mode = sqlite3_column_int(statement, 0);
+        value = sqlite3_column_pooled(pool, statement, 1);
+    }
+
+    _sqlcall(sqlite3_finalize(statement));
+
+    switch (mode) {
+        default:
+            CYThrow("invalid mode from bridge table: %d", mode);
+        case -1:
+            return NULL;
+
+        case 0:
+            return JSEvaluateScript(CYGetJSContext(context), CYJSString(value), NULL, NULL, 0, NULL);
+
+        case 1:
+            if (void (*symbol)() = reinterpret_cast<void (*)()>(CYCastSymbol(name.data)))
+                return CYMakeFunctor(context, symbol, value);
+            else return NULL;
+
+        case 2:
+            if (void *symbol = CYCastSymbol(name.data)) {
+                // XXX: this is horrendously inefficient
+                sig::Signature signature;
+                sig::Parse(pool, &signature, value, &Structor_);
+                ffi_cif cif;
+                sig::sig_ffi_cif(pool, &sig::ObjectiveC, &signature, &cif);
+                return CYFromFFI(context, signature.elements[0].type, cif.rtype, symbol);
+            } else return NULL;
+
+        // XXX: implement case 3
+        case 4:
+            return CYMakeType(context, value);
+    }
+} CYCatch }
+
+static JSObjectRef Pointer_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    if (count != 2)
+        throw CYJSError(context, "incorrect number of arguments to Functor constructor");
+
+    CYPool pool;
+
+    void *value(CYCastPointer<void *>(context, arguments[0]));
+    const char *type(CYPoolCString(pool, context, arguments[1]));
+
+    sig::Signature signature;
+    sig::Parse(pool, &signature, type, &Structor_);
+
+    return CYMakePointer(context, value, _not(size_t), signature.elements[0].type, NULL, NULL);
+} CYCatch }
+
+static JSObjectRef Type_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    if (count != 1)
+        throw CYJSError(context, "incorrect number of arguments to Type constructor");
+    CYPool pool;
+    const char *type(CYPoolCString(pool, context, arguments[0]));
+    return CYMakeType(context, type);
+} CYCatch }
+
+static JSValueRef Type_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
+    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
+
+    sig::Type type;
+
+    if (JSStringIsEqualToUTF8CString(property, "$cyi")) {
+        type.primitive = sig::pointer_P;
+        type.data.data.size = 0;
+    } else {
+        CYPool pool;
+        size_t index(CYGetIndex(pool, context, property));
+        if (index == _not(size_t))
+            return NULL;
+        type.primitive = sig::array_P;
+        type.data.data.size = index;
+    }
+
+    type.name = NULL;
+    type.flags = 0;
+
+    type.data.data.type = internal->type_;
+
+    return CYMakeType(context, &type);
+} CYCatch }
+
+static JSValueRef Type_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
+
+    if (count != 1)
+        throw CYJSError(context, "incorrect number of arguments to type cast function");
+    sig::Type *type(internal->type_);
+    ffi_type *ffi(internal->GetFFI());
+    // XXX: alignment?
+    uint8_t value[ffi->size];
+    CYPool pool;
+    CYPoolFFI(pool, context, type, ffi, value, arguments[0]);
+    return CYFromFFI(context, type, ffi, value);
+} CYCatch }
+
+static JSObjectRef Type_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    if (count != 0)
+        throw CYJSError(context, "incorrect number of arguments to type cast function");
+    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
+
+    sig::Type *type(internal->type_);
+    size_t length;
+
+    if (type->primitive != sig::array_P)
+        length = _not(size_t);
+    else {
+        length = type->data.data.size;
+        type = type->data.data.type;
+    }
+
+    void *value(malloc(internal->GetFFI()->size));
+    return CYMakePointer(context, value, length, type, NULL, NULL);
+} CYCatch }
+
+static JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    if (count != 2)
+        throw CYJSError(context, "incorrect number of arguments to Functor constructor");
+    CYPool pool;
+    const char *type(CYPoolCString(pool, context, arguments[1]));
+    return CYMakeFunctor(context, arguments[0], type);
+} CYCatch }
+
+static JSValueRef CYValue_callAsFunction_valueOf(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    CYValue *internal(reinterpret_cast<CYValue *>(JSObjectGetPrivate(_this)));
+    return CYCastJSValue(context, reinterpret_cast<uintptr_t>(internal->value_));
+} CYCatch }
+
+static JSValueRef CYValue_callAsFunction_toJSON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
+    return CYValue_callAsFunction_valueOf(context, object, _this, count, arguments, exception);
+}
+
+static JSValueRef CYValue_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    CYValue *internal(reinterpret_cast<CYValue *>(JSObjectGetPrivate(_this)));
+    char string[32];
+    sprintf(string, "%p", internal->value_);
+    return CYCastJSValue(context, string);
+} CYCatch }
+
+static JSValueRef Pointer_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    Pointer *internal(reinterpret_cast<Pointer *>(JSObjectGetPrivate(_this)));
+    if (internal->length_ != _not(size_t)) {
+        JSObjectRef Array(CYGetCachedObject(context, Array_s));
+        JSObjectRef toCYON(CYCastJSObject(context, CYGetProperty(context, Array, toCYON_s)));
+        return CYCallAsFunction(context, toCYON, _this, count, arguments);
+    } else {
+        char string[32];
+        sprintf(string, "%p", internal->value_);
+        return CYCastJSValue(context, string);
+    }
+} CYCatch }
+
+static JSValueRef Type_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
+    CYPool pool;
+    const char *type(sig::Unparse(pool, internal->type_));
+    return CYCastJSValue(context, CYJSString(type));
+} CYCatch }
+
+static JSValueRef Type_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
+    CYPool pool;
+    const char *type(sig::Unparse(pool, internal->type_));
+    size_t size(strlen(type));
+    char *cyon(new(pool) char[12 + size + 1]);
+    memcpy(cyon, "new Type(\"", 10);
+    cyon[12 + size] = '\0';
+    cyon[12 + size - 2] = '"';
+    cyon[12 + size - 1] = ')';
+    memcpy(cyon + 10, type, size);
+    return CYCastJSValue(context, CYJSString(cyon));
+} CYCatch }
+
+static JSValueRef Type_callAsFunction_toJSON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
+    return Type_callAsFunction_toString(context, object, _this, count, arguments, exception);
+}
+
+static JSStaticFunction Pointer_staticFunctions[4] = {
+    {"toCYON", &Pointer_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"toJSON", &CYValue_callAsFunction_toJSON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"valueOf", &CYValue_callAsFunction_valueOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {NULL, NULL, 0}
+};
+
+static JSStaticFunction Struct_staticFunctions[2] = {
+    {"$cya", &Struct_callAsFunction_$cya, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {NULL, NULL, 0}
+};
+
+static JSStaticFunction Functor_staticFunctions[4] = {
+    {"toCYON", &CYValue_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"toJSON", &CYValue_callAsFunction_toJSON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"valueOf", &CYValue_callAsFunction_valueOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {NULL, NULL, 0}
+};
+
+namespace cy {
+    JSStaticFunction const * const Functor::StaticFunctions = Functor_staticFunctions;
+}
+
+static JSStaticFunction Type_staticFunctions[4] = {
+    {"toCYON", &Type_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"toJSON", &Type_callAsFunction_toJSON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"toString", &Type_callAsFunction_toString, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {NULL, NULL, 0}
+};
+
+static JSObjectRef (*JSObjectMakeArray$)(JSContextRef, size_t, const JSValueRef[], JSValueRef *);
+
+void CYSetArgs(int argc, const char *argv[]) {
+    JSContextRef context(CYGetJSContext());
+    JSValueRef args[argc];
+    for (int i(0); i != argc; ++i)
+        args[i] = CYCastJSValue(context, argv[i]);
+
+    JSObjectRef array;
+    if (JSObjectMakeArray$ != NULL) {
+        JSValueRef exception(NULL);
+        array = (*JSObjectMakeArray$)(context, argc, args, &exception);
+        CYThrow(context, exception);
+    } else {
+        JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array")));
+        JSValueRef value(CYCallAsFunction(context, Array, NULL, argc, args));
+        array = CYCastJSObject(context, value);
+    }
+
+    JSObjectRef System(CYGetCachedObject(context, CYJSString("System")));
+    CYSetProperty(context, System, CYJSString("args"), array);
+}
+
+JSObjectRef CYGetGlobalObject(JSContextRef context) {
+    return JSContextGetGlobalObject(context);
+}
+
+const char *CYExecute(apr_pool_t *pool, const char *code) {
+    JSContextRef context(CYGetJSContext());
+    JSValueRef exception(NULL), result;
+
+    void *handle;
+    if (hooks_ != NULL && hooks_->ExecuteStart != NULL)
+        handle = (*hooks_->ExecuteStart)(context);
+    else
+        handle = NULL;
+
+    const char *json;
+
+    try {
+        result = JSEvaluateScript(context, CYJSString(code), NULL, NULL, 0, &exception);
+    } catch (const char *error) {
+        return error;
+    }
+
+    if (exception != NULL) { error:
+        result = exception;
+        exception = NULL;
+    }
+
+    if (JSValueIsUndefined(context, result))
+        return NULL;
+
+    try {
+        json = CYPoolCCYON(pool, context, result, &exception);
+    } catch (const char *error) {
+        return error;
+    }
+
+    if (exception != NULL)
+        goto error;
+
+    CYSetProperty(context, CYGetGlobalObject(context), Result_, result);
+
+    if (hooks_ != NULL && hooks_->ExecuteEnd != NULL)
+        (*hooks_->ExecuteEnd)(context, handle);
+    return json;
+}
+
+extern "C" void CydgetSetupContext(JSGlobalContextRef context) {
+    CYSetupContext(context);
+}
+
+void CYInitializeDynamic() {
+    CYInitializeStatic();
+
+    _sqlcall(sqlite3_open("/usr/lib/libcycript.db", &Bridge_));
+
+    JSObjectMakeArray$ = reinterpret_cast<JSObjectRef (*)(JSContextRef, size_t, const JSValueRef[], JSValueRef *)>(dlsym(RTLD_DEFAULT, "JSObjectMakeArray"));
+
+    JSClassDefinition definition;
+
+    definition = kJSClassDefinitionEmpty;
+    definition.className = "All";
+    definition.getProperty = &All_getProperty;
+    All_ = JSClassCreate(&definition);
+
+    definition = kJSClassDefinitionEmpty;
+    definition.className = "Context";
+    definition.finalize = &CYFinalize;
+    Context_ = JSClassCreate(&definition);
+
+    definition = kJSClassDefinitionEmpty;
+    definition.className = "Functor";
+    definition.staticFunctions = cy::Functor::StaticFunctions;
+    definition.callAsFunction = &Functor_callAsFunction;
+    definition.finalize = &CYFinalize;
+    Functor_ = JSClassCreate(&definition);
+
+    definition = kJSClassDefinitionEmpty;
+    definition.className = "Pointer";
+    definition.staticFunctions = Pointer_staticFunctions;
+    definition.getProperty = &Pointer_getProperty;
+    definition.setProperty = &Pointer_setProperty;
+    definition.finalize = &CYFinalize;
+    Pointer_ = JSClassCreate(&definition);
+
+    definition = kJSClassDefinitionEmpty;
+    definition.className = "Struct";
+    definition.staticFunctions = Struct_staticFunctions;
+    definition.getProperty = &Struct_getProperty;
+    definition.setProperty = &Struct_setProperty;
+    definition.getPropertyNames = &Struct_getPropertyNames;
+    definition.finalize = &CYFinalize;
+    Struct_ = JSClassCreate(&definition);
+
+    definition = kJSClassDefinitionEmpty;
+    definition.className = "Type";
+    definition.staticFunctions = Type_staticFunctions;
+    definition.getProperty = &Type_getProperty;
+    definition.callAsFunction = &Type_callAsFunction;
+    definition.callAsConstructor = &Type_callAsConstructor;
+    definition.finalize = &CYFinalize;
+    Type_privateData::Class_ = JSClassCreate(&definition);
+
+    definition = kJSClassDefinitionEmpty;
+    //definition.getProperty = &Global_getProperty;
+    Global_ = JSClassCreate(&definition);
+
+    Array_s = JSStringCreateWithUTF8CString("Array");
+    cy_s = JSStringCreateWithUTF8CString("$cy");
+    length_s = JSStringCreateWithUTF8CString("length");
+    message_s = JSStringCreateWithUTF8CString("message");
+    name_s = JSStringCreateWithUTF8CString("name");
+    pop_s = JSStringCreateWithUTF8CString("pop");
+    prototype_s = JSStringCreateWithUTF8CString("prototype");
+    push_s = JSStringCreateWithUTF8CString("push");
+    splice_s = JSStringCreateWithUTF8CString("splice");
+    toCYON_s = JSStringCreateWithUTF8CString("toCYON");
+    toJSON_s = JSStringCreateWithUTF8CString("toJSON");
+
+    Result_ = JSStringCreateWithUTF8CString("_");
+
+    if (hooks_ != NULL && hooks_->Initialize != NULL)
+        (*hooks_->Initialize)();
+}
+
+void CYThrow(JSContextRef context, JSValueRef value) {
+    if (value != NULL)
+        throw CYJSError(context, value);
+}
+
+const char *CYJSError::PoolCString(apr_pool_t *pool) const {
+    // XXX: this used to be CYPoolCString
+    return CYPoolCCYON(pool, context_, value_);
+}
+
+JSValueRef CYJSError::CastJSValue(JSContextRef context) const {
+    // XXX: what if the context is different?
+    return value_;
+}
+
+JSValueRef CYCastJSError(JSContextRef context, const char *message) {
+    JSObjectRef Error(CYGetCachedObject(context, CYJSString("Error")));
+
+    JSValueRef arguments[1] = {CYCastJSValue(context, message)};
+
+    JSValueRef exception(NULL);
+    JSValueRef value(JSObjectCallAsConstructor(context, Error, 1, arguments, &exception));
+    CYThrow(context, exception);
+
+    return value;
+}
+
+JSValueRef CYPoolError::CastJSValue(JSContextRef context) const {
+    return CYCastJSError(context, message_);
+}
+
+CYJSError::CYJSError(JSContextRef context, const char *format, ...) {
+    _assert(context != NULL);
+
+    CYPool pool;
+
+    va_list args;
+    va_start(args, format);
+    const char *message(apr_pvsprintf(pool, format, args));
+    va_end(args);
+
+    value_ = CYCastJSError(context, message);
+}
+
+JSGlobalContextRef CYGetJSContext(JSContextRef context) {
+    return reinterpret_cast<Context *>(JSObjectGetPrivate(CYCastJSObject(context, CYGetProperty(context, CYGetGlobalObject(context), cy_s))))->context_;
+}
+
+extern "C" void CYSetupContext(JSGlobalContextRef context) {
+    CYInitializeDynamic();
+
+    JSObjectRef global(CYGetGlobalObject(context));
+
+    JSObjectRef cy(JSObjectMake(context, Context_, new Context(context)));
+    CYSetProperty(context, global, cy_s, cy, kJSPropertyAttributeDontEnum);
+
+/* Cache Globals {{{ */
+    JSObjectRef Array(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Array"))));
+    CYSetProperty(context, cy, CYJSString("Array"), Array);
+
+    JSObjectRef Array_prototype(CYCastJSObject(context, CYGetProperty(context, Array, prototype_s)));
+    CYSetProperty(context, cy, CYJSString("Array_prototype"), Array_prototype);
+
+    JSObjectRef Error(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Error"))));
+    CYSetProperty(context, cy, CYJSString("Error"), Error);
+
+    JSObjectRef Function(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Function"))));
+    CYSetProperty(context, cy, CYJSString("Function"), Function);
+
+    JSObjectRef Function_prototype(CYCastJSObject(context, CYGetProperty(context, Function, prototype_s)));
+    CYSetProperty(context, cy, CYJSString("Function_prototype"), Function_prototype);
+
+    JSObjectRef Object(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Object"))));
+    CYSetProperty(context, cy, CYJSString("Object"), Object);
+
+    JSObjectRef Object_prototype(CYCastJSObject(context, CYGetProperty(context, Object, prototype_s)));
+    CYSetProperty(context, cy, CYJSString("Object_prototype"), Object_prototype);
+
+    JSObjectRef String(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("String"))));
+    CYSetProperty(context, cy, CYJSString("String"), String);
+/* }}} */
+
+    CYSetProperty(context, Array_prototype, toCYON_s, &Array_callAsFunction_toCYON, kJSPropertyAttributeDontEnum);
+
+    JSObjectRef cycript(JSObjectMake(context, NULL, NULL));
+    CYSetProperty(context, global, CYJSString("Cycript"), cycript);
+    CYSetProperty(context, cycript, CYJSString("gc"), &Cycript_gc_callAsFunction);
+
+    JSObjectRef Functor(JSObjectMakeConstructor(context, Functor_, &Functor_new));
+    JSObjectSetPrototype(context, CYCastJSObject(context, CYGetProperty(context, Functor, prototype_s)), Function_prototype);
+    CYSetProperty(context, cycript, CYJSString("Functor"), Functor);
+
+    CYSetProperty(context, cycript, CYJSString("Pointer"), JSObjectMakeConstructor(context, Pointer_, &Pointer_new));
+    CYSetProperty(context, cycript, CYJSString("Type"), JSObjectMakeConstructor(context, Type_privateData::Class_, &Type_new));
+
+    JSObjectRef all(JSObjectMake(context, All_, NULL));
+    CYSetProperty(context, cycript, CYJSString("all"), all);
+
+    JSObjectRef last(NULL), curr(global);
+
+    goto next; for (JSValueRef next;;) {
+        if (JSValueIsNull(context, next))
+            break;
+        last = curr;
+        curr = CYCastJSObject(context, next);
+      next:
+        next = JSObjectGetPrototype(context, curr);
+    }
+
+    JSObjectSetPrototype(context, last, all);
+
+    CYSetProperty(context, global, CYJSString("$cyq"), &$cyq);
+
+    JSObjectRef System(JSObjectMake(context, NULL, NULL));
+    CYSetProperty(context, cy, CYJSString("System"), Function);
+
+    CYSetProperty(context, global, CYJSString("system"), System);
+    CYSetProperty(context, System, CYJSString("args"), CYJSNull(context));
+    //CYSetProperty(context, System, CYJSString("global"), global);
+    CYSetProperty(context, System, CYJSString("print"), &System_print);
+
+    if (hooks_ != NULL && hooks_->SetupContext != NULL)
+        (*hooks_->SetupContext)(context);
+}
+
+JSGlobalContextRef CYGetJSContext() {
+    CYInitializeDynamic();
+
+    static JSGlobalContextRef context_;
+
+    if (context_ == NULL) {
+        context_ = JSGlobalContextCreate(Global_);
+        CYSetupContext(context_);
+    }
+
+    return context_;
+}
diff --git a/Execute.mk b/Execute.mk
new file mode 100644 (file)
index 0000000..1102aa2
--- /dev/null
@@ -0,0 +1,19 @@
+CY_EXECUTE :=
+flags += -DCY_EXECUTE
+code += sig/ffi_type.o sig/parse.o sig/copy.o
+code += Execute.o
+library += $(apr) -lffi -lsqlite3
+all += libcycript.db
+filters += C
+
+extra::
+       cp -pR libcycript.db package/usr/lib
+
+libcycript.db: Bridge.def
+       rm -f libcycript.db
+       { \
+           echo 'create table "bridge" ("mode" int not null, "name" text not null, "value" text null);'; \
+           grep '^[CFV]' Bridge.def | sed -e 's/^C/0/;s/^F/1/;s/^V/2/' | sed -e 's/"/\\"/g;s/^\([^ ]*\) \([^ ]*\) \(.*\)$$/insert into "bridge" ("mode", "name", "value") values (\1, '"'"'\2'"'"', '"'"'\3'"'"');/'; \
+           grep '^:' Bridge.def | sed -e 's/^: \([^ ]*\) \(.*\)/insert into "bridge" ("mode", "name", "value") values (-1, '"'"'\1'"'"', '"'"'\2'"'"');/'; \
+           grep '^[EST]' Bridge.def | sed -e 's/^S/3/;s/^T/4/;s/^E/5/' | sed -e 's/^5\(.*\)$$/4\1 i/' | sed -e 's/^\([^ ]*\) \([^ ]*\) \(.*\)$$/insert into "bridge" ("mode", "name", "value") values (\1, '"'"'\2'"'"', '"'"'\3'"'"');/'; \
+       } | tee libcycript.sql | sqlite3 libcycript.db
index 6b4feee3871f3f15046beec6286921830c365c45..0398df551906f058c8d7222f09358bda5013dfa6 100644 (file)
@@ -1,4 +1,4 @@
 export PATH := /usr/local/bin:$(PATH)
-flags += -DCY_EXECUTE
+include Execute.mk
 flags += -I/usr/local/include -I/usr/local/include/webkit-1.0
 library += -lwebkit-1.0
index db14eb94a411b66e6c647c1c522f2a9ad324531e..9e9c85211df6648e070ebec9ce820506675eeb3f 100644 (file)
 #ifndef CYCRIPT_JAVASCRIPT_HPP
 #define CYCRIPT_JAVASCRIPT_HPP
 
+#include <JavaScriptCore/JSBase.h>
+#include <JavaScriptCore/JSContextRef.h>
+#include <JavaScriptCore/JSStringRef.h>
+#include <JavaScriptCore/JSObjectRef.h>
+#include <JavaScriptCore/JSValueRef.h>
+
+#include <ffi.h>
+#include <sqlite3.h>
+
 extern JSStringRef Array_s;
 extern JSStringRef cy_s;
 extern JSStringRef length_s;
@@ -52,4 +61,137 @@ extern JSStringRef splice_s;
 extern JSStringRef toCYON_s;
 extern JSStringRef toJSON_s;
 
+void CYInitializeDynamic();
+JSGlobalContextRef CYGetJSContext();
+JSObjectRef CYGetGlobalObject(JSContextRef context);
+
+extern "C" void CYSetupContext(JSGlobalContextRef context);
+const char *CYExecute(apr_pool_t *pool, const char *code);
+
+void CYSetArgs(int argc, const char *argv[]);
+
+bool CYCastBool(JSContextRef context, JSValueRef value);
+double CYCastDouble(JSContextRef context, JSValueRef value);
+
+CYUTF8String CYPoolUTF8String(apr_pool_t *pool, JSContextRef context, JSStringRef value);
+const char *CYPoolCString(apr_pool_t *pool, JSContextRef context, JSStringRef value);
+
+JSValueRef CYGetProperty(JSContextRef context, JSObjectRef object, size_t index);
+JSValueRef CYGetProperty(JSContextRef context, JSObjectRef object, JSStringRef name);
+
+void CYSetProperty(JSContextRef context, JSObjectRef object, size_t index, JSValueRef value);
+void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef value, JSPropertyAttributes attributes = kJSPropertyAttributeNone);
+void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef (*callback)(JSContextRef, JSObjectRef, JSObjectRef, size_t, const JSValueRef[], JSValueRef *), JSPropertyAttributes attributes = kJSPropertyAttributeNone);
+
+JSObjectRef CYGetCachedObject(JSContextRef context, JSStringRef name);
+
+JSValueRef CYCastJSValue(JSContextRef context, bool value);
+JSValueRef CYCastJSValue(JSContextRef context, double value);
+JSValueRef CYCastJSValue(JSContextRef context, int value);
+JSValueRef CYCastJSValue(JSContextRef context, unsigned int value);
+JSValueRef CYCastJSValue(JSContextRef context, long int value);
+JSValueRef CYCastJSValue(JSContextRef context, long unsigned int value);
+JSValueRef CYCastJSValue(JSContextRef context, long long int value);
+JSValueRef CYCastJSValue(JSContextRef context, long long unsigned int value);
+
+JSValueRef CYCastJSValue(JSContextRef context, JSStringRef value);
+JSValueRef CYCastJSValue(JSContextRef context, const char *value);
+
+JSObjectRef CYCastJSObject(JSContextRef context, JSValueRef value);
+JSValueRef CYJSUndefined(JSContextRef context);
+JSValueRef CYJSNull(JSContextRef context);
+
+void *CYCastPointer_(JSContextRef context, JSValueRef value);
+
+template <typename Type_>
+_finline Type_ CYCastPointer(JSContextRef context, JSValueRef value) {
+    return reinterpret_cast<Type_>(CYCastPointer_(context, value));
+}
+
+void CYPoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, JSValueRef value);
+JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, bool initialize = false, JSObjectRef owner = NULL);
+
+JSValueRef CYCallFunction(apr_pool_t *pool, JSContextRef context, size_t setups, void *setup[], size_t count, const JSValueRef arguments[], bool initialize, JSValueRef *exception, sig::Signature *signature, ffi_cif *cif, void (*function)());
+
+bool CYIsCallable(JSContextRef context, JSValueRef value);
+JSValueRef CYCallAsFunction(JSContextRef context, JSObjectRef function, JSObjectRef _this, size_t count, const JSValueRef arguments[]);
+
+const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSObjectRef object);
+
+struct CYHooks {
+    void *(*ExecuteStart)(JSContextRef);
+    void (*ExecuteEnd)(JSContextRef, void *);
+
+    JSValueRef (*RuntimeProperty)(JSContextRef, CYUTF8String);
+    void (*CallFunction)(JSContextRef, ffi_cif *, void (*)(), uint8_t *, void **);
+
+    void (*Initialize)();
+    void (*SetupContext)(JSContextRef);
+
+    bool (*PoolFFI)(apr_pool_t *, JSContextRef, sig::Type *, ffi_type *, void *, JSValueRef);
+    JSValueRef (*FromFFI)(JSContextRef, sig::Type *, ffi_type *, void *, bool, JSObjectRef);
+};
+
+extern struct CYHooks *hooks_;
+
+char *sqlite3_column_pooled(apr_pool_t *pool, sqlite3_stmt *stmt, int n);
+
+JSObjectRef CYMakePointer(JSContextRef context, void *pointer, size_t length, sig::Type *type, ffi_type *ffi, JSObjectRef owner);
+
+void CYFinalize(JSObjectRef object);
+
+const char *CYPoolCString(apr_pool_t *pool, JSContextRef context, JSValueRef value);
+
+JSStringRef CYCopyJSString(const char *value);
+JSStringRef CYCopyJSString(JSStringRef value);
+JSStringRef CYCopyJSString(CYUTF8String value);
+JSStringRef CYCopyJSString(JSContextRef context, JSValueRef value);
+
+class CYJSString {
+  private:
+    JSStringRef string_;
+
+    void Clear_() {
+        if (string_ != NULL)
+            JSStringRelease(string_);
+    }
+
+  public:
+    CYJSString(const CYJSString &rhs) :
+        string_(CYCopyJSString(rhs.string_))
+    {
+    }
+
+    template <typename Arg0_>
+    CYJSString(Arg0_ arg0) :
+        string_(CYCopyJSString(arg0))
+    {
+    }
+
+    template <typename Arg0_, typename Arg1_>
+    CYJSString(Arg0_ arg0, Arg1_ arg1) :
+        string_(CYCopyJSString(arg0, arg1))
+    {
+    }
+
+    CYJSString &operator =(const CYJSString &rhs) {
+        Clear_();
+        string_ = CYCopyJSString(rhs.string_);
+        return *this;
+    }
+
+    ~CYJSString() {
+        Clear_();
+    }
+
+    void Clear() {
+        Clear_();
+        string_ = NULL;
+    }
+
+    operator JSStringRef() const {
+        return string_;
+    }
+};
+
 #endif/*CYCRIPT_JAVASCRIPT_HPP*/
index 48062d41627b73f22eb936fa8974e4233c1d4db0..8068e821bae4f8b2b3aa7a339c1459e93f60c9a0 100644 (file)
 */
 /* }}} */
 
-#include <sqlite3.h>
-
-#include "Internal.hpp"
-
 #include <dlfcn.h>
 #include <iconv.h>
 
 #include "cycript.hpp"
 
-#include "sig/parse.hpp"
-#include "sig/ffi_type.hpp"
-
 #include "Pooling.hpp"
 
 #include <sys/mman.h>
 #include "Cycript.tab.hh"
 
 #include "Error.hpp"
-#include "JavaScript.hpp"
 #include "String.hpp"
 
-#ifdef __OBJC__
-#define CYCatch_ \
-    catch (NSException *error) { \
-        CYThrow(context, error, exception); \
-        return NULL; \
-    }
-#else
-#define CYCatch_
-#endif
-
-char *sqlite3_column_pooled(apr_pool_t *pool, sqlite3_stmt *stmt, int n) {
-    if (const unsigned char *value = sqlite3_column_text(stmt, n))
-        return apr_pstrdup(pool, (const char *) value);
-    else return NULL;
-}
-
-struct CYHooks *hooks_;
-
 /* C Strings {{{ */
 template <typename Type_>
 _finline size_t iconv_(size_t (*iconv)(iconv_t, Type_, size_t *, char **, size_t *), iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) {
@@ -145,79 +119,6 @@ CYUTF16String CYPoolUTF16String(apr_pool_t *pool, CYUTF8String utf8) {
     return utf16;
 }
 /* }}} */
-/* JavaScript Properties {{{ */
-JSValueRef CYGetProperty(JSContextRef context, JSObjectRef object, size_t index) {
-    JSValueRef exception(NULL);
-    JSValueRef value(JSObjectGetPropertyAtIndex(context, object, index, &exception));
-    CYThrow(context, exception);
-    return value;
-}
-
-JSValueRef CYGetProperty(JSContextRef context, JSObjectRef object, JSStringRef name) {
-    JSValueRef exception(NULL);
-    JSValueRef value(JSObjectGetProperty(context, object, name, &exception));
-    CYThrow(context, exception);
-    return value;
-}
-
-void CYSetProperty(JSContextRef context, JSObjectRef object, size_t index, JSValueRef value) {
-    JSValueRef exception(NULL);
-    JSObjectSetPropertyAtIndex(context, object, index, value, &exception);
-    CYThrow(context, exception);
-}
-
-void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef value, JSPropertyAttributes attributes) {
-    JSValueRef exception(NULL);
-    JSObjectSetProperty(context, object, name, value, attributes, &exception);
-    CYThrow(context, exception);
-}
-
-void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef (*callback)(JSContextRef, JSObjectRef, JSObjectRef, size_t, const JSValueRef[], JSValueRef *), JSPropertyAttributes attributes) {
-    CYSetProperty(context, object, name, JSObjectMakeFunctionWithCallback(context, name, callback), attributes);
-}
-/* }}} */
-/* JavaScript Strings {{{ */
-JSStringRef CYCopyJSString(const char *value) {
-    return value == NULL ? NULL : JSStringCreateWithUTF8CString(value);
-}
-
-JSStringRef CYCopyJSString(JSStringRef value) {
-    return value == NULL ? NULL : JSStringRetain(value);
-}
-
-JSStringRef CYCopyJSString(CYUTF8String value) {
-    // XXX: this is very wrong; it needs to convert to UTF16 and then create from there
-    return CYCopyJSString(value.data);
-}
-
-JSStringRef CYCopyJSString(JSContextRef context, JSValueRef value) {
-    if (JSValueIsNull(context, value))
-        return NULL;
-    JSValueRef exception(NULL);
-    JSStringRef string(JSValueToStringCopy(context, value, &exception));
-    CYThrow(context, exception);
-    return string;
-}
-
-static CYUTF16String CYCastUTF16String(JSStringRef value) {
-    return CYUTF16String(JSStringGetCharactersPtr(value), JSStringGetLength(value));
-}
-
-CYUTF8String CYPoolUTF8String(apr_pool_t *pool, JSContextRef context, JSStringRef value) {
-    return CYPoolUTF8String(pool, CYCastUTF16String(value));
-}
-
-const char *CYPoolCString(apr_pool_t *pool, JSContextRef context, JSStringRef value) {
-    CYUTF8String utf8(CYPoolUTF8String(pool, context, value));
-    _assert(memchr(utf8.data, '\0', utf8.size) == NULL);
-    return utf8.data;
-}
-
-const char *CYPoolCString(apr_pool_t *pool, JSContextRef context, JSValueRef value) {
-    return JSValueIsNull(context, value) ? NULL : CYPoolCString(pool, context, CYJSString(context, value));
-}
-/* }}} */
-
 /* Index Offsets {{{ */
 size_t CYGetIndex(const CYUTF8String &value) {
     if (value.data[0] != '0') {
@@ -235,10 +136,6 @@ size_t CYGetIndex(const CYUTF8String &value) {
         return _not(size_t);
 }
 
-size_t CYGetIndex(apr_pool_t *pool, JSContextRef context, JSStringRef value) {
-    return CYGetIndex(CYPoolUTF8String(pool, context, value));
-}
-
 // XXX: this isn't actually right
 bool CYGetOffset(const char *value, ssize_t &index) {
     if (value[0] != '0') {
@@ -254,7 +151,6 @@ bool CYGetOffset(const char *value, ssize_t &index) {
     return false;
 }
 /* }}} */
-
 /* JavaScript *ify {{{ */
 void CYStringify(std::ostringstream &str, const char *data, size_t size) {
     unsigned quot(0), apos(0);
@@ -331,185 +227,6 @@ bool CYIsKey(CYUTF8String value) {
 }
 /* }}} */
 
-static JSClassRef All_;
-static JSClassRef Context_;
-static JSClassRef Functor_;
-static JSClassRef Global_;
-static JSClassRef Pointer_;
-static JSClassRef Struct_;
-
-JSStringRef Array_s;
-JSStringRef cy_s;
-JSStringRef length_s;
-JSStringRef message_s;
-JSStringRef name_s;
-JSStringRef pop_s;
-JSStringRef prototype_s;
-JSStringRef push_s;
-JSStringRef splice_s;
-JSStringRef toCYON_s;
-JSStringRef toJSON_s;
-
-static JSStringRef Result_;
-
-sqlite3 *Bridge_;
-
-void CYFinalize(JSObjectRef object) {
-    delete reinterpret_cast<CYData *>(JSObjectGetPrivate(object));
-}
-
-struct CStringMapLess :
-    std::binary_function<const char *, const char *, bool>
-{
-    _finline bool operator ()(const char *lhs, const char *rhs) const {
-        return strcmp(lhs, rhs) < 0;
-    }
-};
-
-void Structor_(apr_pool_t *pool, sig::Type *&type) {
-    if (
-        type->primitive == sig::pointer_P &&
-        type->data.data.type != NULL &&
-        type->data.data.type->primitive == sig::struct_P &&
-        strcmp(type->data.data.type->name, "_objc_class") == 0
-    ) {
-        type->primitive = sig::typename_P;
-        type->data.data.type = NULL;
-        return;
-    }
-
-    if (type->primitive != sig::struct_P || type->name == NULL)
-        return;
-
-    sqlite3_stmt *statement;
-
-    _sqlcall(sqlite3_prepare(Bridge_,
-        "select "
-            "\"bridge\".\"mode\", "
-            "\"bridge\".\"value\" "
-        "from \"bridge\" "
-        "where"
-            " \"bridge\".\"mode\" in (3, 4) and"
-            " \"bridge\".\"name\" = ?"
-        " limit 1"
-    , -1, &statement, NULL));
-
-    _sqlcall(sqlite3_bind_text(statement, 1, type->name, -1, SQLITE_STATIC));
-
-    int mode;
-    const char *value;
-
-    if (_sqlcall(sqlite3_step(statement)) == SQLITE_DONE) {
-        mode = -1;
-        value = NULL;
-    } else {
-        mode = sqlite3_column_int(statement, 0);
-        value = sqlite3_column_pooled(pool, statement, 1);
-    }
-
-    _sqlcall(sqlite3_finalize(statement));
-
-    switch (mode) {
-        default:
-            _assert(false);
-        case -1:
-            break;
-
-        case 3: {
-            sig::Parse(pool, &type->data.signature, value, &Structor_);
-        } break;
-
-        case 4: {
-            sig::Signature signature;
-            sig::Parse(pool, &signature, value, &Structor_);
-            type = signature.elements[0].type;
-        } break;
-    }
-}
-
-JSClassRef Type_privateData::Class_;
-
-struct Context :
-    CYData
-{
-    JSGlobalContextRef context_;
-
-    Context(JSGlobalContextRef context) :
-        context_(context)
-    {
-    }
-};
-
-struct Pointer :
-    CYOwned
-{
-    Type_privateData *type_;
-    size_t length_;
-
-    Pointer(void *value, JSContextRef context, JSObjectRef owner, size_t length, sig::Type *type) :
-        CYOwned(value, context, owner),
-        type_(new(pool_) Type_privateData(type)),
-        length_(length)
-    {
-    }
-};
-
-struct Struct_privateData :
-    CYOwned
-{
-    Type_privateData *type_;
-
-    Struct_privateData(JSContextRef context, JSObjectRef owner) :
-        CYOwned(NULL, context, owner)
-    {
-    }
-};
-
-typedef std::map<const char *, Type_privateData *, CStringMapLess> TypeMap;
-static TypeMap Types_;
-
-JSObjectRef CYMakeStruct(JSContextRef context, void *data, sig::Type *type, ffi_type *ffi, JSObjectRef owner) {
-    Struct_privateData *internal(new Struct_privateData(context, owner));
-    apr_pool_t *pool(internal->pool_);
-    Type_privateData *typical(new(pool) Type_privateData(type, ffi));
-    internal->type_ = typical;
-
-    if (owner != NULL)
-        internal->value_ = data;
-    else {
-        size_t size(typical->GetFFI()->size);
-        void *copy(apr_palloc(internal->pool_, size));
-        memcpy(copy, data, size);
-        internal->value_ = copy;
-    }
-
-    return JSObjectMake(context, Struct_, internal);
-}
-
-JSValueRef CYCastJSValue(JSContextRef context, bool value) {
-    return JSValueMakeBoolean(context, value);
-}
-
-JSValueRef CYCastJSValue(JSContextRef context, double value) {
-    return JSValueMakeNumber(context, value);
-}
-
-#define CYCastJSValue_(Type_) \
-    JSValueRef CYCastJSValue(JSContextRef context, Type_ value) { \
-        return JSValueMakeNumber(context, static_cast<double>(value)); \
-    }
-
-CYCastJSValue_(int)
-CYCastJSValue_(unsigned int)
-CYCastJSValue_(long int)
-CYCastJSValue_(long unsigned int)
-CYCastJSValue_(long long int)
-CYCastJSValue_(long long unsigned int)
-
-JSValueRef CYJSUndefined(JSContextRef context) {
-    return JSValueMakeUndefined(context);
-}
-
 double CYCastDouble(const char *value, size_t size) {
     char *end;
     double number(strtod(value, &end));
@@ -522,952 +239,6 @@ double CYCastDouble(const char *value) {
     return CYCastDouble(value, strlen(value));
 }
 
-double CYCastDouble(JSContextRef context, JSValueRef value) {
-    JSValueRef exception(NULL);
-    double number(JSValueToNumber(context, value, &exception));
-    CYThrow(context, exception);
-    return number;
-}
-
-bool CYCastBool(JSContextRef context, JSValueRef value) {
-    return JSValueToBoolean(context, value);
-}
-
-JSValueRef CYJSNull(JSContextRef context) {
-    return JSValueMakeNull(context);
-}
-
-JSValueRef CYCastJSValue(JSContextRef context, JSStringRef value) {
-    return value == NULL ? CYJSNull(context) : JSValueMakeString(context, value);
-}
-
-JSValueRef CYCastJSValue(JSContextRef context, const char *value) {
-    return CYCastJSValue(context, CYJSString(value));
-}
-
-JSObjectRef CYCastJSObject(JSContextRef context, JSValueRef value) {
-    JSValueRef exception(NULL);
-    JSObjectRef object(JSValueToObject(context, value, &exception));
-    CYThrow(context, exception);
-    return object;
-}
-
-JSValueRef CYCallAsFunction(JSContextRef context, JSObjectRef function, JSObjectRef _this, size_t count, const JSValueRef arguments[]) {
-    JSValueRef exception(NULL);
-    JSValueRef value(JSObjectCallAsFunction(context, function, _this, count, arguments, &exception));
-    CYThrow(context, exception);
-    return value;
-}
-
-bool CYIsCallable(JSContextRef context, JSValueRef value) {
-    return value != NULL && JSValueIsObject(context, value) && JSObjectIsFunction(context, (JSObjectRef) value);
-}
-
-static JSValueRef System_print(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    if (count == 0)
-        printf("\n");
-    else {
-        CYPool pool;
-        printf("%s\n", CYPoolCString(pool, context, arguments[0]));
-    }
-
-    return CYJSUndefined(context);
-} CYCatch }
-
-static size_t Nonce_(0);
-
-static JSValueRef $cyq(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
-    CYPool pool;
-    const char *name(apr_psprintf(pool, "%s%"APR_SIZE_T_FMT"", CYPoolCString(pool, context, arguments[0]), Nonce_++));
-    return CYCastJSValue(context, name);
-}
-
-static JSValueRef Cycript_gc_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
-    JSGarbageCollect(context);
-    return CYJSUndefined(context);
-}
-
-const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSValueRef value, JSValueRef *exception) { CYTry {
-    switch (JSType type = JSValueGetType(context, value)) {
-        case kJSTypeUndefined:
-            return "undefined";
-        case kJSTypeNull:
-            return "null";
-        case kJSTypeBoolean:
-            return CYCastBool(context, value) ? "true" : "false";
-
-        case kJSTypeNumber: {
-            std::ostringstream str;
-            CYNumerify(str, CYCastDouble(context, value));
-            std::string value(str.str());
-            return apr_pstrmemdup(pool, value.c_str(), value.size());
-        } break;
-
-        case kJSTypeString: {
-            std::ostringstream str;
-            CYUTF8String string(CYPoolUTF8String(pool, context, CYJSString(context, value)));
-            CYStringify(str, string.data, string.size);
-            std::string value(str.str());
-            return apr_pstrmemdup(pool, value.c_str(), value.size());
-        } break;
-
-        case kJSTypeObject:
-            return CYPoolCCYON(pool, context, (JSObjectRef) value);
-        default:
-            throw CYJSError(context, "JSValueGetType() == 0x%x", type);
-    }
-} CYCatch }
-
-const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSValueRef value) {
-    JSValueRef exception(NULL);
-    const char *cyon(CYPoolCCYON(pool, context, value, &exception));
-    CYThrow(context, exception);
-    return cyon;
-}
-
-const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSObjectRef object) {
-    JSValueRef toCYON(CYGetProperty(context, object, toCYON_s));
-    if (CYIsCallable(context, toCYON)) {
-        JSValueRef value(CYCallAsFunction(context, (JSObjectRef) toCYON, object, 0, NULL));
-        _assert(value != NULL);
-        return CYPoolCString(pool, context, value);
-    }
-
-    JSValueRef toJSON(CYGetProperty(context, object, toJSON_s));
-    if (CYIsCallable(context, toJSON)) {
-        JSValueRef arguments[1] = {CYCastJSValue(context, CYJSString(""))};
-        JSValueRef exception(NULL);
-        const char *cyon(CYPoolCCYON(pool, context, CYCallAsFunction(context, (JSObjectRef) toJSON, object, 1, arguments), &exception));
-        CYThrow(context, exception);
-        return cyon;
-    }
-
-    std::ostringstream str;
-
-    str << '{';
-
-    // XXX: this is, sadly, going to leak
-    JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context, object));
-
-    bool comma(false);
-
-    for (size_t index(0), count(JSPropertyNameArrayGetCount(names)); index != count; ++index) {
-        JSStringRef name(JSPropertyNameArrayGetNameAtIndex(names, index));
-        JSValueRef value(CYGetProperty(context, object, name));
-
-        if (comma)
-            str << ',';
-        else
-            comma = true;
-
-        CYUTF8String string(CYPoolUTF8String(pool, context, name));
-        if (CYIsKey(string))
-            str << string.data;
-        else
-            CYStringify(str, string.data, string.size);
-
-        str << ':' << CYPoolCCYON(pool, context, value);
-    }
-
-    str << '}';
-
-    JSPropertyNameArrayRelease(names);
-
-    std::string string(str.str());
-    return apr_pstrmemdup(pool, string.c_str(), string.size());
-}
-
-static JSValueRef Array_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    CYPool pool;
-    std::ostringstream str;
-
-    str << '[';
-
-    JSValueRef length(CYGetProperty(context, _this, length_s));
-    bool comma(false);
-
-    for (size_t index(0), count(CYCastDouble(context, length)); index != count; ++index) {
-        JSValueRef value(CYGetProperty(context, _this, index));
-
-        if (comma)
-            str << ',';
-        else
-            comma = true;
-
-        if (!JSValueIsUndefined(context, value))
-            str << CYPoolCCYON(pool, context, value);
-        else {
-            str << ',';
-            comma = false;
-        }
-    }
-
-    str << ']';
-
-    std::string value(str.str());
-    return CYCastJSValue(context, CYJSString(CYUTF8String(value.c_str(), value.size())));
-} CYCatch }
-
-JSObjectRef CYMakePointer(JSContextRef context, void *pointer, size_t length, sig::Type *type, ffi_type *ffi, JSObjectRef owner) {
-    Pointer *internal(new Pointer(pointer, context, owner, length, type));
-    return JSObjectMake(context, Pointer_, internal);
-}
-
-static JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), const char *type) {
-    cy::Functor *internal(new cy::Functor(type, function));
-    return JSObjectMake(context, Functor_, internal);
-}
-
-static bool CYGetOffset(apr_pool_t *pool, JSContextRef context, JSStringRef value, ssize_t &index) {
-    return CYGetOffset(CYPoolCString(pool, context, value), index);
-}
-
-void *CYCastPointer_(JSContextRef context, JSValueRef value) {
-    switch (JSValueGetType(context, value)) {
-        case kJSTypeNull:
-            return NULL;
-        /*case kJSTypeObject:
-            if (JSValueIsObjectOfClass(context, value, Pointer_)) {
-                Pointer *internal(reinterpret_cast<Pointer *>(JSObjectGetPrivate((JSObjectRef) value)));
-                return internal->value_;
-            }*/
-        default:
-            double number(CYCastDouble(context, value));
-            if (std::isnan(number))
-                throw CYJSError(context, "cannot convert value to pointer");
-            return reinterpret_cast<void *>(static_cast<uintptr_t>(static_cast<long long>(number)));
-    }
-}
-
-void CYPoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, JSValueRef value) {
-    switch (type->primitive) {
-        case sig::boolean_P:
-            *reinterpret_cast<bool *>(data) = JSValueToBoolean(context, value);
-        break;
-
-#define CYPoolFFI_(primitive, native) \
-        case sig::primitive ## _P: \
-            *reinterpret_cast<native *>(data) = CYCastDouble(context, value); \
-        break;
-
-        CYPoolFFI_(uchar, unsigned char)
-        CYPoolFFI_(char, char)
-        CYPoolFFI_(ushort, unsigned short)
-        CYPoolFFI_(short, short)
-        CYPoolFFI_(ulong, unsigned long)
-        CYPoolFFI_(long, long)
-        CYPoolFFI_(uint, unsigned int)
-        CYPoolFFI_(int, int)
-        CYPoolFFI_(ulonglong, unsigned long long)
-        CYPoolFFI_(longlong, long long)
-        CYPoolFFI_(float, float)
-        CYPoolFFI_(double, double)
-
-        case sig::array_P: {
-            uint8_t *base(reinterpret_cast<uint8_t *>(data));
-            JSObjectRef aggregate(JSValueIsObject(context, value) ? (JSObjectRef) value : NULL);
-            for (size_t index(0); index != type->data.data.size; ++index) {
-                ffi_type *field(ffi->elements[index]);
-
-                JSValueRef rhs;
-                if (aggregate == NULL)
-                    rhs = value;
-                else {
-                    rhs = CYGetProperty(context, aggregate, index);
-                    if (JSValueIsUndefined(context, rhs))
-                        throw CYJSError(context, "unable to extract array value");
-                }
-
-                CYPoolFFI(pool, context, type->data.data.type, field, base, rhs);
-                // XXX: alignment?
-                base += field->size;
-            }
-        } break;
-
-        case sig::pointer_P:
-            *reinterpret_cast<void **>(data) = CYCastPointer<void *>(context, value);
-        break;
-
-        case sig::string_P:
-            *reinterpret_cast<const char **>(data) = CYPoolCString(pool, context, value);
-        break;
-
-        case sig::struct_P: {
-            uint8_t *base(reinterpret_cast<uint8_t *>(data));
-            JSObjectRef aggregate(JSValueIsObject(context, value) ? (JSObjectRef) value : NULL);
-            for (size_t index(0); index != type->data.signature.count; ++index) {
-                sig::Element *element(&type->data.signature.elements[index]);
-                ffi_type *field(ffi->elements[index]);
-
-                JSValueRef rhs;
-                if (aggregate == NULL)
-                    rhs = value;
-                else {
-                    rhs = CYGetProperty(context, aggregate, index);
-                    if (JSValueIsUndefined(context, rhs)) {
-                        if (element->name != NULL)
-                            rhs = CYGetProperty(context, aggregate, CYJSString(element->name));
-                        else
-                            goto undefined;
-                        if (JSValueIsUndefined(context, rhs)) undefined:
-                            throw CYJSError(context, "unable to extract structure value");
-                    }
-                }
-
-                CYPoolFFI(pool, context, element->type, field, base, rhs);
-                // XXX: alignment?
-                base += field->size;
-            }
-        } break;
-
-        case sig::void_P:
-        break;
-
-        default:
-            if (hooks_ != NULL && hooks_->PoolFFI != NULL)
-                if ((*hooks_->PoolFFI)(pool, context, type, ffi, data, value))
-                    return;
-
-            CYThrow("unimplemented signature code: '%c''\n", type->primitive);
-    }
-}
-
-JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) {
-    switch (type->primitive) {
-        case sig::boolean_P:
-            return CYCastJSValue(context, *reinterpret_cast<bool *>(data));
-
-#define CYFromFFI_(primitive, native) \
-        case sig::primitive ## _P: \
-            return CYCastJSValue(context, *reinterpret_cast<native *>(data)); \
-
-        CYFromFFI_(uchar, unsigned char)
-        CYFromFFI_(char, char)
-        CYFromFFI_(ushort, unsigned short)
-        CYFromFFI_(short, short)
-        CYFromFFI_(ulong, unsigned long)
-        CYFromFFI_(long, long)
-        CYFromFFI_(uint, unsigned int)
-        CYFromFFI_(int, int)
-        CYFromFFI_(ulonglong, unsigned long long)
-        CYFromFFI_(longlong, long long)
-        CYFromFFI_(float, float)
-        CYFromFFI_(double, double)
-
-        case sig::array_P:
-            if (void *pointer = data)
-                return CYMakePointer(context, pointer, type->data.data.size, type->data.data.type, NULL, owner);
-            else goto null;
-
-        case sig::pointer_P:
-            if (void *pointer = *reinterpret_cast<void **>(data))
-                return CYMakePointer(context, pointer, _not(size_t), type->data.data.type, NULL, owner);
-            else goto null;
-
-        case sig::string_P:
-            if (char *utf8 = *reinterpret_cast<char **>(data))
-                return CYCastJSValue(context, utf8);
-            else goto null;
-
-        case sig::struct_P:
-            return CYMakeStruct(context, data, type, ffi, owner);
-        case sig::void_P:
-            return CYJSUndefined(context);
-
-        null:
-            return CYJSNull(context);
-        default:
-            if (hooks_ != NULL && hooks_->FromFFI != NULL)
-                if (JSValueRef value = (*hooks_->FromFFI)(context, type, ffi, data, initialize, owner))
-                    return value;
-
-            CYThrow("unimplemented signature code: '%c''\n", type->primitive);
-    }
-}
-
-static void FunctionClosure_(ffi_cif *cif, void *result, void **arguments, void *arg) {
-    Closure_privateData *internal(reinterpret_cast<Closure_privateData *>(arg));
-
-    JSContextRef context(internal->context_);
-
-    size_t count(internal->cif_.nargs);
-    JSValueRef values[count];
-
-    for (size_t index(0); index != count; ++index)
-        values[index] = CYFromFFI(context, internal->signature_.elements[1 + index].type, internal->cif_.arg_types[index], arguments[index]);
-
-    JSValueRef value(CYCallAsFunction(context, internal->function_, NULL, count, values));
-    CYPoolFFI(NULL, context, internal->signature_.elements[0].type, internal->cif_.rtype, result, value);
-}
-
-Closure_privateData *CYMakeFunctor_(JSContextRef context, JSObjectRef function, const char *type, void (*callback)(ffi_cif *, void *, void **, void *)) {
-    // XXX: in case of exceptions this will leak
-    // XXX: in point of fact, this may /need/ to leak :(
-    Closure_privateData *internal(new Closure_privateData(context, function, type));
-
-    ffi_closure *closure((ffi_closure *) _syscall(mmap(
-        NULL, sizeof(ffi_closure),
-        PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,
-        -1, 0
-    )));
-
-    ffi_status status(ffi_prep_closure(closure, &internal->cif_, callback, internal));
-    _assert(status == FFI_OK);
-
-    _syscall(mprotect(closure, sizeof(*closure), PROT_READ | PROT_EXEC));
-
-    internal->value_ = closure;
-
-    return internal;
-}
-
-static JSObjectRef CYMakeFunctor(JSContextRef context, JSObjectRef function, const char *type) {
-    Closure_privateData *internal(CYMakeFunctor_(context, function, type, &FunctionClosure_));
-    JSObjectRef object(JSObjectMake(context, Functor_, internal));
-    // XXX: see above notes about needing to leak
-    JSValueProtect(CYGetJSContext(context), object);
-    return object;
-}
-
-JSObjectRef CYGetCachedObject(JSContextRef context, JSStringRef name) {
-    return CYCastJSObject(context, CYGetProperty(context, CYCastJSObject(context, CYGetProperty(context, CYGetGlobalObject(context), cy_s)), name));
-}
-
-static JSObjectRef CYMakeFunctor(JSContextRef context, JSValueRef value, const char *type) {
-    JSObjectRef Function(CYGetCachedObject(context, CYJSString("Function")));
-
-    JSValueRef exception(NULL);
-    bool function(JSValueIsInstanceOfConstructor(context, value, Function, &exception));
-    CYThrow(context, exception);
-
-    if (function) {
-        JSObjectRef function(CYCastJSObject(context, value));
-        return CYMakeFunctor(context, function, type);
-    } else {
-        void (*function)()(CYCastPointer<void (*)()>(context, value));
-        return CYMakeFunctor(context, function, type);
-    }
-}
-
-static bool Index_(apr_pool_t *pool, JSContextRef context, Struct_privateData *internal, JSStringRef property, ssize_t &index, uint8_t *&base) {
-    Type_privateData *typical(internal->type_);
-    sig::Type *type(typical->type_);
-    if (type == NULL)
-        return false;
-
-    const char *name(CYPoolCString(pool, context, property));
-    size_t length(strlen(name));
-    double number(CYCastDouble(name, length));
-
-    size_t count(type->data.signature.count);
-
-    if (std::isnan(number)) {
-        if (property == NULL)
-            return false;
-
-        sig::Element *elements(type->data.signature.elements);
-
-        for (size_t local(0); local != count; ++local) {
-            sig::Element *element(&elements[local]);
-            if (element->name != NULL && strcmp(name, element->name) == 0) {
-                index = local;
-                goto base;
-            }
-        }
-
-        return false;
-    } else {
-        index = static_cast<ssize_t>(number);
-        if (index != number || index < 0 || static_cast<size_t>(index) >= count)
-            return false;
-    }
-
-  base:
-    ffi_type **elements(typical->GetFFI()->elements);
-
-    base = reinterpret_cast<uint8_t *>(internal->value_);
-    for (ssize_t local(0); local != index; ++local)
-        base += elements[local]->size;
-
-    return true;
-}
-
-static JSValueRef Pointer_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
-    CYPool pool;
-    Pointer *internal(reinterpret_cast<Pointer *>(JSObjectGetPrivate(object)));
-
-    if (JSStringIsEqual(property, length_s))
-        return internal->length_ == _not(size_t) ? CYJSUndefined(context) : CYCastJSValue(context, internal->length_);
-
-    Type_privateData *typical(internal->type_);
-
-    if (typical->type_ == NULL)
-        return NULL;
-
-    ssize_t offset;
-    if (JSStringIsEqualToUTF8CString(property, "$cyi"))
-        offset = 0;
-    else if (!CYGetOffset(pool, context, property, offset))
-        return NULL;
-
-    ffi_type *ffi(typical->GetFFI());
-
-    uint8_t *base(reinterpret_cast<uint8_t *>(internal->value_));
-    base += ffi->size * offset;
-
-    JSObjectRef owner(internal->GetOwner() ?: object);
-    return CYFromFFI(context, typical->type_, ffi, base, false, owner);
-} CYCatch }
-
-static bool Pointer_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry {
-    CYPool pool;
-    Pointer *internal(reinterpret_cast<Pointer *>(JSObjectGetPrivate(object)));
-    Type_privateData *typical(internal->type_);
-
-    if (typical->type_ == NULL)
-        return NULL;
-
-    ssize_t offset;
-    if (JSStringIsEqualToUTF8CString(property, "$cyi"))
-        offset = 0;
-    else if (!CYGetOffset(pool, context, property, offset))
-        return NULL;
-
-    ffi_type *ffi(typical->GetFFI());
-
-    uint8_t *base(reinterpret_cast<uint8_t *>(internal->value_));
-    base += ffi->size * offset;
-
-    CYPoolFFI(NULL, context, typical->type_, ffi, base, value);
-    return true;
-} CYCatch }
-
-static JSValueRef Struct_callAsFunction_$cya(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
-    Struct_privateData *internal(reinterpret_cast<Struct_privateData *>(JSObjectGetPrivate(_this)));
-    Type_privateData *typical(internal->type_);
-    return CYMakePointer(context, internal->value_, _not(size_t), typical->type_, typical->ffi_, _this);
-}
-
-static JSValueRef Struct_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
-    CYPool pool;
-    Struct_privateData *internal(reinterpret_cast<Struct_privateData *>(JSObjectGetPrivate(object)));
-    Type_privateData *typical(internal->type_);
-
-    ssize_t index;
-    uint8_t *base;
-
-    if (!Index_(pool, context, internal, property, index, base))
-        return NULL;
-
-    JSObjectRef owner(internal->GetOwner() ?: object);
-
-    return CYFromFFI(context, typical->type_->data.signature.elements[index].type, typical->GetFFI()->elements[index], base, false, owner);
-} CYCatch }
-
-static bool Struct_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry {
-    CYPool pool;
-    Struct_privateData *internal(reinterpret_cast<Struct_privateData *>(JSObjectGetPrivate(object)));
-    Type_privateData *typical(internal->type_);
-
-    ssize_t index;
-    uint8_t *base;
-
-    if (!Index_(pool, context, internal, property, index, base))
-        return false;
-
-    CYPoolFFI(NULL, context, typical->type_->data.signature.elements[index].type, typical->GetFFI()->elements[index], base, value);
-    return true;
-} CYCatch }
-
-static void Struct_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef names) {
-    Struct_privateData *internal(reinterpret_cast<Struct_privateData *>(JSObjectGetPrivate(object)));
-    Type_privateData *typical(internal->type_);
-    sig::Type *type(typical->type_);
-
-    if (type == NULL)
-        return;
-
-    size_t count(type->data.signature.count);
-    sig::Element *elements(type->data.signature.elements);
-
-    char number[32];
-
-    for (size_t index(0); index != count; ++index) {
-        const char *name;
-        name = elements[index].name;
-
-        if (name == NULL) {
-            sprintf(number, "%zu", index);
-            name = number;
-        }
-
-        JSPropertyNameAccumulatorAddName(names, CYJSString(name));
-    }
-}
-
-JSValueRef CYCallFunction(apr_pool_t *pool, JSContextRef context, size_t setups, void *setup[], size_t count, const JSValueRef arguments[], bool initialize, JSValueRef *exception, sig::Signature *signature, ffi_cif *cif, void (*function)()) { CYTry {
-    if (setups + count != signature->count - 1)
-        throw CYJSError(context, "incorrect number of arguments to ffi function");
-
-    size_t size(setups + count);
-    void *values[size];
-    memcpy(values, setup, sizeof(void *) * setups);
-
-    for (size_t index(setups); index != size; ++index) {
-        sig::Element *element(&signature->elements[index + 1]);
-        ffi_type *ffi(cif->arg_types[index]);
-        // XXX: alignment?
-        values[index] = new(pool) uint8_t[ffi->size];
-        CYPoolFFI(pool, context, element->type, ffi, values[index], arguments[index - setups]);
-    }
-
-    uint8_t value[cif->rtype->size];
-
-    if (hooks_ != NULL && hooks_->CallFunction != NULL)
-        (*hooks_->CallFunction)(context, cif, function, value, values);
-    else
-        ffi_call(cif, function, value, values);
-
-    return CYFromFFI(context, signature->elements[0].type, cif->rtype, value, initialize);
-} CYCatch }
-
-static JSValueRef Functor_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
-    CYPool pool;
-    cy::Functor *internal(reinterpret_cast<cy::Functor *>(JSObjectGetPrivate(object)));
-    return CYCallFunction(pool, context, 0, NULL, count, arguments, false, exception, &internal->signature_, &internal->cif_, internal->GetValue());
-}
-
-static JSObjectRef CYMakeType(JSContextRef context, const char *type) {
-    Type_privateData *internal(new Type_privateData(type));
-    return JSObjectMake(context, Type_privateData::Class_, internal);
-}
-
-static JSObjectRef CYMakeType(JSContextRef context, sig::Type *type) {
-    Type_privateData *internal(new Type_privateData(type));
-    return JSObjectMake(context, Type_privateData::Class_, internal);
-}
-
-static void *CYCastSymbol(const char *name) {
-    return dlsym(RTLD_DEFAULT, name);
-}
-
-static JSValueRef All_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
-    JSObjectRef global(CYGetGlobalObject(context));
-    JSObjectRef cycript(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Cycript"))));
-    if (JSValueRef value = CYGetProperty(context, cycript, property))
-        if (!JSValueIsUndefined(context, value))
-            return value;
-
-    CYPool pool;
-    CYUTF8String name(CYPoolUTF8String(pool, context, property));
-
-    if (hooks_ != NULL && hooks_->RuntimeProperty != NULL)
-        if (JSValueRef value = (*hooks_->RuntimeProperty)(context, name))
-            return value;
-
-    sqlite3_stmt *statement;
-
-    _sqlcall(sqlite3_prepare(Bridge_,
-        "select "
-            "\"bridge\".\"mode\", "
-            "\"bridge\".\"value\" "
-        "from \"bridge\" "
-        "where"
-            " \"bridge\".\"name\" = ?"
-        " limit 1"
-    , -1, &statement, NULL));
-
-    _sqlcall(sqlite3_bind_text(statement, 1, name.data, name.size, SQLITE_STATIC));
-
-    int mode;
-    const char *value;
-
-    if (_sqlcall(sqlite3_step(statement)) == SQLITE_DONE) {
-        mode = -1;
-        value = NULL;
-    } else {
-        mode = sqlite3_column_int(statement, 0);
-        value = sqlite3_column_pooled(pool, statement, 1);
-    }
-
-    _sqlcall(sqlite3_finalize(statement));
-
-    switch (mode) {
-        default:
-            CYThrow("invalid mode from bridge table: %d", mode);
-        case -1:
-            return NULL;
-
-        case 0:
-            return JSEvaluateScript(CYGetJSContext(context), CYJSString(value), NULL, NULL, 0, NULL);
-
-        case 1:
-            if (void (*symbol)() = reinterpret_cast<void (*)()>(CYCastSymbol(name.data)))
-                return CYMakeFunctor(context, symbol, value);
-            else return NULL;
-
-        case 2:
-            if (void *symbol = CYCastSymbol(name.data)) {
-                // XXX: this is horrendously inefficient
-                sig::Signature signature;
-                sig::Parse(pool, &signature, value, &Structor_);
-                ffi_cif cif;
-                sig::sig_ffi_cif(pool, &sig::ObjectiveC, &signature, &cif);
-                return CYFromFFI(context, signature.elements[0].type, cif.rtype, symbol);
-            } else return NULL;
-
-        // XXX: implement case 3
-        case 4:
-            return CYMakeType(context, value);
-    }
-} CYCatch }
-
-static JSObjectRef Pointer_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    if (count != 2)
-        throw CYJSError(context, "incorrect number of arguments to Functor constructor");
-
-    CYPool pool;
-
-    void *value(CYCastPointer<void *>(context, arguments[0]));
-    const char *type(CYPoolCString(pool, context, arguments[1]));
-
-    sig::Signature signature;
-    sig::Parse(pool, &signature, type, &Structor_);
-
-    return CYMakePointer(context, value, _not(size_t), signature.elements[0].type, NULL, NULL);
-} CYCatch }
-
-static JSObjectRef Type_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    if (count != 1)
-        throw CYJSError(context, "incorrect number of arguments to Type constructor");
-    CYPool pool;
-    const char *type(CYPoolCString(pool, context, arguments[0]));
-    return CYMakeType(context, type);
-} CYCatch }
-
-static JSValueRef Type_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
-    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
-
-    sig::Type type;
-
-    if (JSStringIsEqualToUTF8CString(property, "$cyi")) {
-        type.primitive = sig::pointer_P;
-        type.data.data.size = 0;
-    } else {
-        CYPool pool;
-        size_t index(CYGetIndex(pool, context, property));
-        if (index == _not(size_t))
-            return NULL;
-        type.primitive = sig::array_P;
-        type.data.data.size = index;
-    }
-
-    type.name = NULL;
-    type.flags = 0;
-
-    type.data.data.type = internal->type_;
-
-    return CYMakeType(context, &type);
-} CYCatch }
-
-static JSValueRef Type_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
-
-    if (count != 1)
-        throw CYJSError(context, "incorrect number of arguments to type cast function");
-    sig::Type *type(internal->type_);
-    ffi_type *ffi(internal->GetFFI());
-    // XXX: alignment?
-    uint8_t value[ffi->size];
-    CYPool pool;
-    CYPoolFFI(pool, context, type, ffi, value, arguments[0]);
-    return CYFromFFI(context, type, ffi, value);
-} CYCatch }
-
-static JSObjectRef Type_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    if (count != 0)
-        throw CYJSError(context, "incorrect number of arguments to type cast function");
-    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
-
-    sig::Type *type(internal->type_);
-    size_t length;
-
-    if (type->primitive != sig::array_P)
-        length = _not(size_t);
-    else {
-        length = type->data.data.size;
-        type = type->data.data.type;
-    }
-
-    void *value(malloc(internal->GetFFI()->size));
-    return CYMakePointer(context, value, length, type, NULL, NULL);
-} CYCatch }
-
-static JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    if (count != 2)
-        throw CYJSError(context, "incorrect number of arguments to Functor constructor");
-    CYPool pool;
-    const char *type(CYPoolCString(pool, context, arguments[1]));
-    return CYMakeFunctor(context, arguments[0], type);
-} CYCatch }
-
-static JSValueRef CYValue_callAsFunction_valueOf(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    CYValue *internal(reinterpret_cast<CYValue *>(JSObjectGetPrivate(_this)));
-    return CYCastJSValue(context, reinterpret_cast<uintptr_t>(internal->value_));
-} CYCatch }
-
-static JSValueRef CYValue_callAsFunction_toJSON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
-    return CYValue_callAsFunction_valueOf(context, object, _this, count, arguments, exception);
-}
-
-static JSValueRef CYValue_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    CYValue *internal(reinterpret_cast<CYValue *>(JSObjectGetPrivate(_this)));
-    char string[32];
-    sprintf(string, "%p", internal->value_);
-    return CYCastJSValue(context, string);
-} CYCatch }
-
-static JSValueRef Pointer_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    Pointer *internal(reinterpret_cast<Pointer *>(JSObjectGetPrivate(_this)));
-    if (internal->length_ != _not(size_t)) {
-        JSObjectRef Array(CYGetCachedObject(context, Array_s));
-        JSObjectRef toCYON(CYCastJSObject(context, CYGetProperty(context, Array, toCYON_s)));
-        return CYCallAsFunction(context, toCYON, _this, count, arguments);
-    } else {
-        char string[32];
-        sprintf(string, "%p", internal->value_);
-        return CYCastJSValue(context, string);
-    }
-} CYCatch }
-
-static JSValueRef Type_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
-    CYPool pool;
-    const char *type(sig::Unparse(pool, internal->type_));
-    return CYCastJSValue(context, CYJSString(type));
-} CYCatch }
-
-static JSValueRef Type_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
-    CYPool pool;
-    const char *type(sig::Unparse(pool, internal->type_));
-    size_t size(strlen(type));
-    char *cyon(new(pool) char[12 + size + 1]);
-    memcpy(cyon, "new Type(\"", 10);
-    cyon[12 + size] = '\0';
-    cyon[12 + size - 2] = '"';
-    cyon[12 + size - 1] = ')';
-    memcpy(cyon + 10, type, size);
-    return CYCastJSValue(context, CYJSString(cyon));
-} CYCatch }
-
-static JSValueRef Type_callAsFunction_toJSON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
-    return Type_callAsFunction_toString(context, object, _this, count, arguments, exception);
-}
-
-static JSStaticFunction Pointer_staticFunctions[4] = {
-    {"toCYON", &Pointer_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
-    {"toJSON", &CYValue_callAsFunction_toJSON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
-    {"valueOf", &CYValue_callAsFunction_valueOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
-    {NULL, NULL, 0}
-};
-
-static JSStaticFunction Struct_staticFunctions[2] = {
-    {"$cya", &Struct_callAsFunction_$cya, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
-    {NULL, NULL, 0}
-};
-
-static JSStaticFunction Functor_staticFunctions[4] = {
-    {"toCYON", &CYValue_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
-    {"toJSON", &CYValue_callAsFunction_toJSON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
-    {"valueOf", &CYValue_callAsFunction_valueOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
-    {NULL, NULL, 0}
-};
-
-namespace cy {
-    JSStaticFunction const * const Functor::StaticFunctions = Functor_staticFunctions;
-}
-
-static JSStaticFunction Type_staticFunctions[4] = {
-    {"toCYON", &Type_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
-    {"toJSON", &Type_callAsFunction_toJSON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
-    {"toString", &Type_callAsFunction_toString, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
-    {NULL, NULL, 0}
-};
-
-static JSObjectRef (*JSObjectMakeArray$)(JSContextRef, size_t, const JSValueRef[], JSValueRef *);
-
-void CYSetArgs(int argc, const char *argv[]) {
-    JSContextRef context(CYGetJSContext());
-    JSValueRef args[argc];
-    for (int i(0); i != argc; ++i)
-        args[i] = CYCastJSValue(context, argv[i]);
-
-    JSObjectRef array;
-    if (JSObjectMakeArray$ != NULL) {
-        JSValueRef exception(NULL);
-        array = (*JSObjectMakeArray$)(context, argc, args, &exception);
-        CYThrow(context, exception);
-    } else {
-        JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array")));
-        JSValueRef value(CYCallAsFunction(context, Array, NULL, argc, args));
-        array = CYCastJSObject(context, value);
-    }
-
-    JSObjectRef System(CYGetCachedObject(context, CYJSString("System")));
-    CYSetProperty(context, System, CYJSString("args"), array);
-}
-
-JSObjectRef CYGetGlobalObject(JSContextRef context) {
-    return JSContextGetGlobalObject(context);
-}
-
-const char *CYExecute(apr_pool_t *pool, const char *code) {
-    JSContextRef context(CYGetJSContext());
-    JSValueRef exception(NULL), result;
-
-    void *handle;
-    if (hooks_ != NULL && hooks_->ExecuteStart != NULL)
-        handle = (*hooks_->ExecuteStart)(context);
-    else
-        handle = NULL;
-
-    const char *json;
-
-    try {
-        result = JSEvaluateScript(context, CYJSString(code), NULL, NULL, 0, &exception);
-    } catch (const char *error) {
-        return error;
-    }
-
-    if (exception != NULL) { error:
-        result = exception;
-        exception = NULL;
-    }
-
-    if (JSValueIsUndefined(context, result))
-        return NULL;
-
-    try {
-        json = CYPoolCCYON(pool, context, result, &exception);
-    } catch (const char *error) {
-        return error;
-    }
-
-    if (exception != NULL)
-        goto error;
-
-    CYSetProperty(context, CYGetGlobalObject(context), Result_, result);
-
-    if (hooks_ != NULL && hooks_->ExecuteEnd != NULL)
-        (*hooks_->ExecuteEnd)(context, handle);
-    return json;
-}
-
-extern "C" void CydgetSetupContext(JSGlobalContextRef context) {
-    CYSetupContext(context);
-}
-
 extern "C" void CydgetPoolParse(apr_pool_t *pool, const uint16_t **data, size_t *size) {
     CYDriver driver("");
     cy::parser parser(driver);
@@ -1497,104 +268,20 @@ static apr_pool_t *Pool_;
 
 static bool initialized_;
 
-void CYInitialize() {
+void CYInitializeStatic() {
     if (!initialized_)
         initialized_ = true;
     else return;
 
     _aprcall(apr_initialize());
     _aprcall(apr_pool_create(&Pool_, NULL));
-    _sqlcall(sqlite3_open("/usr/lib/libcycript.db", &Bridge_));
-
-    JSObjectMakeArray$ = reinterpret_cast<JSObjectRef (*)(JSContextRef, size_t, const JSValueRef[], JSValueRef *)>(dlsym(RTLD_DEFAULT, "JSObjectMakeArray"));
-
-    JSClassDefinition definition;
-
-    definition = kJSClassDefinitionEmpty;
-    definition.className = "All";
-    definition.getProperty = &All_getProperty;
-    All_ = JSClassCreate(&definition);
-
-    definition = kJSClassDefinitionEmpty;
-    definition.className = "Context";
-    definition.finalize = &CYFinalize;
-    Context_ = JSClassCreate(&definition);
-
-    definition = kJSClassDefinitionEmpty;
-    definition.className = "Functor";
-    definition.staticFunctions = cy::Functor::StaticFunctions;
-    definition.callAsFunction = &Functor_callAsFunction;
-    definition.finalize = &CYFinalize;
-    Functor_ = JSClassCreate(&definition);
-
-    definition = kJSClassDefinitionEmpty;
-    definition.className = "Pointer";
-    definition.staticFunctions = Pointer_staticFunctions;
-    definition.getProperty = &Pointer_getProperty;
-    definition.setProperty = &Pointer_setProperty;
-    definition.finalize = &CYFinalize;
-    Pointer_ = JSClassCreate(&definition);
-
-    definition = kJSClassDefinitionEmpty;
-    definition.className = "Struct";
-    definition.staticFunctions = Struct_staticFunctions;
-    definition.getProperty = &Struct_getProperty;
-    definition.setProperty = &Struct_setProperty;
-    definition.getPropertyNames = &Struct_getPropertyNames;
-    definition.finalize = &CYFinalize;
-    Struct_ = JSClassCreate(&definition);
-
-    definition = kJSClassDefinitionEmpty;
-    definition.className = "Type";
-    definition.staticFunctions = Type_staticFunctions;
-    definition.getProperty = &Type_getProperty;
-    definition.callAsFunction = &Type_callAsFunction;
-    definition.callAsConstructor = &Type_callAsConstructor;
-    definition.finalize = &CYFinalize;
-    Type_privateData::Class_ = JSClassCreate(&definition);
-
-    definition = kJSClassDefinitionEmpty;
-    //definition.getProperty = &Global_getProperty;
-    Global_ = JSClassCreate(&definition);
-
-    Array_s = JSStringCreateWithUTF8CString("Array");
-    cy_s = JSStringCreateWithUTF8CString("$cy");
-    length_s = JSStringCreateWithUTF8CString("length");
-    message_s = JSStringCreateWithUTF8CString("message");
-    name_s = JSStringCreateWithUTF8CString("name");
-    pop_s = JSStringCreateWithUTF8CString("pop");
-    prototype_s = JSStringCreateWithUTF8CString("prototype");
-    push_s = JSStringCreateWithUTF8CString("push");
-    splice_s = JSStringCreateWithUTF8CString("splice");
-    toCYON_s = JSStringCreateWithUTF8CString("toCYON");
-    toJSON_s = JSStringCreateWithUTF8CString("toJSON");
-
-    Result_ = JSStringCreateWithUTF8CString("_");
-
-    if (hooks_ != NULL && hooks_->Initialize != NULL)
-        (*hooks_->Initialize)();
 }
 
 apr_pool_t *CYGetGlobalPool() {
-    CYInitialize();
+    CYInitializeStatic();
     return Pool_;
 }
 
-void CYThrow(JSContextRef context, JSValueRef value) {
-    if (value != NULL)
-        throw CYJSError(context, value);
-}
-
-const char *CYJSError::PoolCString(apr_pool_t *pool) const {
-    // XXX: this used to be CYPoolCString
-    return CYPoolCCYON(pool, context_, value_);
-}
-
-JSValueRef CYJSError::CastJSValue(JSContextRef context) const {
-    // XXX: what if the context is different?
-    return value_;
-}
-
 void CYThrow(const char *format, ...) {
     va_list args;
     va_start(args, format);
@@ -1617,126 +304,3 @@ CYPoolError::CYPoolError(const char *format, ...) {
 CYPoolError::CYPoolError(const char *format, va_list args) {
     message_ = apr_pvsprintf(pool_, format, args);
 }
-
-JSValueRef CYCastJSError(JSContextRef context, const char *message) {
-    JSObjectRef Error(CYGetCachedObject(context, CYJSString("Error")));
-
-    JSValueRef arguments[1] = {CYCastJSValue(context, message)};
-
-    JSValueRef exception(NULL);
-    JSValueRef value(JSObjectCallAsConstructor(context, Error, 1, arguments, &exception));
-    CYThrow(context, exception);
-
-    return value;
-}
-
-JSValueRef CYPoolError::CastJSValue(JSContextRef context) const {
-    return CYCastJSError(context, message_);
-}
-
-CYJSError::CYJSError(JSContextRef context, const char *format, ...) {
-    _assert(context != NULL);
-
-    CYPool pool;
-
-    va_list args;
-    va_start(args, format);
-    const char *message(apr_pvsprintf(pool, format, args));
-    va_end(args);
-
-    value_ = CYCastJSError(context, message);
-}
-
-JSGlobalContextRef CYGetJSContext(JSContextRef context) {
-    return reinterpret_cast<Context *>(JSObjectGetPrivate(CYCastJSObject(context, CYGetProperty(context, CYGetGlobalObject(context), cy_s))))->context_;
-}
-
-extern "C" void CYSetupContext(JSGlobalContextRef context) {
-    CYInitialize();
-
-    JSObjectRef global(CYGetGlobalObject(context));
-
-    JSObjectRef cy(JSObjectMake(context, Context_, new Context(context)));
-    CYSetProperty(context, global, cy_s, cy, kJSPropertyAttributeDontEnum);
-
-/* Cache Globals {{{ */
-    JSObjectRef Array(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Array"))));
-    CYSetProperty(context, cy, CYJSString("Array"), Array);
-
-    JSObjectRef Array_prototype(CYCastJSObject(context, CYGetProperty(context, Array, prototype_s)));
-    CYSetProperty(context, cy, CYJSString("Array_prototype"), Array_prototype);
-
-    JSObjectRef Error(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Error"))));
-    CYSetProperty(context, cy, CYJSString("Error"), Error);
-
-    JSObjectRef Function(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Function"))));
-    CYSetProperty(context, cy, CYJSString("Function"), Function);
-
-    JSObjectRef Function_prototype(CYCastJSObject(context, CYGetProperty(context, Function, prototype_s)));
-    CYSetProperty(context, cy, CYJSString("Function_prototype"), Function_prototype);
-
-    JSObjectRef Object(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Object"))));
-    CYSetProperty(context, cy, CYJSString("Object"), Object);
-
-    JSObjectRef Object_prototype(CYCastJSObject(context, CYGetProperty(context, Object, prototype_s)));
-    CYSetProperty(context, cy, CYJSString("Object_prototype"), Object_prototype);
-
-    JSObjectRef String(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("String"))));
-    CYSetProperty(context, cy, CYJSString("String"), String);
-/* }}} */
-
-    CYSetProperty(context, Array_prototype, toCYON_s, &Array_callAsFunction_toCYON, kJSPropertyAttributeDontEnum);
-
-    JSObjectRef cycript(JSObjectMake(context, NULL, NULL));
-    CYSetProperty(context, global, CYJSString("Cycript"), cycript);
-    CYSetProperty(context, cycript, CYJSString("gc"), &Cycript_gc_callAsFunction);
-
-    JSObjectRef Functor(JSObjectMakeConstructor(context, Functor_, &Functor_new));
-    JSObjectSetPrototype(context, CYCastJSObject(context, CYGetProperty(context, Functor, prototype_s)), Function_prototype);
-    CYSetProperty(context, cycript, CYJSString("Functor"), Functor);
-
-    CYSetProperty(context, cycript, CYJSString("Pointer"), JSObjectMakeConstructor(context, Pointer_, &Pointer_new));
-    CYSetProperty(context, cycript, CYJSString("Type"), JSObjectMakeConstructor(context, Type_privateData::Class_, &Type_new));
-
-    JSObjectRef all(JSObjectMake(context, All_, NULL));
-    CYSetProperty(context, cycript, CYJSString("all"), all);
-
-    JSObjectRef last(NULL), curr(global);
-
-    goto next; for (JSValueRef next;;) {
-        if (JSValueIsNull(context, next))
-            break;
-        last = curr;
-        curr = CYCastJSObject(context, next);
-      next:
-        next = JSObjectGetPrototype(context, curr);
-    }
-
-    JSObjectSetPrototype(context, last, all);
-
-    CYSetProperty(context, global, CYJSString("$cyq"), &$cyq);
-
-    JSObjectRef System(JSObjectMake(context, NULL, NULL));
-    CYSetProperty(context, cy, CYJSString("System"), Function);
-
-    CYSetProperty(context, global, CYJSString("system"), System);
-    CYSetProperty(context, System, CYJSString("args"), CYJSNull(context));
-    //CYSetProperty(context, System, CYJSString("global"), global);
-    CYSetProperty(context, System, CYJSString("print"), &System_print);
-
-    if (hooks_ != NULL && hooks_->SetupContext != NULL)
-        (*hooks_->SetupContext)(context);
-}
-
-JSGlobalContextRef CYGetJSContext() {
-    CYInitialize();
-
-    static JSGlobalContextRef context_;
-
-    if (context_ == NULL) {
-        context_ = JSGlobalContextCreate(Global_);
-        CYSetupContext(context_);
-    }
-
-    return context_;
-}
index 8d23656819128c9d510a14fb1466d2ecd64c1dc5..80fe9393534fc96753db53383d633ece3db3d4a2 100644 (file)
--- a/Linux.mk
+++ b/Linux.mk
@@ -1,4 +1,13 @@
 export PATH := /usr/local/bin:$(PATH)
-flags += -I/usr/include/webkit-1.0
-flags += -DCY_EXECUTE
+
+ifneq ($(shell pkg-config webkit-1.0 --modversion 2>/dev/null),)
+flags += $(shell pkg-config --cflags webkit-1.0)
 library += -lwebkit-1.0
+include Execute.mk
+else
+ifneq ($(shell pkg-config WebKitGtk --modversion 2>/dev/null),)
+flags += $(shell pkg-config --cflags WebKitGtk)
+library += $(shell pkg-config --libs WebKitGtk)
+include Execute.mk
+endif
+endif
index c912882a671ef90f4e427db5c1aa264b4be93c86..754cdbc8446d3207c08a96f55c798bb6637e12aa 100644 (file)
@@ -41,6 +41,7 @@
 #define CYCRIPT_STRING_HPP
 
 #include "cycript.hpp"
+#include "Pooling.hpp"
 
 struct CYUTF8String {
     const char *data;
@@ -69,62 +70,11 @@ struct CYUTF16String {
     }
 };
 
-JSStringRef CYCopyJSString(const char *value);
-JSStringRef CYCopyJSString(JSStringRef value);
-JSStringRef CYCopyJSString(CYUTF8String value);
-JSStringRef CYCopyJSString(JSContextRef context, JSValueRef value);
-
-class CYJSString {
-  private:
-    JSStringRef string_;
-
-    void Clear_() {
-        if (string_ != NULL)
-            JSStringRelease(string_);
-    }
-
-  public:
-    CYJSString(const CYJSString &rhs) :
-        string_(CYCopyJSString(rhs.string_))
-    {
-    }
-
-    template <typename Arg0_>
-    CYJSString(Arg0_ arg0) :
-        string_(CYCopyJSString(arg0))
-    {
-    }
-
-    template <typename Arg0_, typename Arg1_>
-    CYJSString(Arg0_ arg0, Arg1_ arg1) :
-        string_(CYCopyJSString(arg0, arg1))
-    {
-    }
-
-    CYJSString &operator =(const CYJSString &rhs) {
-        Clear_();
-        string_ = CYCopyJSString(rhs.string_);
-        return *this;
-    }
-
-    ~CYJSString() {
-        Clear_();
-    }
-
-    void Clear() {
-        Clear_();
-        string_ = NULL;
-    }
-
-    operator JSStringRef() const {
-        return string_;
-    }
-};
-
 size_t CYGetIndex(const CYUTF8String &value);
 bool CYIsKey(CYUTF8String value);
 bool CYGetOffset(const char *value, ssize_t &index);
 
-const char *CYPoolCString(apr_pool_t *pool, JSContextRef context, JSValueRef value);
+CYUTF8String CYPoolUTF8String(apr_pool_t *pool, CYUTF16String utf16);
+CYUTF16String CYPoolUTF16String(apr_pool_t *pool, CYUTF8String utf8);
 
 #endif/*CYCRIPT_STRING_HPP*/
index f73a7e823b209982a8a64035e95f59337d0fa616..3f4b1c7b0302d79261c85b6aa94d833ace3e8801 100644 (file)
 #ifndef CYCRIPT_HPP
 #define CYCRIPT_HPP
 
-#ifdef __APPLE__
-#include <JavaScriptCore/JavaScriptCore.h>
-#else
-#include <JavaScriptCore/JavaScript.h>
-#endif
-
 #include <apr_pools.h>
-#include <ffi.h>
 #include <sig/types.hpp>
 #include <sstream>
 
 #include "String.hpp"
 
-#include <sqlite3.h>
-
-void CYInitialize();
+void CYInitializeStatic();
 
 bool CYRecvAll_(int socket, uint8_t *data, size_t size);
 bool CYSendAll_(int socket, const uint8_t *data, size_t size);
@@ -63,6 +54,9 @@ bool CYSendAll_(int socket, const uint8_t *data, size_t size);
 void CYNumerify(std::ostringstream &str, double value);
 void CYStringify(std::ostringstream &str, const char *data, size_t size);
 
+double CYCastDouble(const char *value, size_t size);
+double CYCastDouble(const char *value);
+
 extern "C" void CYHandleClient(apr_pool_t *pool, int socket);
 
 template <typename Type_>
@@ -75,83 +69,6 @@ bool CYSendAll(int socket, const Type_ *data, size_t size) {
     return CYSendAll_(socket, reinterpret_cast<const uint8_t *>(data), size);
 }
 
-JSGlobalContextRef CYGetJSContext();
 apr_pool_t *CYGetGlobalPool();
-JSObjectRef CYGetGlobalObject(JSContextRef context);
-
-extern "C" void CYSetupContext(JSGlobalContextRef context);
-const char *CYExecute(apr_pool_t *pool, const char *code);
-
-void CYSetArgs(int argc, const char *argv[]);
-
-bool CYCastBool(JSContextRef context, JSValueRef value);
-double CYCastDouble(JSContextRef context, JSValueRef value);
-
-CYUTF8String CYPoolUTF8String(apr_pool_t *pool, JSContextRef context, JSStringRef value);
-const char *CYPoolCString(apr_pool_t *pool, JSContextRef context, JSStringRef value);
-
-JSValueRef CYGetProperty(JSContextRef context, JSObjectRef object, size_t index);
-JSValueRef CYGetProperty(JSContextRef context, JSObjectRef object, JSStringRef name);
-
-void CYSetProperty(JSContextRef context, JSObjectRef object, size_t index, JSValueRef value);
-void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef value, JSPropertyAttributes attributes = kJSPropertyAttributeNone);
-void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef (*callback)(JSContextRef, JSObjectRef, JSObjectRef, size_t, const JSValueRef[], JSValueRef *), JSPropertyAttributes attributes = kJSPropertyAttributeNone);
-
-JSObjectRef CYGetCachedObject(JSContextRef context, JSStringRef name);
-
-JSValueRef CYCastJSValue(JSContextRef context, bool value);
-JSValueRef CYCastJSValue(JSContextRef context, double value);
-JSValueRef CYCastJSValue(JSContextRef context, int value);
-JSValueRef CYCastJSValue(JSContextRef context, unsigned int value);
-JSValueRef CYCastJSValue(JSContextRef context, long int value);
-JSValueRef CYCastJSValue(JSContextRef context, long unsigned int value);
-JSValueRef CYCastJSValue(JSContextRef context, long long int value);
-JSValueRef CYCastJSValue(JSContextRef context, long long unsigned int value);
-
-JSValueRef CYCastJSValue(JSContextRef context, JSStringRef value);
-JSValueRef CYCastJSValue(JSContextRef context, const char *value);
-
-JSObjectRef CYCastJSObject(JSContextRef context, JSValueRef value);
-JSValueRef CYJSUndefined(JSContextRef context);
-JSValueRef CYJSNull(JSContextRef context);
-
-void *CYCastPointer_(JSContextRef context, JSValueRef value);
-
-template <typename Type_>
-_finline Type_ CYCastPointer(JSContextRef context, JSValueRef value) {
-    return reinterpret_cast<Type_>(CYCastPointer_(context, value));
-}
-
-void CYPoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, JSValueRef value);
-JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, bool initialize = false, JSObjectRef owner = NULL);
-
-JSValueRef CYCallFunction(apr_pool_t *pool, JSContextRef context, size_t setups, void *setup[], size_t count, const JSValueRef arguments[], bool initialize, JSValueRef *exception, sig::Signature *signature, ffi_cif *cif, void (*function)());
-
-bool CYIsCallable(JSContextRef context, JSValueRef value);
-JSValueRef CYCallAsFunction(JSContextRef context, JSObjectRef function, JSObjectRef _this, size_t count, const JSValueRef arguments[]);
-
-const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSObjectRef object);
-
-struct CYHooks {
-    void *(*ExecuteStart)(JSContextRef);
-    void (*ExecuteEnd)(JSContextRef, void *);
-
-    JSValueRef (*RuntimeProperty)(JSContextRef, CYUTF8String);
-    void (*CallFunction)(JSContextRef, ffi_cif *, void (*)(), uint8_t *, void **);
-
-    void (*Initialize)();
-    void (*SetupContext)(JSContextRef);
-
-    bool (*PoolFFI)(apr_pool_t *, JSContextRef, sig::Type *, ffi_type *, void *, JSValueRef);
-    JSValueRef (*FromFFI)(JSContextRef, sig::Type *, ffi_type *, void *, bool, JSObjectRef);
-};
-
-extern struct CYHooks *hooks_;
-
-char *sqlite3_column_pooled(apr_pool_t *pool, sqlite3_stmt *stmt, int n);
-
-JSObjectRef CYMakePointer(JSContextRef context, void *pointer, size_t length, sig::Type *type, ffi_type *ffi, JSObjectRef owner);
-
-void CYFinalize(JSObjectRef object);
 
 #endif/*CYCRIPT_HPP*/
index 486c4481c26892e0cfa1cf8127342fe831df5891..8ea1d3da2c834e18521b92e089a92753e89042b0 100644 (file)
--- a/makefile
+++ b/makefile
@@ -15,7 +15,7 @@ objc :=
 svn := $(shell svnversion)
 
 all:
-all := libcycript.db cycript
+all := cycript
 
 dpkg_architecture := $(shell which dpkg-architecture 2>/dev/null)
 ifneq ($(dpkg_architecture),)
@@ -23,7 +23,8 @@ arch := $(shell $(dpkg_architecture) -qDEB_HOST_ARCH 2>/dev/null)
 endif
 
 header := Cycript.tab.hh Parser.hpp Pooling.hpp cycript.hpp Internal.hpp Error.hpp String.hpp Exception.hpp Standard.hpp
-code := sig/ffi_type.o sig/parse.o sig/copy.o
+
+code := 
 code += Replace.o Output.o
 code += Cycript.tab.o lex.cy.o
 code += Network.o Parser.o
@@ -31,12 +32,12 @@ code += JavaScriptCore.o Library.o
 
 inject := 
 
-filters := #E4X
+filters := #E4X
 ldid := true
 entitle := $(ldid)
 dll := so
 apr := -lapr-1
-library := $(apr) -lffi -lsqlite3
+library := 
 console := $(apr) -lreadline
 depends :=
 
@@ -47,11 +48,13 @@ uname_p ?= $(shell uname -p)
 -include $(uname_s).mk
 -include $(uname_s)-$(uname_p).mk
 
+ifdef CY_EXECUTE
 ifeq ($(filter ObjectiveC,$(filters)),)
 ifneq ($(shell which gnustep-config 2>/dev/null),)
 include GNUstep.mk
 endif
 endif
+endif
 
 flags += -Wall -Werror -Wno-parentheses #-Wno-unused
 flags += -fPIC -fno-common
@@ -64,7 +67,7 @@ deb := $(shell grep ^Package: control.in | cut -d ' ' -f 2-)_$(shell grep ^Versi
 
 all: $(deb)
 
-extra:
+extra::
 
 ifeq ($(depends)$(dll),dylib)
 control: control.in cycript libcycript.dylib
@@ -83,28 +86,18 @@ $(deb): $(all) control
        rm -rf package
        mkdir -p package/DEBIAN
        cp -pR control package/DEBIAN
-       $(restart) extra
        mkdir -p package/usr/{bin,lib,sbin}
+       $(restart) extra
        cp -pR libcycript.$(dll) package/usr/lib
        cp -pR cycript package/usr/bin
        #cp -pR cyrver package/usr/sbin
-       cp -pR libcycript.db package/usr/lib
        dpkg-deb -b package $(deb)
 endif
 
 all: $(all)
 
 clean:
-       rm -f *.o libcycript.$(dll) cycript libcycript.db Struct.hpp lex.cy.c Cycript.tab.cc Cycript.tab.hh location.hh position.hh stack.hh cyrver Cycript.y Cycript.l control
-
-libcycript.db: Bridge.def
-       rm -f libcycript.db
-       { \
-           echo 'create table "bridge" ("mode" int not null, "name" text not null, "value" text null);'; \
-           grep '^[CFV]' Bridge.def | sed -e 's/^C/0/;s/^F/1/;s/^V/2/' | sed -e 's/"/\\"/g;s/^\([^ ]*\) \([^ ]*\) \(.*\)$$/insert into "bridge" ("mode", "name", "value") values (\1, '"'"'\2'"'"', '"'"'\3'"'"');/'; \
-           grep '^:' Bridge.def | sed -e 's/^: \([^ ]*\) \(.*\)/insert into "bridge" ("mode", "name", "value") values (-1, '"'"'\1'"'"', '"'"'\2'"'"');/'; \
-           grep '^[EST]' Bridge.def | sed -e 's/^S/3/;s/^T/4/;s/^E/5/' | sed -e 's/^5\(.*\)$$/4\1 i/' | sed -e 's/^\([^ ]*\) \([^ ]*\) \(.*\)$$/insert into "bridge" ("mode", "name", "value") values (\1, '"'"'\2'"'"', '"'"'\3'"'"');/'; \
-       } | tee libcycript.sql | sqlite3 libcycript.db
+       rm -f *.o libcycript.$(dll) $(all) Struct.hpp lex.cy.c Cycript.tab.cc Cycript.tab.hh location.hh position.hh stack.hh cyrver Cycript.y Cycript.l control
 
 %.y: %.y.in
        ./Filter.sh <$< >$@ $(filters)