ref: c55b4e18bc30a3321179edf48cd42fcb3ccb6424
parent: 4c326a51a42436f9277cc86bf83d2e6dc4d3711e
author: Tor Andersson <tor@ccxvii.net>
date: Wed Jan 22 19:16:21 EST 2014
Implement instanceof expression.
--- a/jscompile.c
+++ b/jscompile.c
@@ -201,8 +201,10 @@
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;
}
}
--- 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 -- */
--- a/jsrun.c
+++ b/jsrun.c
@@ -400,7 +400,7 @@
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_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 @@
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 @@
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 @@
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 */
--- a/jsvalue.c
+++ b/jsvalue.c
@@ -296,6 +296,38 @@
/* 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);
--- a/jsvalue.h
+++ b/jsvalue.h
@@ -92,6 +92,8 @@
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);