diff --git a/jscompile.c b/jscompile.c index ef15196..969f839 100644 --- a/jscompile.c +++ b/jscompile.c @@ -201,8 +201,10 @@ static void cobject(JF, js_Ast *list) cexp(J, F, kv->b); emit(J, F, OP_SETPROP); emit(J, F, OP_POP); + } else { + // TODO: set/get + jsC_error(J, kv, "property setters and getters are not implemented"); } - // TODO: set, get list = list->b; } } diff --git a/jscompile.h b/jscompile.h index 160b022..e22e644 100644 --- a/jscompile.h +++ b/jscompile.h @@ -1,7 +1,9 @@ #ifndef js_compile_h #define js_compile_h -enum +typedef enum js_OpCode js_OpCode; + +enum js_OpCode { OP_POP, /* A -- */ OP_POP2, /* A B -- */ diff --git a/jsrun.c b/jsrun.c index e5e3889..d7c7eee 100644 --- a/jsrun.c +++ b/jsrun.c @@ -400,7 +400,7 @@ void js_call(js_State *J, int n) else if (obj->type == JS_CCFUNCTION) jsR_callcfunction(J, n, obj->u.c.function); else - js_typeerror(J, "not a function"); + js_typeerror(J, "call: not a function"); BOT = savebot; } @@ -451,7 +451,7 @@ void js_construct(js_State *J, int n) void js_savetry(js_State *J, short *pc) { if (J->trylen == JS_TRYLIMIT) - js_error(J, "exception stack overflow"); + js_error(J, "try: exception stack overflow"); J->trybuf[J->trylen].E = J->E; J->trybuf[J->trylen].top = J->top; J->trybuf[J->trylen].bot = J->bot; @@ -512,7 +512,8 @@ static void jsR_run(js_State *J, js_Function *F) const char **ST = F->strtab; short *pcstart = F->code; short *pc = F->code; - int opcode, offset; + js_OpCode opcode; + int offset; const char *str; js_Object *obj; @@ -574,7 +575,7 @@ static void jsR_run(js_State *J, js_Function *F) if (ref) js_pushvalue(J, ref->value); else - js_referenceerror(J, "%s", str); + js_referenceerror(J, "%s is not defined", str); break; case OP_SETVAR: @@ -749,7 +750,9 @@ static void jsR_run(js_State *J, js_Function *F) case OP_LE: b = js_compare(J); js_pushboolean(J, b <= 0); break; case OP_GE: b = js_compare(J); js_pushboolean(J, b >= 0); break; - // OP_INSTANCEOF + case OP_INSTANCEOF: + js_instanceof(J); + break; /* Equality */ diff --git a/jsvalue.c b/jsvalue.c index 4bd8d99..fc29682 100644 --- a/jsvalue.c +++ b/jsvalue.c @@ -296,6 +296,38 @@ void js_newcconstructor(js_State *J, js_CFunction cfun, js_CFunction ccon) /* Non-trivial operations on values. These are implemented using the stack. */ +void js_instanceof(js_State *J) +{ + js_Object *O, *V; + + if (!js_iscallable(J, -1)) + js_typeerror(J, "instanceof: invalid operand"); + + if (!js_isobject(J, -2)) { + js_pop(J, 2); + js_pushboolean(J, 0); + return; + } + V = js_toobject(J, -2); + + js_getproperty(J, -1, "prototype"); + if (!js_isobject(J, -1)) + js_typeerror(J, "instanceof: 'prototype' property is not an object"); + O = js_toobject(J, -1); + + while (V) { + V = V->prototype; + if (O == V) { + js_pop(J, 3); + js_pushboolean(J, 1); + return; + } + } + + js_pop(J, 3); + js_pushboolean(J, 0); +} + void js_concat(js_State *J) { js_Value va = js_toprimitive(J, -2, JS_HNONE); diff --git a/jsvalue.h b/jsvalue.h index 78d8ec9..50312d8 100644 --- a/jsvalue.h +++ b/jsvalue.h @@ -92,6 +92,8 @@ unsigned int jsV_numbertouint32(double n); const char *jsV_numbertostring(js_State *J, double number); double jsV_stringtonumber(js_State *J, const char *string); +void js_instanceof(js_State *J); + /* jsproperty.c */ js_Object *jsV_newobject(js_State *J, js_Class type, js_Object *prototype); js_Property *jsV_getownproperty(js_State *J, js_Object *obj, const char *name);