diff --git a/jscompile.c b/jscompile.c index e59d1aa..233f725 100644 --- a/jscompile.c +++ b/jscompile.c @@ -1109,6 +1109,11 @@ static void cfunbody(JF, js_Ast *name, js_Ast *params, js_Ast *body) } } +js_Function *jsC_compilefunction(js_State *J, js_Ast *prog) +{ + return newfun(J, prog->a, prog->b, prog->c, 0); +} + js_Function *jsC_compile(js_State *J, js_Ast *prog) { return newfun(J, NULL, NULL, prog, 1); diff --git a/jscompile.h b/jscompile.h index e36715e..9210d27 100644 --- a/jscompile.h +++ b/jscompile.h @@ -138,6 +138,7 @@ struct js_Function int gcmark; }; +js_Function *jsC_compilefunction(js_State *J, js_Ast *prog); js_Function *jsC_compile(js_State *J, js_Ast *prog); const char *jsC_opcodestring(int opcode); void jsC_dumpfunction(js_State *J, js_Function *fun); diff --git a/jsfunction.c b/jsfunction.c index bb8f4b9..c1c0bf4 100644 --- a/jsfunction.c +++ b/jsfunction.c @@ -1,11 +1,46 @@ #include "jsi.h" +#include "jsparse.h" #include "jscompile.h" #include "jsvalue.h" #include "jsbuiltin.h" static int jsB_Function(js_State *J, int argc) { - return 0; + const char *source; + struct sbuffer *sb; + js_Ast *parse; + js_Function *fun; + int i; + + if (argc == 0) + source = ""; + else { + source = js_tostring(J, argc); + sb = NULL; + if (argc > 1) { + for (i = 1; i < argc; ++i) { + if (i > 1) sb = sb_putc(sb, ','); + sb = sb_puts(sb, js_tostring(J, i)); + } + sb = sb_putc(sb, ')'); + } + } + + if (js_try(J)) { + free(sb); + jsP_freeparse(J); + js_throw(J); + } + + parse = jsP_parsefunction(J, "Function", sb->s, source); + fun = jsC_compilefunction(J, parse); + + js_endtry(J); + free(sb); + jsP_freeparse(J); + + js_newfunction(J, fun, J->GE); + return 1; } static int jsB_Function_prototype(js_State *J, int argc) diff --git a/jsi.h b/jsi.h index 428a73b..7e93786 100644 --- a/jsi.h +++ b/jsi.h @@ -116,6 +116,7 @@ struct js_State js_Object *R; /* registry of hidden values */ js_Object *G; /* the global object */ js_Environment *E; /* current environment scope */ + js_Environment *GE; /* global environment scope (at the root) */ /* execution stack */ int top, bot; diff --git a/jsparse.c b/jsparse.c index 1557497..450f3d8 100644 --- a/jsparse.c +++ b/jsparse.c @@ -967,3 +967,14 @@ js_Ast *jsP_parse(js_State *J, const char *filename, const char *source) return p; } + +js_Ast *jsP_parsefunction(js_State *J, const char *filename, const char *params, const char *body) +{ + js_Ast *p = NULL; + if (params) { + jsY_initlex(J, filename, params); + next(J); + p = parameters(J); + } + return EXP3(FUN, NULL, p, jsP_parse(J, filename, body)); +} diff --git a/jsparse.h b/jsparse.h index 290fc28..9f39e7a 100644 --- a/jsparse.h +++ b/jsparse.h @@ -136,6 +136,7 @@ struct js_Ast js_Ast *gcnext; /* next in alloc list */ }; +js_Ast *jsP_parsefunction(js_State *J, const char *filename, const char *params, const char *body); js_Ast *jsP_parse(js_State *J, const char *filename, const char *source); void jsP_freeparse(js_State *J); diff --git a/jsstate.c b/jsstate.c index 9ff6658..c4b311a 100644 --- a/jsstate.c +++ b/jsstate.c @@ -114,6 +114,7 @@ js_State *js_newstate(void) J->R = jsV_newobject(J, JS_COBJECT, NULL); J->G = jsV_newobject(J, JS_COBJECT, NULL); J->E = jsR_newenvironment(J, J->G, NULL); + J->GE = J->E; jsB_init(J);