mirror of
https://github.com/ccxvii/mujs.git
synced 2026-09-22 07:03:36 +08:00
Clean up handling of function declarations / statements / expressions.
This commit is contained in:
+4
-4
@@ -286,7 +286,7 @@ static void cexp(JF, js_Ast *exp)
|
||||
emit(J, F, n);
|
||||
break;
|
||||
|
||||
case EXP_FUNC:
|
||||
case EXP_FUN:
|
||||
emitfunction(J, F, OP_CLOSURE, newfun(J, exp->a, exp->b, exp->c));
|
||||
break;
|
||||
|
||||
@@ -412,7 +412,7 @@ static void cstm(JF, js_Ast *stm)
|
||||
int loop, then, end;
|
||||
|
||||
switch (stm->type) {
|
||||
case STM_FUNC:
|
||||
case AST_FUNDEC:
|
||||
break;
|
||||
|
||||
case STM_BLOCK:
|
||||
@@ -509,7 +509,7 @@ static void cfundecs(JF, js_Ast *list)
|
||||
{
|
||||
while (list) {
|
||||
js_Ast *stm = list->a;
|
||||
if (stm->type == STM_FUNC) {
|
||||
if (stm->type == AST_FUNDEC) {
|
||||
emitfunction(J, F, OP_CLOSURE, newfun(J, stm->a, stm->b, stm->c));
|
||||
emitname(J, F, OP_FUNDEC, stm->a->string);
|
||||
}
|
||||
@@ -521,7 +521,7 @@ static void cvardecs(JF, js_Ast *node)
|
||||
{
|
||||
if (node->type == EXP_VAR) {
|
||||
emitname(J, F, OP_VARDEC, node->a->string);
|
||||
} else if (node->type != EXP_FUNC && node->type != STM_FUNC) {
|
||||
} else if (node->type != EXP_FUN && node->type != AST_FUNDEC) {
|
||||
if (node->a) cvardecs(J, F, node->a);
|
||||
if (node->b) cvardecs(J, F, node->b);
|
||||
if (node->c) cvardecs(J, F, node->c);
|
||||
|
||||
@@ -6,19 +6,19 @@
|
||||
#include <assert.h>
|
||||
|
||||
static const char *astname[] = {
|
||||
"list", "ident", "number", "string", "regexp", "undef", "null", "true",
|
||||
"false", "this", "array", "object", "prop_val", "prop_get", "prop_set",
|
||||
"index", "member", "call", "new", "funexp", "delete", "void", "typeof",
|
||||
"preinc", "predec", "postinc", "postdec", "pos", "neg", "bitnot",
|
||||
"lognot", "logor", "logand", "bitor", "bitxor", "bitand", "eq", "ne",
|
||||
"eq3", "ne3", "lt", "gt", "le", "ge", "instanceof", "in", "shl", "shr",
|
||||
"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", "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",
|
||||
"list", "ident", "number", "string", "regexp", "fundec", "undef",
|
||||
"null", "true", "false", "this", "fun", "array", "object", "prop_val",
|
||||
"prop_get", "prop_set", "index", "member", "call", "new", "delete",
|
||||
"void", "typeof", "preinc", "predec", "postinc", "postdec", "pos",
|
||||
"neg", "bitnot", "lognot", "logor", "logand", "bitor", "bitxor",
|
||||
"bitand", "eq", "ne", "eq3", "ne3", "lt", "gt", "le", "ge",
|
||||
"instanceof", "in", "shl", "shr", "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", "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",
|
||||
};
|
||||
|
||||
static const char *opname[] = {
|
||||
@@ -268,7 +268,7 @@ static void pexpi(int d, int i, js_Ast *exp)
|
||||
if (i) pc(')');
|
||||
break;
|
||||
|
||||
case EXP_FUNC:
|
||||
case EXP_FUN:
|
||||
ps("(function ");
|
||||
if (exp->a) pexpi(d, 1, exp->a);
|
||||
pc('(');
|
||||
@@ -352,7 +352,7 @@ static void pstm(int d, js_Ast *stm)
|
||||
in(d);
|
||||
|
||||
switch (stm->type) {
|
||||
case STM_FUNC:
|
||||
case AST_FUNDEC:
|
||||
ps("function ");
|
||||
pexpi(d, 1, stm->a);
|
||||
pc('(');
|
||||
@@ -533,7 +533,7 @@ static void snode(int d, js_Ast *node)
|
||||
case AST_REGEXP: pc(' '); pregexp(node->string, node->number); break;
|
||||
case AST_NUMBER: printf(" %.9g", node->number); break;
|
||||
case STM_BLOCK: afun = sblock; break;
|
||||
case STM_FUNC: case EXP_FUNC: cfun = sblock; break;
|
||||
case AST_FUNDEC: case EXP_FUN: cfun = sblock; break;
|
||||
case STM_SWITCH: bfun = sblock; break;
|
||||
case STM_CASE: bfun = sblock; break;
|
||||
case STM_DEFAULT: afun = sblock; break;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#define nelem(a) (sizeof (a) / sizeof (a)[0])
|
||||
|
||||
#define LIST(h) jsP_newnode(J, AST_LIST, h, 0, 0, 0);
|
||||
#define LIST(h) jsP_newnode(J, AST_LIST, h, 0, 0, 0)
|
||||
|
||||
#define EXP0(x) jsP_newnode(J, EXP_ ## x, 0, 0, 0, 0)
|
||||
#define EXP1(x,a) jsP_newnode(J, EXP_ ## x, a, 0, 0, 0)
|
||||
@@ -24,7 +24,7 @@ static js_Ast *expression(js_State *J, int notin);
|
||||
static js_Ast *assignment(js_State *J, int notin);
|
||||
static js_Ast *memberexp(js_State *J);
|
||||
static js_Ast *statement(js_State *J);
|
||||
static js_Ast *funcbody(js_State *J);
|
||||
static js_Ast *funbody(js_State *J);
|
||||
|
||||
js_Ast *jsP_newnode(js_State *J, int type, js_Ast *a, js_Ast *b, js_Ast *c, js_Ast *d)
|
||||
{
|
||||
@@ -70,6 +70,8 @@ void jsP_freeparse(js_State *J)
|
||||
J->ast = NULL;
|
||||
}
|
||||
|
||||
/* Lookahead */
|
||||
|
||||
static inline void next(js_State *J)
|
||||
{
|
||||
J->lookahead = jsP_lex(J);
|
||||
@@ -215,7 +217,7 @@ static js_Ast *propassign(js_State *J)
|
||||
name = propname(J);
|
||||
expect(J, '(');
|
||||
expect(J, ')');
|
||||
body = funcbody(J);
|
||||
body = funbody(J);
|
||||
return EXP2(PROP_GET, name, body);
|
||||
}
|
||||
if (!strcmp(name->string, "set")) {
|
||||
@@ -223,7 +225,7 @@ static js_Ast *propassign(js_State *J)
|
||||
expect(J, '(');
|
||||
arg = identifier(J);
|
||||
expect(J, ')');
|
||||
body = funcbody(J);
|
||||
body = funbody(J);
|
||||
return EXP3(PROP_SET, name, arg, body);
|
||||
}
|
||||
}
|
||||
@@ -247,6 +249,54 @@ static js_Ast *objectliteral(js_State *J)
|
||||
return head;
|
||||
}
|
||||
|
||||
/* Functions */
|
||||
|
||||
static js_Ast *parameters(js_State *J)
|
||||
{
|
||||
js_Ast *head, *tail;
|
||||
if (J->lookahead == ')')
|
||||
return NULL;
|
||||
head = tail = LIST(identifier(J));
|
||||
while (accept(J, ',')) {
|
||||
tail = tail->b = LIST(identifier(J));
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
static js_Ast *fundec(js_State *J)
|
||||
{
|
||||
js_Ast *a, *b, *c;
|
||||
a = identifier(J);
|
||||
expect(J, '(');
|
||||
b = parameters(J);
|
||||
expect(J, ')');
|
||||
c = funbody(J);
|
||||
return jsP_newnode(J, AST_FUNDEC, a, b, c, 0);
|
||||
}
|
||||
|
||||
static js_Ast *funstm(js_State *J)
|
||||
{
|
||||
js_Ast *a, *b, *c;
|
||||
a = identifier(J);
|
||||
expect(J, '(');
|
||||
b = parameters(J);
|
||||
expect(J, ')');
|
||||
c = funbody(J);
|
||||
/* rewrite function statement as "var X = function X() {}" */
|
||||
return STM1(VAR, LIST(EXP2(VAR, a, EXP3(FUN, a, b, c))));
|
||||
}
|
||||
|
||||
static js_Ast *funexp(js_State *J)
|
||||
{
|
||||
js_Ast *a, *b, *c;
|
||||
a = identifieropt(J);
|
||||
expect(J, '(');
|
||||
b = parameters(J);
|
||||
expect(J, ')');
|
||||
c = funbody(J);
|
||||
return EXP3(FUN, a, b, c);
|
||||
}
|
||||
|
||||
/* Expressions */
|
||||
|
||||
static js_Ast *primary(js_State *J)
|
||||
@@ -299,21 +349,9 @@ static js_Ast *arguments(js_State *J)
|
||||
return head;
|
||||
}
|
||||
|
||||
static js_Ast *parameters(js_State *J)
|
||||
{
|
||||
js_Ast *head, *tail;
|
||||
if (J->lookahead == ')')
|
||||
return NULL;
|
||||
head = tail = LIST(identifier(J));
|
||||
while (accept(J, ',')) {
|
||||
tail = tail->b = LIST(identifier(J));
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
static js_Ast *newexp(js_State *J)
|
||||
{
|
||||
js_Ast *a, *b, *c;
|
||||
js_Ast *a, *b;
|
||||
|
||||
if (accept(J, TK_NEW)) {
|
||||
a = memberexp(J);
|
||||
@@ -325,14 +363,8 @@ static js_Ast *newexp(js_State *J)
|
||||
return EXP1(NEW, a);
|
||||
}
|
||||
|
||||
if (accept(J, TK_FUNCTION)) {
|
||||
a = identifieropt(J);
|
||||
expect(J, '(');
|
||||
b = parameters(J);
|
||||
expect(J, ')');
|
||||
c = funcbody(J);
|
||||
return EXP3(FUNC, a, b, c);
|
||||
}
|
||||
if (accept(J, TK_FUNCTION))
|
||||
return funexp(J);
|
||||
|
||||
return primary(J);
|
||||
}
|
||||
@@ -752,6 +784,11 @@ static js_Ast *statement(js_State *J)
|
||||
return STM0(DEBUGGER);
|
||||
}
|
||||
|
||||
if (accept(J, TK_FUNCTION)) {
|
||||
jsP_warning(J, "function statements are not standard");
|
||||
return funstm(J);
|
||||
}
|
||||
|
||||
/* labelled statement or expression statement */
|
||||
if (J->lookahead == TK_IDENTIFIER) {
|
||||
a = expression(J, 0);
|
||||
@@ -764,9 +801,6 @@ static js_Ast *statement(js_State *J)
|
||||
}
|
||||
|
||||
/* expression statement */
|
||||
if (J->lookahead == TK_FUNCTION)
|
||||
jsP_warning(J, "naked function expression");
|
||||
|
||||
a = expression(J, 0);
|
||||
semicolon(J);
|
||||
return a;
|
||||
@@ -777,36 +811,29 @@ static js_Ast *statement(js_State *J)
|
||||
|
||||
/* Program */
|
||||
|
||||
static js_Ast *chunkelement(js_State *J)
|
||||
static js_Ast *scriptelement(js_State *J)
|
||||
{
|
||||
js_Ast *a, *b, *c;
|
||||
if (accept(J, TK_FUNCTION)) {
|
||||
a = identifier(J);
|
||||
expect(J, '(');
|
||||
b = parameters(J);
|
||||
expect(J, ')');
|
||||
c = funcbody(J);
|
||||
return STM3(FUNC, a, b, c);
|
||||
}
|
||||
if (accept(J, TK_FUNCTION))
|
||||
return fundec(J);
|
||||
return statement(J);
|
||||
}
|
||||
|
||||
static js_Ast *chunklist(js_State *J)
|
||||
static js_Ast *script(js_State *J)
|
||||
{
|
||||
js_Ast *head, *tail;
|
||||
if (J->lookahead == '}' || J->lookahead == 0)
|
||||
return NULL;
|
||||
head = tail = LIST(chunkelement(J));
|
||||
head = tail = LIST(scriptelement(J));
|
||||
while (J->lookahead != '}' && J->lookahead != 0)
|
||||
tail = tail->b = LIST(chunkelement(J));
|
||||
tail = tail->b = LIST(scriptelement(J));
|
||||
return head;
|
||||
}
|
||||
|
||||
static js_Ast *funcbody(js_State *J)
|
||||
static js_Ast *funbody(js_State *J)
|
||||
{
|
||||
js_Ast *a;
|
||||
expect(J, '{');
|
||||
a = chunklist(J);
|
||||
a = script(J);
|
||||
expect(J, '}');
|
||||
return a;
|
||||
}
|
||||
@@ -815,7 +842,7 @@ void jsP_warning(js_State *J, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
fprintf(stderr, "%s:%d: warning:", J->filename, J->line);
|
||||
fprintf(stderr, "%s:%d: warning: ", J->filename, J->line);
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
@@ -846,5 +873,5 @@ js_Ast *jsP_parse(js_State *J, const char *filename, const char *source)
|
||||
}
|
||||
|
||||
next(J);
|
||||
return chunklist(J);
|
||||
return script(J);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ enum
|
||||
AST_STRING,
|
||||
AST_REGEXP,
|
||||
|
||||
AST_FUNDEC,
|
||||
|
||||
/* literals */
|
||||
EXP_UNDEF, /* for array elisions */
|
||||
EXP_NULL,
|
||||
@@ -27,6 +29,8 @@ enum
|
||||
EXP_FALSE,
|
||||
EXP_THIS,
|
||||
|
||||
EXP_FUN,
|
||||
|
||||
EXP_ARRAY,
|
||||
EXP_OBJECT,
|
||||
EXP_PROP_VAL,
|
||||
@@ -38,7 +42,6 @@ enum
|
||||
EXP_MEMBER,
|
||||
EXP_CALL,
|
||||
EXP_NEW,
|
||||
EXP_FUNC, /* function expression */
|
||||
|
||||
EXP_DELETE,
|
||||
EXP_VOID,
|
||||
@@ -96,7 +99,6 @@ enum
|
||||
EXP_VAR, /* var initializer */
|
||||
|
||||
/* statements */
|
||||
STM_FUNC, /* function declaration */
|
||||
STM_BLOCK,
|
||||
STM_NOP,
|
||||
STM_VAR,
|
||||
|
||||
Reference in New Issue
Block a user