ref: d8576fe02cf8abda964603386fd2f6fae9c787c0
parent: 52f78c568760d8157e0f4dd780f7ffe6c521bc65
author: Tor Andersson <[email protected]>
date: Sun Jan 12 11:25:22 EST 2014
Create var bindings for self function and function declarations.
--- a/jscompile.c
+++ b/jscompile.c
@@ -181,6 +181,10 @@
cexp(J, F, exp->a);
emitname(J, F, OP_AMEMBER, exp->b->string);
break;
+ case EXP_CALL:
+ /* host functions may return an assignable l-value */
+ cexp(J, F, exp);
+ break;
default:
jsC_error(J, exp, "invalid l-value in assignment");
break;
@@ -256,7 +260,7 @@
break;
case EXP_FUNC:
- emitfunction(J, F, OP_FUNEXP, newfun(J, exp->a, exp->b, exp->c));
+ emitfunction(J, F, OP_CLOSURE, newfun(J, exp->a, exp->b, exp->c));
break;
case EXP_DELETE:
@@ -385,7 +389,6 @@
switch (stm->type) {
case STM_FUNC:
- emitfunction(J, F, OP_FUNDEC, newfun(J, stm->a, stm->b, stm->c));
break;
case STM_BLOCK:
@@ -459,6 +462,34 @@
}
}
+static void cfundecs(JF, js_Ast *list)
+{
+ while (list) {
+ js_Ast *stm = list->a;
+ if (stm->type == STM_FUNC) {
+ emitfunction(J, F, OP_CLOSURE, newfun(J, stm->a, stm->b, stm->c));
+ emitname(J, F, OP_VARDEC, stm->a->string);
+ }
+ list = list->b;
+ }
+}
+
+static void cfunbody(JF, js_Ast *name, js_Ast *params, js_Ast *body)
+{
+ if (name) {
+ emitfunction(J, F, OP_CLOSURE, F);
+ emitname(J, F, OP_VARDEC, name->string);
+ }
+
+ cfundecs(J, F, body);
+
+ cstmlist(J, F, body);
+ if (F->len == 0 || F->code[F->len - 1] != OP_RETURN) {
+ emit(J, F, OP_UNDEF);
+ emit(J, F, OP_RETURN);
+ }
+}
+
static js_Function *newfun(js_State *J, js_Ast *name, js_Ast *params, js_Ast *body)
{
js_Function *F = malloc(sizeof(js_Function));
@@ -477,11 +508,7 @@
F->next = J->fun;
J->fun = F;
- cstmlist(J, F, body);
- if (F->len == 0 || F->code[F->len - 1] != OP_RETURN) {
- emit(J, F, OP_UNDEF);
- emit(J, F, OP_RETURN);
- }
+ cfunbody(J, F, name, params, body);
return F;
}
--- a/jscompile.h
+++ b/jscompile.h
@@ -6,6 +6,7 @@
OP_POP,
OP_DUP,
+ OP_CLOSURE,
OP_CONST,
OP_UNDEF,
OP_NULL,
@@ -19,8 +20,6 @@
OP_OBJECTPUT,
OP_VARDEC,
- OP_FUNDEC,
- OP_FUNEXP,
OP_LOADVAR, /* -(name)- <value> */
OP_LOADINDEX, /* <obj> <idx> -- <value> */
--- a/jsdump.c
+++ b/jsdump.c
@@ -626,8 +626,7 @@
case OP_LOADMEMBER:
case OP_AVAR:
case OP_AMEMBER:
- case OP_FUNDEC:
- case OP_FUNEXP:
+ case OP_CLOSURE:
pc(' ');
jsC_dumpvalue(J, fun->klist[*p++]);
break;
@@ -650,8 +649,10 @@
for (i = 0; i < fun->klen; i++) {
if (fun->klist[i].type == JS_TFUNCTION) {
- nl();
- jsC_dumpfunction(J, fun->klist[i].u.function);
+ if (fun->klist[i].u.function != fun) {
+ nl();
+ jsC_dumpfunction(J, fun->klist[i].u.function);
+ }
}
}
}