Support 'typeof' operator.

This commit is contained in:
Tor Andersson
2014-01-18 17:38:40 +01:00
parent 9650392e04
commit 24f48308ce
6 changed files with 55 additions and 22 deletions

View File

@@ -44,7 +44,6 @@ enum
OP_CALL, /* <closure> <this> <args...> -(numargs)- <returnvalue> */
OP_NEW, /* <closure> <args...> -(numargs)- <returnvalue> */
OP_VOID,
OP_TYPEOF,
OP_POS,
OP_NEG,

2
jsgc.c
View File

@@ -1,7 +1,7 @@
#include "js.h"
#include "jscompile.h"
#include "jsrun.h"
#include "jsobject.h"
#include "jsrun.h"
#include "jsstate.h"
static void jsG_markobject(js_State *J, int mark, js_Object *obj);

View File

@@ -1,7 +1,7 @@
#include "js.h"
#include "jscompile.h"
#include "jsrun.h"
#include "jsobject.h"
#include "jsrun.h"
#include "jsstate.h"
static js_Object *jsR_newfunction(js_State *J, js_Function *function, js_Environment *scope)

42
jsrun.c
View File

@@ -119,6 +119,19 @@ int js_isstring(js_State *J, int idx) { return stackidx(J, idx)->type == JS_TSTR
int js_isprimitive(js_State *J, int idx) { return stackidx(J, idx)->type != JS_TOBJECT; }
int js_isobject(js_State *J, int idx) { return stackidx(J, idx)->type == JS_TOBJECT; }
const char *js_typeof(js_State *J, int idx)
{
switch (stackidx(J, idx)->type) {
case JS_TUNDEFINED: return "undefined";
case JS_TNULL: return "object";
case JS_TBOOLEAN: return "boolean";
case JS_TNUMBER: return "number";
case JS_TSTRING: return "string";
case JS_TOBJECT: return "object";
}
return "object";
}
js_Value js_tovalue(js_State *J, int idx)
{
return *stackidx(J, idx);
@@ -587,6 +600,12 @@ static void jsR_run(js_State *J, js_Function *F)
/* Unary expressions */
case OP_TYPEOF:
str = js_typeof(J, -1);
js_pop(J, 1);
js_pushliteral(J, str);
break;
case OP_POS:
x = js_tonumber(J, -1);
js_pop(J, 1);
@@ -614,25 +633,7 @@ static void jsR_run(js_State *J, js_Function *F)
/* Binary expressions */
case OP_ADD:
{
js_Value va = js_toprimitive(J, -2, JS_HNONE);
js_Value vb = js_toprimitive(J, -1, JS_HNONE);
if (va.type == JS_TSTRING || vb.type == JS_TSTRING) {
const char *sa = jsR_tostring(J, &va);
const char *sb = jsR_tostring(J, &vb);
char *sab = malloc(strlen(sa) + strlen(sb) + 1);
strcpy(sab, sa);
strcat(sab, sb);
js_pop(J, 2);
js_pushstring(J, sab);
free(sab);
} else {
x = jsR_tonumber(J, &va);
y = jsR_tonumber(J, &vb);
js_pop(J, 2);
js_pushnumber(J, x + y);
}
}
jsR_concat(J);
break;
case OP_SUB:
@@ -795,6 +796,9 @@ int jsR_loadscript(js_State *J, const char *filename, const char *source)
if (!P) return 1;
jsP_optimize(J, P);
F = jsC_compile(J, P);
jsP_dumpsyntax(J, P);
jsP_freeparse(J);
if (!F) return 1;

View File

@@ -16,6 +16,8 @@ js_Environment *jsR_newenvironment(js_State *J, js_Object *variables, js_Environ
int jsR_loadscript(js_State *J, const char *filename, const char *source);
void jsR_error(js_State *J, const char *fmt, ...);
void js_pushobject(js_State *J, js_Object *v);
js_Object *js_toobject(js_State *J, int idx);
js_Value js_toprimitive(js_State *J, int idx, int hint);
/* public */
@@ -43,6 +45,7 @@ void js_newscript(js_State *J, js_Function *function);
void js_newcfunction(js_State *J, js_CFunction fun);
void js_newcconstructor(js_State *J, js_CFunction fun, js_CFunction con);
const char *js_typeof(js_State *J, int idx);
int js_isundefined(js_State *J, int idx);
int js_isnull(js_State *J, int idx);
int js_isboolean(js_State *J, int idx);

View File

@@ -1,5 +1,6 @@
#include "js.h"
#include "jsobject.h"
#include "jsrun.h"
js_Value jsR_toprimitive(js_State *J, const js_Value *v, int preferred)
{
@@ -99,3 +100,29 @@ js_Object *jsR_toobject(js_State *J, const js_Value *v)
}
jsR_error(J, "TypeError (ToObject)");
}
void jsR_concat(js_State *J)
{
js_Value va = js_toprimitive(J, -2, JS_HNONE);
js_Value vb = js_toprimitive(J, -1, JS_HNONE);
if (va.type == JS_TSTRING || vb.type == JS_TSTRING) {
const char *sa = jsR_tostring(J, &va);
const char *sb = jsR_tostring(J, &vb);
char *sab = malloc(strlen(sa) + strlen(sb) + 1);
strcpy(sab, sa);
strcat(sab, sb);
js_pop(J, 2);
js_pushstring(J, sab);
free(sab);
} else {
double x = jsR_tonumber(J, &va);
double y = jsR_tonumber(J, &vb);
js_pop(J, 2);
js_pushnumber(J, x + y);
}
}
int jsR_compare(js_State *J)
{
return 0;
}