mirror of
https://github.com/ccxvii/mujs.git
synced 2026-09-22 07:03:36 +08:00
Implement Number and Object classes.
Split built-in functions into one file per class.
This commit is contained in:
@@ -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
@@ -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");
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user