Implement value stack and use it in the interpreter.

We can now run simple programs that don't use function calls.
This commit is contained in:
Tor Andersson
2014-01-14 18:17:06 +01:00
parent 8d5ace5e79
commit f77a6e7e8e
12 changed files with 687 additions and 345 deletions
+219 -110
View File
@@ -45,10 +45,10 @@ static void freefun(js_State *J, js_Function *F)
{
// int i;
// for (i = 0; i < F->funlen; i++)
// freefun(J, F->funlist[i]);
free(F->funlist);
free(F->numlist);
free(F->strlist);
// freefun(J, F->funtab[i]);
free(F->funtab);
free(F->numtab);
free(F->strtab);
free(F->code);
free(F);
}
@@ -68,9 +68,9 @@ static int addfunction(JF, js_Function *value)
{
if (F->funlen >= F->funcap) {
F->funcap = F->funcap ? F->funcap * 2 : 16;
F->funlist = realloc(F->funlist, F->funcap * sizeof *F->funlist);
F->funtab = realloc(F->funtab, F->funcap * sizeof *F->funtab);
}
F->funlist[F->funlen] = value;
F->funtab[F->funlen] = value;
return F->funlen++;
}
@@ -78,13 +78,13 @@ static int addnumber(JF, double value)
{
int i;
for (i = 0; i < F->numlen; i++)
if (F->numlist[i] == value)
if (F->numtab[i] == value)
return i;
if (F->numlen >= F->numcap) {
F->numcap = F->numcap ? F->numcap * 2 : 16;
F->numlist = realloc(F->numlist, F->numcap * sizeof *F->numlist);
F->numtab = realloc(F->numtab, F->numcap * sizeof *F->numtab);
}
F->numlist[F->numlen] = value;
F->numtab[F->numlen] = value;
return F->numlen++;
}
@@ -92,26 +92,35 @@ static int addstring(JF, const char *value)
{
int i;
for (i = 0; i < F->strlen; i++)
if (!strcmp(F->strlist[i], value))
if (!strcmp(F->strtab[i], value))
return i;
if (F->strlen >= F->strcap) {
F->strcap = F->strcap ? F->strcap * 2 : 16;
F->strlist = realloc(F->strlist, F->strcap * sizeof *F->strlist);
F->strtab = realloc(F->strtab, F->strcap * sizeof *F->strtab);
}
F->strlist[F->strlen] = value;
F->strtab[F->strlen] = value;
return F->strlen++;
}
static void emitfunction(JF, int opcode, js_Function *fun)
static void emitfunction(JF, js_Function *fun)
{
emit(J, F, opcode);
emit(J, F, OP_CLOSURE);
emit(J, F, addfunction(J, F, fun));
}
static void emitnumber(JF, int opcode, double num)
static void emitnumber(JF, double num)
{
emit(J, F, opcode);
emit(J, F, addnumber(J, F, num));
if (num == 0)
emit(J, F, OP_NUMBER_0);
else if (num == 1)
emit(J, F, OP_NUMBER_1);
else if (num == (short)num) {
emit(J, F, OP_NUMBER_X);
emit(J, F, (short)num);
} else {
emit(J, F, OP_NUMBER);
emit(J, F, addnumber(J, F, num));
}
}
static void emitstring(JF, int opcode, const char *str)
@@ -146,13 +155,13 @@ static void label(JF, int inst)
/* Expressions */
static void unary(JF, js_Ast *exp, int opcode)
static void cunary(JF, js_Ast *exp, int opcode)
{
cexp(J, F, exp->a);
emit(J, F, opcode);
}
static void binary(JF, js_Ast *exp, int opcode)
static void cbinary(JF, js_Ast *exp, int opcode)
{
cexp(J, F, exp->a);
cexp(J, F, exp->b);
@@ -163,9 +172,12 @@ static void carray(JF, js_Ast *list)
{
int i = 0;
while (list) {
emit(J, F, OP_DUP);
emit(J, F, OP_NUMBER_X);
cexp(J, F, list->a);
emit(J, F, OP_ARRAYPUT);
emit(J, F, i++);
emit(J, F, OP_SETPROP);
emit(J, F, OP_POP);
list = list->b;
}
}
@@ -176,15 +188,16 @@ static void cobject(JF, js_Ast *list)
js_Ast *kv = list->a;
if (kv->type == EXP_PROP_VAL) {
js_Ast *prop = kv->a;
cexp(J, F, kv->b);
emit(J, F, OP_DUP);
if (prop->type == AST_IDENTIFIER || prop->type == AST_STRING)
emitstring(J, F, OP_OBJECTPUT, prop->string);
else if (prop->type == AST_STRING)
emitstring(J, F, OP_OBJECTPUT, prop->string);
emitstring(J, F, OP_STRING, prop->string);
else if (prop->type == AST_NUMBER)
emitnumber(J, F, OP_OBJECTPUT, prop->number);
emitnumber(J, F, prop->number);
else
jsC_error(J, list, "illegal property name in object initializer");
cexp(J, F, kv->b);
emit(J, F, OP_SETPROP);
emit(J, F, OP_POP);
}
// TODO: set, get
list = list->b;
@@ -202,38 +215,114 @@ static int cargs(JF, js_Ast *list)
return n;
}
static void clval(JF, js_Ast *exp)
static void cassign(JF, js_Ast *lhs, js_Ast *rhs)
{
switch (exp->type) {
switch (lhs->type) {
case AST_IDENTIFIER:
emitstring(J, F, OP_AVAR, exp->string);
cexp(J, F, rhs);
emitstring(J, F, OP_SETVAR, lhs->string);
break;
case EXP_INDEX:
cexp(J, F, exp->a);
cexp(J, F, exp->b);
emit(J, F, OP_AINDEX);
cexp(J, F, lhs->a);
cexp(J, F, lhs->b);
cexp(J, F, rhs);
emit(J, F, OP_SETPROP);
break;
case EXP_MEMBER:
cexp(J, F, exp->a);
emitstring(J, F, OP_AMEMBER, exp->b->string);
cexp(J, F, lhs->a);
emitstring(J, F, OP_STRING, lhs->b->string);
cexp(J, F, rhs);
emit(J, F, OP_SETPROP);
break;
case EXP_CALL:
/* host functions may return an assignable l-value */
cexp(J, F, exp);
case EXP_CALL: /* host functions may return an assignable l-value */
cexp(J, F, lhs);
cexp(J, F, rhs);
emit(J, F, OP_SETPROP);
break;
default:
jsC_error(J, exp, "invalid l-value in assignment");
jsC_error(J, lhs, "invalid l-value in assignment");
break;
}
}
static void assignop(JF, js_Ast *exp, int opcode)
static void cassignop1(JF, js_Ast *lhs, int dup)
{
clval(J, F, exp->a);
emit(J, F, OP_LOAD);
cexp(J, F, exp->b);
switch (lhs->type) {
case AST_IDENTIFIER:
emitstring(J, F, OP_GETVAR, lhs->string);
if (dup) emit(J, F, OP_DUP);
break;
case EXP_INDEX:
cexp(J, F, lhs->a);
cexp(J, F, lhs->b);
emit(J, F, OP_DUP2);
emit(J, F, OP_GETPROP);
if (dup) emit(J, F, OP_DUP1ROT4);
break;
case EXP_MEMBER:
cexp(J, F, lhs->a);
emitstring(J, F, OP_STRING, lhs->b->string);
emit(J, F, OP_DUP2);
emit(J, F, OP_GETPROP);
if (dup) emit(J, F, OP_DUP1ROT4);
break;
case EXP_CALL: /* host functions may return an assignable l-value */
cexp(J, F, lhs);
emit(J, F, OP_DUP2);
emit(J, F, OP_GETPROP);
if (dup) emit(J, F, OP_DUP1ROT4);
break;
default:
jsC_error(J, lhs, "invalid l-value in assignment");
break;
}
}
static void cassignop2(JF, js_Ast *lhs)
{
switch (lhs->type) {
case AST_IDENTIFIER:
emitstring(J, F, OP_SETVAR, lhs->string);
break;
case EXP_INDEX:
case EXP_MEMBER:
case EXP_CALL:
emit(J, F, OP_SETPROP);
break;
default:
jsC_error(J, lhs, "invalid l-value in assignment");
break;
}
}
static void cassignop(JF, js_Ast *lhs, js_Ast *rhs, int opcode)
{
cassignop1(J, F, lhs, 0);
cexp(J, F, rhs);
emit(J, F, opcode);
emit(J, F, OP_STORE);
cassignop2(J, F, lhs);
}
static void cdelete(JF, js_Ast *exp)
{
switch (exp->type) {
case AST_IDENTIFIER:
emitstring(J, F, OP_DELVAR, exp->string);
break;
case EXP_INDEX:
cexp(J, F, exp->a);
cexp(J, F, exp->b);
emit(J, F, OP_DELPROP);
break;
case EXP_MEMBER:
cexp(J, F, exp->a);
emitstring(J, F, OP_STRING, exp->b->string);
emit(J, F, OP_DELPROP);
break;
default:
jsC_error(J, exp, "invalid l-value in delete expression");
break;
}
}
static void cvarinit(JF, js_Ast *list)
@@ -242,9 +331,7 @@ static void cvarinit(JF, js_Ast *list)
js_Ast *var = list->a;
if (var->b) {
cexp(J, F, var->b);
emitstring(J, F, OP_AVAR, var->a->string);
emit(J, F, OP_STORE);
emit(J, F, OP_POP);
emitstring(J, F, OP_SETVAR, var->a->string);
}
list = list->b;
}
@@ -258,12 +345,13 @@ static void ccall(JF, js_Ast *fun, js_Ast *args)
cexp(J, F, fun->a);
emit(J, F, OP_DUP);
cexp(J, F, fun->b);
emit(J, F, OP_LOADINDEX);
emit(J, F, OP_GETPROP);
break;
case EXP_MEMBER:
cexp(J, F, fun->a);
emit(J, F, OP_DUP);
emitstring(J, F, OP_LOADMEMBER, fun->b->string);
emitstring(J, F, OP_STRING, fun->b->string);
emit(J, F, OP_GETPROP);
break;
default:
emit(J, F, OP_THIS);
@@ -281,9 +369,8 @@ static void cexp(JF, js_Ast *exp)
int n;
switch (exp->type) {
case AST_IDENTIFIER: emitstring(J, F, OP_LOADVAR, exp->string); break;
case AST_NUMBER: emitnumber(J, F, OP_NUMBER, exp->number); break;
case AST_STRING: emitstring(J, F, OP_STRING, exp->string); break;
case AST_NUMBER: emitnumber(J, F, exp->number); break;
case EXP_UNDEF: emit(J, F, OP_UNDEF); break;
case EXP_NULL: emit(J, F, OP_NULL); break;
case EXP_TRUE: emit(J, F, OP_TRUE); break;
@@ -300,15 +387,24 @@ static void cexp(JF, js_Ast *exp)
carray(J, F, exp->a);
break;
case EXP_FUN:
emitfunction(J, F, newfun(J, exp->a, exp->b, exp->c));
break;
case AST_IDENTIFIER:
emitstring(J, F, OP_GETVAR, exp->string);
break;
case EXP_INDEX:
cexp(J, F, exp->a);
cexp(J, F, exp->b);
emit(J, F, OP_LOADINDEX);
emit(J, F, OP_GETPROP);
break;
case EXP_MEMBER:
cexp(J, F, exp->a);
emitstring(J, F, OP_LOADMEMBER, exp->b->string);
emitstring(J, F, OP_STRING, exp->b->string);
emit(J, F, OP_GETPROP);
break;
case EXP_CALL:
@@ -322,13 +418,38 @@ static void cexp(JF, js_Ast *exp)
emit(J, F, n);
break;
case EXP_FUN:
emitfunction(J, F, OP_CLOSURE, newfun(J, exp->a, exp->b, exp->c));
case EXP_DELETE:
cdelete(J, F, exp->a);
break;
case EXP_DELETE:
clval(J, F, exp->a);
emit(J, F, OP_DELETE);
case EXP_PREINC:
cassignop1(J, F, exp->a, 0);
emit(J, F, OP_NUMBER_1);
emit(J, F, OP_ADD);
cassignop2(J, F, exp->a);
break;
case EXP_PREDEC:
cassignop1(J, F, exp->a, 0);
emit(J, F, OP_NUMBER_1);
emit(J, F, OP_SUB);
cassignop2(J, F, exp->a);
break;
case EXP_POSTINC:
cassignop1(J, F, exp->a, 1);
emit(J, F, OP_NUMBER_1);
emit(J, F, OP_ADD);
cassignop2(J, F, exp->a);
emit(J, F, OP_POP);
break;
case EXP_POSTDEC:
cassignop1(J, F, exp->a, 1);
emit(J, F, OP_NUMBER_1);
emit(J, F, OP_SUB);
cassignop2(J, F, exp->a);
emit(J, F, OP_POP);
break;
case EXP_VOID:
@@ -337,56 +458,46 @@ static void cexp(JF, js_Ast *exp)
emit(J, F, OP_UNDEF);
break;
case EXP_TYPEOF: unary(J, F, exp, OP_TYPEOF); break;
case EXP_POS: unary(J, F, exp, OP_POS); break;
case EXP_NEG: unary(J, F, exp, OP_NEG); break;
case EXP_BITNOT: unary(J, F, exp, OP_BITNOT); break;
case EXP_LOGNOT: unary(J, F, exp, OP_LOGNOT); break;
case EXP_TYPEOF: cunary(J, F, exp, OP_TYPEOF); break;
case EXP_POS: cunary(J, F, exp, OP_POS); break;
case EXP_NEG: cunary(J, F, exp, OP_NEG); break;
case EXP_BITNOT: cunary(J, F, exp, OP_BITNOT); break;
case EXP_LOGNOT: cunary(J, F, exp, OP_LOGNOT); break;
case EXP_PREINC: clval(J, F, exp->a); emit(J, F, OP_PREINC); break;
case EXP_PREDEC: clval(J, F, exp->a); emit(J, F, OP_PREDEC); break;
case EXP_POSTINC: clval(J, F, exp->a); emit(J, F, OP_POSTINC); break;
case EXP_POSTDEC: clval(J, F, exp->a); emit(J, F, OP_POSTDEC); break;
case EXP_BITOR: cbinary(J, F, exp, OP_BITOR); break;
case EXP_BITXOR: cbinary(J, F, exp, OP_BITXOR); break;
case EXP_BITAND: cbinary(J, F, exp, OP_BITAND); break;
case EXP_EQ: cbinary(J, F, exp, OP_EQ); break;
case EXP_NE: cbinary(J, F, exp, OP_NE); break;
case EXP_STRICTEQ: cbinary(J, F, exp, OP_STRICTEQ); break;
case EXP_STRICTNE: cbinary(J, F, exp, OP_STRICTNE); break;
case EXP_LT: cbinary(J, F, exp, OP_LT); break;
case EXP_GT: cbinary(J, F, exp, OP_GT); break;
case EXP_LE: cbinary(J, F, exp, OP_LE); break;
case EXP_GE: cbinary(J, F, exp, OP_GE); break;
case EXP_INSTANCEOF: cbinary(J, F, exp, OP_INSTANCEOF); break;
case EXP_IN: cbinary(J, F, exp, OP_IN); break;
case EXP_SHL: cbinary(J, F, exp, OP_SHL); break;
case EXP_SHR: cbinary(J, F, exp, OP_SHR); break;
case EXP_USHR: cbinary(J, F, exp, OP_USHR); break;
case EXP_ADD: cbinary(J, F, exp, OP_ADD); break;
case EXP_SUB: cbinary(J, F, exp, OP_SUB); break;
case EXP_MUL: cbinary(J, F, exp, OP_MUL); break;
case EXP_DIV: cbinary(J, F, exp, OP_DIV); break;
case EXP_MOD: cbinary(J, F, exp, OP_MOD); break;
case EXP_BITOR: binary(J, F, exp, OP_BITOR); break;
case EXP_BITXOR: binary(J, F, exp, OP_BITXOR); break;
case EXP_BITAND: binary(J, F, exp, OP_BITAND); break;
case EXP_EQ: binary(J, F, exp, OP_EQ); break;
case EXP_NE: binary(J, F, exp, OP_NE); break;
case EXP_EQ3: binary(J, F, exp, OP_EQ3); break;
case EXP_NE3: binary(J, F, exp, OP_NE3); break;
case EXP_LT: binary(J, F, exp, OP_LT); break;
case EXP_GT: binary(J, F, exp, OP_GT); break;
case EXP_LE: binary(J, F, exp, OP_LE); break;
case EXP_GE: binary(J, F, exp, OP_GE); break;
case EXP_INSTANCEOF: binary(J, F, exp, OP_INSTANCEOF); break;
case EXP_IN: binary(J, F, exp, OP_IN); break;
case EXP_SHL: binary(J, F, exp, OP_SHL); break;
case EXP_SHR: binary(J, F, exp, OP_SHR); break;
case EXP_USHR: binary(J, F, exp, OP_USHR); break;
case EXP_ADD: binary(J, F, exp, OP_ADD); break;
case EXP_SUB: binary(J, F, exp, OP_SUB); break;
case EXP_MUL: binary(J, F, exp, OP_MUL); break;
case EXP_DIV: binary(J, F, exp, OP_DIV); break;
case EXP_MOD: binary(J, F, exp, OP_MOD); break;
case EXP_ASS:
clval(J, F, exp->a);
cexp(J, F, exp->b);
emit(J, F, OP_STORE);
break;
case EXP_ASS_MUL: assignop(J, F, exp, OP_MUL); break;
case EXP_ASS_DIV: assignop(J, F, exp, OP_DIV); break;
case EXP_ASS_MOD: assignop(J, F, exp, OP_MOD); break;
case EXP_ASS_ADD: assignop(J, F, exp, OP_ADD); break;
case EXP_ASS_SUB: assignop(J, F, exp, OP_SUB); break;
case EXP_ASS_SHL: assignop(J, F, exp, OP_SHL); break;
case EXP_ASS_SHR: assignop(J, F, exp, OP_SHR); break;
case EXP_ASS_USHR: assignop(J, F, exp, OP_USHR); break;
case EXP_ASS_BITAND: assignop(J, F, exp, OP_BITAND); break;
case EXP_ASS_BITXOR: assignop(J, F, exp, OP_BITXOR); break;
case EXP_ASS_BITOR: assignop(J, F, exp, OP_BITOR); break;
case EXP_ASS: cassign(J, F, exp->a, exp->b); break;
case EXP_ASS_MUL: cassignop(J, F, exp->a, exp->b, OP_MUL); break;
case EXP_ASS_DIV: cassignop(J, F, exp->a, exp->b, OP_DIV); break;
case EXP_ASS_MOD: cassignop(J, F, exp->a, exp->b, OP_MOD); break;
case EXP_ASS_ADD: cassignop(J, F, exp->a, exp->b, OP_ADD); break;
case EXP_ASS_SUB: cassignop(J, F, exp->a, exp->b, OP_SUB); break;
case EXP_ASS_SHL: cassignop(J, F, exp->a, exp->b, OP_SHL); break;
case EXP_ASS_SHR: cassignop(J, F, exp->a, exp->b, OP_SHR); break;
case EXP_ASS_USHR: cassignop(J, F, exp->a, exp->b, OP_USHR); break;
case EXP_ASS_BITAND: cassignop(J, F, exp->a, exp->b, OP_BITAND); break;
case EXP_ASS_BITXOR: cassignop(J, F, exp->a, exp->b, OP_BITXOR); break;
case EXP_ASS_BITOR: cassignop(J, F, exp->a, exp->b, OP_BITOR); break;
case EXP_COMMA:
cexp(J, F, exp->a);
@@ -536,7 +647,7 @@ static void cfundecs(JF, js_Ast *list)
while (list) {
js_Ast *stm = list->a;
if (stm->type == AST_FUNDEC) {
emitfunction(J, F, OP_CLOSURE, newfun(J, stm->a, stm->b, stm->c));
emitfunction(J, F, newfun(J, stm->a, stm->b, stm->c));
emitstring(J, F, OP_FUNDEC, stm->a->string);
}
list = list->b;
@@ -558,7 +669,7 @@ static void cvardecs(JF, js_Ast *node)
static void cfunbody(JF, js_Ast *name, js_Ast *params, js_Ast *body)
{
if (name) {
emitfunction(J, F, OP_CLOSURE, F);
emitfunction(J, F, F);
emitstring(J, F, OP_FUNDEC, name->string);
}
@@ -568,10 +679,8 @@ static void cfunbody(JF, js_Ast *name, js_Ast *params, js_Ast *body)
cstmlist(J, F, body);
}
if (F->codelen == 0 || F->code[F->codelen - 1] != OP_RETURN) {
emit(J, F, OP_UNDEF);
emit(J, F, OP_RETURN);
}
emit(J, F, OP_UNDEF);
emit(J, F, OP_RETURN);
}
int jsC_error(js_State *J, js_Ast *node, const char *fmt, ...)
+32 -35
View File
@@ -3,12 +3,18 @@
enum
{
OP_POP,
OP_DUP,
OP_POP, /* A -- */
OP_DUP, /* A -- A A */
OP_DUP2, /* A B -- A B A B */
OP_DUP1ROT4, /* A B C -- C A B C */
OP_CLOSURE,
OP_NUMBER,
OP_STRING,
OP_NUMBER_0, /* -- 0 */
OP_NUMBER_1, /* -- 1 */
OP_NUMBER_X, /* -K- K */
OP_NUMBER, /* -N- <number> */
OP_STRING, /* -S- <string> */
OP_CLOSURE, /* -F- <closure> */
OP_UNDEF,
OP_NULL,
@@ -17,33 +23,23 @@ enum
OP_THIS,
OP_NEWARRAY,
OP_ARRAYPUT,
OP_NEWOBJECT,
OP_OBJECTPUT,
OP_FUNDEC, /* <closure> -(name)- */
OP_VARDEC, /* -(name)- */
OP_FUNDEC, /* <closure> -S- */
OP_VARDEC, /* -S- */
OP_LOADVAR, /* -(name)- <value> */
OP_LOADMEMBER, /* <obj> -(name)- <value> */
OP_LOADINDEX, /* <obj> <idx> -- <value> */
OP_GETVAR, /* -S- <value> */
OP_SETVAR, /* <value> -S- <value> */
OP_DELVAR, /* -S- <success> */
OP_AVAR, /* -(name)- <addr> */
OP_AMEMBER, /* <obj> -(name)- <addr> */
OP_AINDEX, /* <obj> <idx> -- <addr> */
OP_LOAD, /* <addr> -- <addr> <value> */
OP_STORE, /* <addr> <value> -- <value> */
OP_IN, /* <name> <obj> -- <exists?> */
OP_GETPROP, /* <obj> <name> -- <value> */
OP_SETPROP, /* <obj> <name> <value> -- <value> */
OP_DELPROP, /* <obj> <name> -- <success> */
OP_CALL, /* <thisvalue> <closure> <args...> -(numargs)- <returnvalue> */
OP_NEW, /* <closure> <args...> -(numargs)- <returnvalue> */
OP_DELETE, /* <addr> -- <success> */
OP_PREINC, /* <addr> -- <value+1> */
OP_PREDEC, /* <addr> -- <value-1> */
OP_POSTINC, /* <addr> -- <value> */
OP_POSTDEC, /* <addr> -- <value> */
OP_VOID,
OP_TYPEOF,
OP_POS,
@@ -56,14 +52,12 @@ enum
OP_BITAND,
OP_EQ,
OP_NE,
OP_EQ3,
OP_NE3,
OP_STRICTEQ,
OP_STRICTNE,
OP_LT,
OP_GT,
OP_LE,
OP_GE,
OP_INSTANCEOF,
OP_IN,
OP_SHL,
OP_SHR,
OP_USHR,
@@ -73,17 +67,20 @@ enum
OP_DIV,
OP_MOD,
OP_TRY,
OP_THROW,
OP_RETURN,
OP_DEBUGGER,
OP_INSTANCEOF,
OP_THROW,
OP_TRY,
OP_CATCH,
OP_ENDCATCH,
OP_WITH,
OP_ENDWITH,
OP_DEBUGGER,
OP_JUMP,
OP_JTRUE,
OP_JFALSE,
OP_RETURN,
};
struct js_Function
@@ -94,13 +91,13 @@ struct js_Function
short *code;
int codecap, codelen;
js_Function **funlist;
js_Function **funtab;
int funcap, funlen;
double *numlist;
double *numtab;
int numcap, numlen;
const char **strlist;
const char **strtab;
int strcap, strlen;
js_Function *next; /* alloc list */
+16 -19
View File
@@ -1,7 +1,6 @@
#include "js.h"
#include "jsparse.h"
#include "jscompile.h"
#include "jsvalue.h"
#include "jsobject.h"
#include <assert.h>
@@ -194,8 +193,8 @@ static void pexpi(int d, int i, js_Ast *exp)
case EXP_BITAND: pbin(d, i, exp, " & "); break;
case EXP_EQ: pbin(d, i, exp, " == "); break;
case EXP_NE: pbin(d, i, exp, " != "); break;
case EXP_EQ3: pbin(d, i, exp, " === "); break;
case EXP_NE3: pbin(d, i, exp, " !== "); break;
case EXP_STRICTEQ: pbin(d, i, exp, " === "); break;
case EXP_STRICTNE: pbin(d, i, exp, " !== "); break;
case EXP_LT: pbin(d, i, exp, " < "); break;
case EXP_GT: pbin(d, i, exp, " > "); break;
case EXP_LE: pbin(d, i, exp, " <= "); break;
@@ -598,13 +597,13 @@ void jsC_dumpfunction(js_State *J, js_Function *F)
printf("function %p %s(%d)\n", F, F->name, F->numparams);
for (i = 0; i < F->funlen; i++)
printf("\tfunction %p %s\n", F->funlist[i], F->funlist[i]->name);
printf("\tfunction %p %s\n", F->funtab[i], F->funtab[i]->name);
for (i = 0; i < F->strlen; i++) {
ps("\tstring "); pstr(F->strlist[i]); ps("\n");
ps("\tstring "); pstr(F->strtab[i]); ps("\n");
}
// TODO: regexp
for (i = 0; i < F->numlen; i++)
printf("\tnumber %.9g\n", F->numlist[i]);
printf("\tnumber %.9g\n", F->numtab[i]);
while (p < end) {
int c = *p++;
@@ -614,29 +613,27 @@ void jsC_dumpfunction(js_State *J, js_Function *F)
switch (c) {
case OP_CLOSURE:
pc(' ');
ps(F->funlist[*p++]->name);
ps(" f:");
ps(F->funtab[*p++]->name);
break;
case OP_NUMBER:
printf(" %.9g", F->numlist[*p++]);
printf(" %.9g", F->numtab[*p++]);
break;
case OP_STRING:
pc(' ');
pstr(F->strlist[*p++]);
pstr(F->strtab[*p++]);
break;
case OP_OBJECTPUT:
case OP_FUNDEC:
case OP_VARDEC:
case OP_LOADVAR:
case OP_LOADMEMBER:
case OP_AVAR:
case OP_AMEMBER:
case OP_GETVAR:
case OP_SETVAR:
case OP_DELVAR:
pc(' ');
ps(F->strlist[*p++]);
ps(F->strtab[*p++]);
break;
case OP_ARRAYPUT:
case OP_NUMBER_X:
case OP_CALL:
case OP_NEW:
case OP_JUMP:
@@ -650,9 +647,9 @@ void jsC_dumpfunction(js_State *J, js_Function *F)
}
for (i = 0; i < F->funlen; i++) {
if (F->funlist[i] != F) {
if (F->funtab[i] != F) {
nl();
jsC_dumpfunction(J, F->funlist[i]);
jsC_dumpfunction(J, F->funtab[i]);
}
}
}
+2 -2
View File
@@ -525,7 +525,7 @@ static int lex(js_State *J, const char **sp)
case '=':
if (ACCEPT('=')) {
if (ACCEPT('='))
return TK_EQ3;
return TK_STRICTEQ;
return TK_EQ;
}
return '=';
@@ -533,7 +533,7 @@ static int lex(js_State *J, const char **sp)
case '!':
if (ACCEPT('=')) {
if (ACCEPT('='))
return TK_NE3;
return TK_STRICTNE;
return TK_NE;
}
return '!';
+2 -2
View File
@@ -12,8 +12,8 @@ enum {
TK_GE,
TK_EQ,
TK_NE,
TK_EQ3,
TK_NE3,
TK_STRICTEQ,
TK_STRICTNE,
TK_SHL,
TK_SHR,
TK_USHR,
+2 -3
View File
@@ -1,5 +1,4 @@
#include "js.h"
#include "jsvalue.h"
#include "jsobject.h"
/*
@@ -21,6 +20,8 @@
static js_Property sentinel = { "", &sentinel, &sentinel, 0 };
static js_Property undefined = { "", &sentinel, &sentinel, 0, { {0}, JS_TUNDEFINED } };
static js_Property *newproperty(const char *key)
{
js_Property *node = malloc(sizeof(js_Property));
@@ -116,11 +117,9 @@ static void js_dumpvalue(js_State *J, js_Value v)
case JS_TBOOLEAN: printf(v.u.boolean ? "true" : "false"); break;
case JS_TNUMBER: printf("%.9g", v.u.number); break;
case JS_TSTRING: printf("'%s'", v.u.string); break;
case JS_TREGEXP: printf("/%s/", v.u.regexp.prog); break;
case JS_TOBJECT: printf("<object %p>", v.u.object); break;
case JS_TCLOSURE: printf("<closure %p>", v.u.closure); break;
case JS_TCFUNCTION: printf("<cfunction %p>", v.u.cfunction); break;
case JS_TREFERENCE: printf("<reference %p>", v.u.reference); break;
}
}
+26 -1
View File
@@ -1,6 +1,30 @@
#ifndef js_object_h
#define js_object_h
enum js_ValueType {
JS_TUNDEFINED,
JS_TNULL,
JS_TBOOLEAN,
JS_TNUMBER,
JS_TSTRING,
JS_TOBJECT,
JS_TCLOSURE,
JS_TCFUNCTION,
};
struct js_Value
{
union {
int boolean;
double number;
const char *string;
js_Object *object;
js_Closure *closure;
js_CFunction *cfunction;
} u;
js_ValueType type;
};
struct js_Property
{
char *key;
@@ -13,7 +37,7 @@ struct js_Object
{
js_Property *properties;
js_Object *prototype;
js_Object *parent;
js_Object *outer;
};
js_Object *js_newobject(js_State *J);
@@ -21,6 +45,7 @@ js_Property *js_getproperty(js_State *J, js_Object *obj, const char *name);
js_Property *js_setproperty(js_State *J, js_Object *obj, const char *name);
void js_deleteproperty(js_State *J, js_Object *obj, const char *name);
void jsC_dumpvalue(js_State *J, js_Value v);
void js_dumpobject(js_State *J, js_Object *obj);
#endif
+2 -2
View File
@@ -458,8 +458,8 @@ static js_Ast *equality(js_State *J, int notin)
loop:
if (accept(J, TK_EQ)) { a = EXP2(EQ, a, relational(J, notin)); goto loop; }
if (accept(J, TK_NE)) { a = EXP2(NE, a, relational(J, notin)); goto loop; }
if (accept(J, TK_EQ3)) { a = EXP2(EQ3, a, relational(J, notin)); goto loop; }
if (accept(J, TK_NE3)) { a = EXP2(NE3, a, relational(J, notin)); goto loop; }
if (accept(J, TK_STRICTEQ)) { a = EXP2(STRICTEQ, a, relational(J, notin)); goto loop; }
if (accept(J, TK_STRICTNE)) { a = EXP2(STRICTNE, a, relational(J, notin)); goto loop; }
return a;
}
+2 -2
View File
@@ -62,8 +62,8 @@ enum
EXP_BITAND,
EXP_EQ,
EXP_NE,
EXP_EQ3,
EXP_NE3,
EXP_STRICTEQ,
EXP_STRICTNE,
EXP_LT,
EXP_GT,
EXP_LE,
+383 -132
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -1,6 +1,7 @@
#ifndef js_run_h
#define js_run_h
void jsR_error(js_State *J, const char *message);
void jsR_runfunction(js_State *J, js_Function *F);
#endif
-37
View File
@@ -1,37 +0,0 @@
#ifndef js_value_h
#define js_value_h
enum js_ValueType {
JS_TUNDEFINED,
JS_TNULL,
JS_TBOOLEAN,
JS_TNUMBER,
JS_TSTRING,
JS_TREGEXP,
JS_TOBJECT,
JS_TCLOSURE,
JS_TCFUNCTION,
JS_TREFERENCE, /* l-value from aval/aindex/amember */
};
struct js_Value
{
union {
int boolean;
double number;
const char *string;
struct {
const char *prog;
unsigned char flags;
} regexp;
js_Object *object;
js_Closure *closure;
js_CFunction *cfunction;
js_Property *reference;
} u;
js_ValueType type;
};
void jsC_dumpvalue(js_State *J, js_Value v);
#endif