ref: 52f78c568760d8157e0f4dd780f7ffe6c521bc65
parent: dceb42044791bacd56bcf5017c865ff13bb68d7c
author: Tor Andersson <tor.andersson@artifex.com>
date: Sun Jan 12 10:31:43 EST 2014
Compile sub-functions.
--- a/jscompile.c
+++ b/jscompile.c
@@ -8,17 +8,27 @@
#define JF js_State *J, js_Function *F
+static js_Function *newfun(js_State *J, js_Ast *name, js_Ast *params, js_Ast *body);
+
static void cexp(JF, js_Ast *exp);
static void cstmlist(JF, js_Ast *list);
+static int listlen(js_Ast *list)
+{
+ int n = 0;
+ while (list) {
+ n++;
+ list = list->b;
+ }
+ return n;
+}
+
static int consteq(js_Value a, js_Value b)
{
- if (a.type != b.type)
- return 0;
- if (a.type == JS_TNUMBER)
- return a.u.number == b.u.number;
- else
- return a.u.p == b.u.p;
+ if (a.type != b.type) return 0;
+ if (a.type == JS_TNUMBER) return a.u.number == b.u.number;
+ if (a.type == JS_TSTRING) return a.u.string == b.u.string;
+ return a.u.p == b.u.p;
}
static int addconst(JF, js_Value v)
@@ -50,6 +60,15 @@
F->code[F->len++] = value;
}
+static void emitfunction(JF, int opcode, js_Function *fun)
+{
+ js_Value v;
+ v.type = JS_TFUNCTION;
+ v.u.function = fun;
+ emit(J, F, opcode);
+ emit(J, F, addconst(J, F, v));
+}
+
static void emitnumber(JF, int opcode, double n)
{
js_Value v;
@@ -236,6 +255,10 @@
emit(J, F, n);
break;
+ case EXP_FUNC:
+ emitfunction(J, F, OP_FUNEXP, newfun(J, exp->a, exp->b, exp->c));
+ break;
+
case EXP_DELETE:
clval(J, F, exp->a);
emit(J, F, OP_DELETE);
@@ -361,6 +384,10 @@
int then, end;
switch (stm->type) {
+ case STM_FUNC:
+ emitfunction(J, F, OP_FUNDEC, newfun(J, stm->a, stm->b, stm->c));
+ break;
+
case STM_BLOCK:
cstmlist(J, F, stm->a);
break;
@@ -432,10 +459,13 @@
}
}
-static js_Function *newfun(js_State *J)
+static js_Function *newfun(js_State *J, js_Ast *name, js_Ast *params, js_Ast *body)
{
js_Function *F = malloc(sizeof(js_Function));
+ F->name = name ? name->string : "<anonymous>";
+ F->numparams = listlen(params);
+
F->cap = 256;
F->len = 0;
F->code = malloc(F->cap);
@@ -447,6 +477,12 @@
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);
+ }
+
return F;
}
@@ -491,13 +527,8 @@
return NULL;
}
- F = newfun(J);
- cstmlist(J, F, prog);
+ F = newfun(J, NULL, NULL, prog);
- emit(J, F, OP_UNDEF);
- emit(J, F, OP_RETURN);
-
J->fun = NULL;
return F;
}
-
--- a/jscompile.h
+++ b/jscompile.h
@@ -87,6 +87,9 @@
struct js_Function
{
+ const char *name;
+ int numparams;
+
unsigned char *code;
int cap, len;
@@ -99,6 +102,7 @@
js_Function *jsC_compile(js_State *J, js_Ast *prog);
void jsC_freecompile(js_State *J);
int jsC_error(js_State *J, js_Ast *node, const char *fmt, ...);
+
void jsC_dumpvalue(js_State *J, js_Value v);
void jsC_dumpfunction(js_State *J, js_Function *fun);
--- a/jsdump.c
+++ b/jsdump.c
@@ -15,7 +15,7 @@
"ushr", "add", "sub", "mul", "div", "mod", "cond", "ass", "ass_mul",
"ass_div", "ass_mod", "ass_add", "ass_sub", "ass_shl", "ass_shr",
"ass_ushr", "ass_bitand", "ass_bitxor", "ass_bitor", "comma",
- "var-init", "block", "fundec", "nop", "var", "if", "do-while", "while",
+ "var-init", "fundec", "block", "nop", "var", "if", "do-while", "while",
"for", "for-var", "for-in", "for-in-var", "continue", "break",
"return", "with", "switch", "throw", "try", "debugger", "label",
"case", "default",
@@ -594,7 +594,7 @@
case JS_TREGEXP: printf("<regexp %p>", v.u.p); break;
case JS_TOBJECT: printf("<object %p>", v.u.p); break;
- case JS_TFUNCTION: printf("<function %p>", v.u.p); break;
+ case JS_TFUNCTION: printf("<function %p>", v.u.function); break;
case JS_TCFUNCTION: printf("<cfunction %p>", v.u.p); break;
case JS_TCLOSURE: printf("<closure %p>", v.u.p); break;
case JS_TARGUMENTS: printf("<arguments %p>", v.u.p); break;
@@ -607,9 +607,10 @@
{
unsigned char *p = fun->code;
unsigned char *end = fun->code + fun->len;
- int dest;
+ int i, dest;
- printf("function with %d constants\n", fun->klen);
+ printf("function %p, %s, %d parameters, %d constants\n",
+ fun, fun->name, fun->numparams, fun->klen);
while (p < end) {
int c = *p++;
@@ -625,6 +626,8 @@
case OP_LOADMEMBER:
case OP_AVAR:
case OP_AMEMBER:
+ case OP_FUNDEC:
+ case OP_FUNEXP:
pc(' ');
jsC_dumpvalue(J, fun->klist[*p++]);
break;
@@ -643,5 +646,12 @@
}
nl();
+ }
+
+ for (i = 0; i < fun->klen; i++) {
+ if (fun->klist[i].type == JS_TFUNCTION) {
+ nl();
+ jsC_dumpfunction(J, fun->klist[i].u.function);
+ }
}
}
--- a/jsparse.h
+++ b/jsparse.h
@@ -96,8 +96,8 @@
EXP_VAR, /* var initializer */
/* statements */
- STM_BLOCK,
STM_FUNC, /* function declaration */
+ STM_BLOCK,
STM_NOP,
STM_VAR,
STM_IF,
--- a/jsrun.h
+++ b/jsrun.h
@@ -24,6 +24,7 @@
double number;
const char *string;
int boolean;
+ js_Function *function;
void *p;
} u;
int flag;