Implement Number and Object classes.

Split built-in functions into one file per class.
This commit is contained in:
Tor Andersson
2014-01-18 22:04:37 +01:00
parent 07610bd0ac
commit a592f61f36
10 changed files with 291 additions and 95 deletions
+8
View File
@@ -8,6 +8,7 @@
#include <string.h>
#include <setjmp.h>
#include <math.h>
#include <float.h>
/* noreturn is a GCC extension */
#ifdef __GNUC__
@@ -64,4 +65,11 @@ const char *js_intern(js_State *J, const char *s);
void js_printstrings(js_State *J);
void js_freestrings(js_State *J);
void jsB_initobject(js_State *J);
void jsB_initarray(js_State *J);
void jsB_initfunction(js_State *J);
void jsB_initboolean(js_State *J);
void jsB_initnumber(js_State *J);
void jsB_initstring(js_State *J);
#endif
+15
View File
@@ -0,0 +1,15 @@
#include "js.h"
#include "jsobject.h"
#include "jsrun.h"
#include "jsstate.h"
static int jsB_Array(js_State *J, int n) { return 0; }
void jsB_initarray(js_State *J)
{
J->Array_prototype = jsR_newobject(J, JS_COBJECT, NULL);
js_newcfunction(J, jsB_Array);
js_pushobject(J, J->Array_prototype);
js_setproperty(J, -2, "prototype");
js_setglobal(J, "Array");
}
+15
View File
@@ -0,0 +1,15 @@
#include "js.h"
#include "jsobject.h"
#include "jsrun.h"
#include "jsstate.h"
static int jsB_Boolean(js_State *J, int n) { return 0; }
void jsB_initboolean(js_State *J)
{
J->Boolean_prototype = jsR_newobject(J, JS_COBJECT, NULL);
js_newcfunction(J, jsB_Boolean);
js_pushobject(J, J->Boolean_prototype);
js_setproperty(J, -2, "prototype");
js_setglobal(J, "Boolean");
}
+15
View File
@@ -0,0 +1,15 @@
#include "js.h"
#include "jsobject.h"
#include "jsrun.h"
#include "jsstate.h"
static int jsB_Function(js_State *J, int n) { return 0; }
void jsB_initfunction(js_State *J)
{
J->Function_prototype = jsR_newobject(J, JS_COBJECT, NULL);
js_newcfunction(J, jsB_Function);
js_pushobject(J, J->Function_prototype);
js_setproperty(J, -2, "prototype");
js_setglobal(J, "Function");
}
+105
View File
@@ -0,0 +1,105 @@
#include "js.h"
#include "jsobject.h"
#include "jsrun.h"
#include "jsstate.h"
static int jsB_new_Number(js_State *J, int n)
{
js_pushobject(J, jsR_newnumber(J, n > 0 ? js_tonumber(J, 0) : 0));
return 1;
}
static int jsB_Number(js_State *J, int n)
{
js_pushnumber(J, n > 0 ? js_tonumber(J, 1) : 0);
return 1;
}
static int jsB_Number_p_valueOf(js_State *J, int n)
{
js_Object *T = js_toobject(J, 0);
if (T->type != JS_CNUMBER) jsR_error(J, "TypeError");
js_pushnumber(J, T->primitive.number);
return 1;
}
static int jsB_Number_p_toString(js_State *J, int n)
{
js_Object *T = js_toobject(J, 0);
if (T->type != JS_CNUMBER) jsR_error(J, "TypeError");
js_pushliteral(J, jsR_numbertostring(J, T->primitive.number));
return 1;
}
static int jsB_Number_p_toFixed(js_State *J, int n)
{
char buf[40];
js_Object *T = js_toobject(J, 0);
int width = js_tonumber(J, 1);
if (T->type != JS_CNUMBER) jsR_error(J, "TypeError");
sprintf(buf, "%*f", width, T->primitive.number);
js_pushstring(J, buf);
return 1;
}
static int jsB_Number_p_toExponential(js_State *J, int n)
{
char buf[40];
js_Object *T = js_toobject(J, 0);
int width = js_tonumber(J, 1);
if (T->type != JS_CNUMBER) jsR_error(J, "TypeError");
sprintf(buf, "%*e", width, T->primitive.number);
js_pushstring(J, buf);
return 1;
}
static int jsB_Number_p_toPrecision(js_State *J, int n)
{
char buf[40];
js_Object *T = js_toobject(J, 0);
int width = js_tonumber(J, 1);
if (T->type != JS_CNUMBER) jsR_error(J, "TypeError");
sprintf(buf, "%*g", width, T->primitive.number);
js_pushstring(J, buf);
return 1;
}
void jsB_initnumber(js_State *J)
{
J->Number_prototype = jsR_newobject(J, JS_CNUMBER, J->Object_prototype);
J->Number_prototype->primitive.number = 0;
js_pushobject(J, jsR_newcconstructor(J, jsB_Number, jsB_new_Number));
{
js_pushobject(J, J->Number_prototype);
{
js_copy(J, -2);
js_setproperty(J, -2, "constructor");
js_newcfunction(J, jsB_Number_p_valueOf);
js_setproperty(J, -2, "valueOf");
js_newcfunction(J, jsB_Number_p_toString);
js_dup(J);
js_setproperty(J, -3, "toString");
js_setproperty(J, -2, "toLocaleString");
js_newcfunction(J, jsB_Number_p_toFixed);
js_setproperty(J, -2, "toFixed");
js_newcfunction(J, jsB_Number_p_toExponential);
js_setproperty(J, -2, "toExponential");
js_newcfunction(J, jsB_Number_p_toPrecision);
js_setproperty(J, -2, "toPrecision");
}
js_setproperty(J, -2, "prototype");
js_pushnumber(J, DBL_MAX);
js_setproperty(J, -2, "MAX_VALUE");
js_pushnumber(J, DBL_MIN);
js_setproperty(J, -2, "MIN_VALUE");
js_pushnumber(J, NAN);
js_setproperty(J, -2, "NaN");
js_pushnumber(J, -INFINITY);
js_setproperty(J, -2, "NEGATIVE_INFINITY");
js_pushnumber(J, INFINITY);
js_setproperty(J, -2, "POSITIVE_INFINITY");
}
js_setglobal(J, "Number");
}
+109
View File
@@ -0,0 +1,109 @@
#include "js.h"
#include "jsobject.h"
#include "jsrun.h"
#include "jsstate.h"
static int jsB_new_Object(js_State *J, int n) {
if (n == 0 || js_isundefined(J, 0) || js_isnull(J, 0))
js_newobject(J);
else
js_pushobject(J, js_toobject(J, 0));
return 1;
}
static int jsB_Object(js_State *J, int n) {
if (n == 0 || js_isundefined(J, 1) || js_isnull(J, 1))
js_newobject(J);
else
js_pushobject(J, js_toobject(J, 1));
return 1;
}
static int jsB_Object_p_toString(js_State *J, int n)
{
js_Object *T = js_toobject(J, 0);
switch (T->type) {
case JS_COBJECT: js_pushliteral(J, "[object Object]"); break;
case JS_CARRAY: js_pushliteral(J, "[object Array]"); break;
case JS_CFUNCTION: js_pushliteral(J, "[object Function]"); break;
case JS_CSCRIPT: js_pushliteral(J, "[object Function]"); break;
case JS_CCFUNCTION: js_pushliteral(J, "[object Function]"); break;
case JS_CERROR: js_pushliteral(J, "[object Error]"); break;
case JS_CBOOLEAN: js_pushliteral(J, "[object Boolean]"); break;
case JS_CNUMBER: js_pushliteral(J, "[object Number]"); break;
case JS_CSTRING: js_pushliteral(J, "[object String]"); break;
case JS_CREGEXP: js_pushliteral(J, "[object RegExp]"); break;
case JS_CDATE: js_pushliteral(J, "[object Date]"); break;
case JS_CMATH: js_pushliteral(J, "[object Math]"); break;
default: return 0;
}
return 1;
}
static int jsB_Object_p_valueOf(js_State *J, int n)
{
/* return the 'this' object */
return 1;
}
static int jsB_Object_p_hasOwnProperty(js_State *J, int n)
{
js_Object *T = js_toobject(J, 0);
const char *name = js_tostring(J, 1);
js_Property *ref = jsR_getownproperty(J, T, name);
js_pushboolean(J, ref != NULL);
return 1;
}
static int jsB_Object_p_isPrototypeOf(js_State *J, int n)
{
js_Object *T = js_toobject(J, 0);
if (js_isobject(J, 1)) {
js_Object *V = js_toobject(J, 1);
do {
V = V->prototype;
if (V == T) {
js_pushboolean(J, 1);
return 1;
}
} while (V);
}
js_pushboolean(J, 0);
return 1;
}
static int jsB_Object_p_propertyIsEnumerable(js_State *J, int n)
{
js_Object *T = js_toobject(J, 0);
const char *name = js_tostring(J, 1);
js_Property *ref = jsR_getownproperty(J, T, name);
js_pushboolean(J, ref && (ref->flags & JS_PENUMERABLE));
return 1;
}
void jsB_initobject(js_State *J)
{
J->Object_prototype = jsR_newobject(J, JS_COBJECT, NULL);
js_pushobject(J, jsR_newcconstructor(J, jsB_Object, jsB_new_Object));
{
js_pushobject(J, J->Object_prototype);
{
js_copy(J, -2);
js_setproperty(J, -2, "constructor");
js_newcfunction(J, jsB_Object_p_toString);
js_dup(J);
js_setproperty(J, -3, "toString");
js_setproperty(J, -2, "toLocaleString");
js_newcfunction(J, jsB_Object_p_valueOf);
js_setproperty(J, -2, "valueOf");
js_newcfunction(J, jsB_Object_p_hasOwnProperty);
js_setproperty(J, -2, "hasOwnProperty");
js_newcfunction(J, jsB_Object_p_isPrototypeOf);
js_setproperty(J, -2, "isPrototypeOf");
js_newcfunction(J, jsB_Object_p_propertyIsEnumerable);
js_setproperty(J, -2, "propertyIsEnumerable");
}
js_setproperty(J, -2, "prototype");
}
js_setglobal(J, "Object");
}
+15
View File
@@ -0,0 +1,15 @@
#include "js.h"
#include "jsobject.h"
#include "jsrun.h"
#include "jsstate.h"
static int jsB_String(js_State *J, int n) { return 0; }
void jsB_initstring(js_State *J)
{
J->String_prototype = jsR_newobject(J, JS_COBJECT, NULL);
js_newcfunction(J, jsB_String);
js_pushobject(J, J->String_prototype);
js_setproperty(J, -2, "prototype");
js_setglobal(J, "String");
}
+1 -78
View File
@@ -29,8 +29,6 @@ static int jsB_eval(js_State *J, int argc)
if (!js_isstring(J, -1))
return 1;
// FIXME: return value if eval string is an expression
s = js_tostring(J, -1);
if (jsR_loadscript(J, "(eval)", s))
jsR_error(J, "SyntaxError (eval)");
@@ -40,81 +38,6 @@ static int jsB_eval(js_State *J, int argc)
return 1;
}
static int jsB_Object(js_State *J, int n) {
if (n == 0 || js_isundefined(J, 1) || js_isnull(J, 1))
js_newobject(J);
else
js_pushobject(J, js_toobject(J, 1));
return 1;
}
static int jsB_new_Object(js_State *J, int n) {
if (n == 0 || js_isundefined(J, 0) || js_isnull(J, 0))
js_newobject(J);
else
js_pushobject(J, js_toobject(J, 0));
return 1;
}
static int jsB_Array(js_State *J, int n) { return 0; }
static int jsB_Function(js_State *J, int n) { return 0; }
static int jsB_Boolean(js_State *J, int n) { return 0; }
static int jsB_Number(js_State *J, int n) { return 0; }
static int jsB_String(js_State *J, int n) { return 0; }
static void jsB_initobject(js_State *J)
{
J->Object_prototype = jsR_newobject(J, JS_COBJECT, NULL);
js_newcconstructor(J, jsB_Object, jsB_new_Object);
js_pushobject(J, J->Object_prototype);
js_setproperty(J, -2, "prototype");
js_setglobal(J, "Object");
}
static void jsB_initarray(js_State *J)
{
J->Array_prototype = jsR_newobject(J, JS_COBJECT, NULL);
js_newcfunction(J, jsB_Array);
js_pushobject(J, J->Array_prototype);
js_setproperty(J, -2, "prototype");
js_setglobal(J, "Array");
}
static void jsB_initfunction(js_State *J)
{
J->Function_prototype = jsR_newobject(J, JS_COBJECT, NULL);
js_newcfunction(J, jsB_Function);
js_pushobject(J, J->Function_prototype);
js_setproperty(J, -2, "prototype");
js_setglobal(J, "Function");
}
static void jsB_initboolean(js_State *J)
{
J->Boolean_prototype = jsR_newobject(J, JS_COBJECT, NULL);
js_newcfunction(J, jsB_Boolean);
js_pushobject(J, J->Boolean_prototype);
js_setproperty(J, -2, "prototype");
js_setglobal(J, "Boolean");
}
static void jsB_initnumber(js_State *J)
{
J->Number_prototype = jsR_newobject(J, JS_COBJECT, NULL);
js_newcfunction(J, jsB_Number);
js_pushobject(J, J->Number_prototype);
js_setproperty(J, -2, "prototype");
js_setglobal(J, "Number");
}
static void jsB_initstring(js_State *J)
{
J->String_prototype = jsR_newobject(J, JS_COBJECT, NULL);
js_newcfunction(J, jsB_String);
js_pushobject(J, J->String_prototype);
js_setproperty(J, -2, "prototype");
js_setglobal(J, "String");
}
static int jsB_parseInt(js_State *J, int argc)
{
const char *s = js_tostring(J, 1);
@@ -126,7 +49,7 @@ static int jsB_parseInt(js_State *J, int argc)
static int jsB_parseFloat(js_State *J, int argc)
{
const char *s = js_tostring(J, 1);
js_pushnumber(J, strtod(s, NULL));
js_pushnumber(J, jsR_stringtonumber(J, s));
return 1;
}
+7 -16
View File
@@ -21,15 +21,15 @@ static js_Object *jsR_newscript(js_State *J, js_Function *function)
static js_Object *jsR_newcfunction(js_State *J, js_CFunction cfunction)
{
js_Object *obj = jsR_newobject(J, JS_CCFUNCTION, NULL);
js_Object *obj = jsR_newobject(J, JS_CCFUNCTION, J->Function_prototype);
obj->cfunction = cfunction;
obj->cconstructor = NULL;
return obj;
}
static js_Object *jsR_newcconstructor(js_State *J, js_CFunction cfunction, js_CFunction cconstructor)
js_Object *jsR_newcconstructor(js_State *J, js_CFunction cfunction, js_CFunction cconstructor)
{
js_Object *obj = jsR_newobject(J, JS_CCFUNCTION, NULL);
js_Object *obj = jsR_newobject(J, JS_CCFUNCTION, J->Function_prototype);
obj->cfunction = cfunction;
obj->cconstructor = cconstructor;
return obj;
@@ -85,19 +85,10 @@ void js_newscript(js_State *J, js_Function *F)
void js_newcfunction(js_State *J, js_CFunction fun)
{
js_pushobject(J, jsR_newcfunction(J, fun));
// TODO: length property?
js_newobject(J);
js_copy(J, -2);
js_setproperty(J, -2, "constructor");
js_setproperty(J, -2, "prototype");
}
void js_newcconstructor(js_State *J, js_CFunction fun, js_CFunction con)
{
js_pushobject(J, jsR_newcconstructor(J, fun, con));
// TODO: length property?
js_newobject(J);
js_copy(J, -2);
js_setproperty(J, -2, "constructor");
{
js_copy(J, -2);
js_setproperty(J, -2, "constructor");
}
js_setproperty(J, -2, "prototype");
}
+1 -1
View File
@@ -13,6 +13,7 @@ struct js_Environment
/* private */
void jsB_init(js_State *J);
js_Environment *jsR_newenvironment(js_State *J, js_Object *variables, js_Environment *outer);
js_Object *jsR_newcconstructor(js_State *J, js_CFunction cfunction, js_CFunction cconstructor);
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);
@@ -52,7 +53,6 @@ void js_newarray(js_State *J);
void js_newfunction(js_State *J, js_Function *function, js_Environment *scope);
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);