mirror of
https://github.com/ccxvii/mujs.git
synced 2026-02-06 01:41:37 +08:00
Split header into js.h public and jsi.h private. Start cleaning up
private function prefixes.
This commit is contained in:
137
js.h
137
js.h
@@ -1,86 +1,93 @@
|
||||
#ifndef js_h
|
||||
#define js_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <setjmp.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
/* noreturn is a GCC extension */
|
||||
#ifdef __GNUC__
|
||||
#define JS_NORETURN __attribute__((noreturn))
|
||||
#else
|
||||
#ifdef _MSC_VER
|
||||
#define JS_NORETURN __declspec(noreturn)
|
||||
#else
|
||||
#define JS_NORETURN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* GCC can do type checking of printf strings */
|
||||
#ifndef __printflike
|
||||
#if __GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7
|
||||
#define __printflike(fmtarg, firstvararg) \
|
||||
__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
|
||||
#else
|
||||
#define __printflike(fmtarg, firstvararg)
|
||||
#endif
|
||||
#endif
|
||||
#include "jsconf.h"
|
||||
|
||||
typedef struct js_State js_State;
|
||||
typedef int (*js_CFunction)(js_State *J, int argc);
|
||||
|
||||
#define JS_REGEXP_G 1
|
||||
#define JS_REGEXP_I 2
|
||||
#define JS_REGEXP_M 4
|
||||
/* Basic functions */
|
||||
|
||||
js_State *js_newstate(void);
|
||||
void js_close(js_State *J);
|
||||
void js_freestate(js_State *J);
|
||||
|
||||
void js_loadstring(js_State *J, const char *source);
|
||||
void js_loadfile(js_State *J, const char *filename);
|
||||
int js_dostring(js_State *J, const char *source);
|
||||
int js_dofile(js_State *J, const char *filename);
|
||||
|
||||
void js_gc(js_State *J, int report);
|
||||
|
||||
/* binding API: TODO: move from jsrun.h */
|
||||
|
||||
typedef int (*js_CFunction)(js_State *J, int argc);
|
||||
|
||||
/* private */
|
||||
|
||||
typedef struct js_Ast js_Ast;
|
||||
typedef struct js_Environment js_Environment;
|
||||
typedef struct js_Function js_Function;
|
||||
typedef struct js_Object js_Object;
|
||||
typedef struct js_StringNode js_StringNode;
|
||||
|
||||
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);
|
||||
void jsB_initerror(js_State *J);
|
||||
void jsB_initmath(js_State *J);
|
||||
/* Push a new Error object with the formatted message and throw it */
|
||||
JS_NORETURN void js_error(js_State *J, const char *fmt, ...) JS_PRINTFLIKE(2,3);
|
||||
|
||||
/* Property attribute flags */
|
||||
enum {
|
||||
JS_READONLY = 1,
|
||||
JS_DONTENUM = 2,
|
||||
JS_DONTDELETE = 4,
|
||||
};
|
||||
|
||||
JS_NORETURN void js_throw(js_State *J);
|
||||
JS_NORETURN void js_error(js_State *J, const char *fmt, ...) __printflike(2,3);
|
||||
|
||||
JS_NORETURN void jsR_throwError(js_State *J, const char *message);
|
||||
JS_NORETURN void jsR_throwEvalError(js_State *J, const char *message);
|
||||
JS_NORETURN void jsR_throwRangeError(js_State *J, const char *message);
|
||||
JS_NORETURN void jsR_throwReferenceError(js_State *J, const char *message);
|
||||
JS_NORETURN void jsR_throwSyntaxError(js_State *J, const char *message);
|
||||
JS_NORETURN void jsR_throwTypeError(js_State *J, const char *message);
|
||||
JS_NORETURN void jsR_throwURIError(js_State *J, const char *message);
|
||||
void js_loadstring(js_State *J, const char *filename, const char *source);
|
||||
void js_loadfile(js_State *J, const char *filename);
|
||||
|
||||
void js_call(js_State *J, int n);
|
||||
void js_construct(js_State *J, int n);
|
||||
|
||||
void js_getglobal(js_State *J, const char *name);
|
||||
void js_setglobal(js_State *J, const char *name);
|
||||
|
||||
void js_getownproperty(js_State *J, int idx, const char *name);
|
||||
void js_getproperty(js_State *J, int idx, const char *name);
|
||||
void js_setproperty(js_State *J, int idx, const char *name);
|
||||
void js_cfgproperty(js_State *J, int idx, const char *name, int atts);
|
||||
void js_delproperty(js_State *J, int idx, const char *name);
|
||||
int js_nextproperty(js_State *J, int idx);
|
||||
|
||||
void js_pushglobal(js_State *J);
|
||||
void js_pushundefined(js_State *J);
|
||||
void js_pushnull(js_State *J);
|
||||
void js_pushboolean(js_State *J, int v);
|
||||
void js_pushnumber(js_State *J, double v);
|
||||
void js_pushstring(js_State *J, const char *v);
|
||||
void js_pushliteral(js_State *J, const char *v);
|
||||
|
||||
void js_newobject(js_State *J);
|
||||
void js_newarray(js_State *J);
|
||||
void js_newcfunction(js_State *J, js_CFunction fun, int length);
|
||||
|
||||
int js_isundefined(js_State *J, int idx);
|
||||
int js_isnull(js_State *J, int idx);
|
||||
int js_isboolean(js_State *J, int idx);
|
||||
int js_isnumber(js_State *J, int idx);
|
||||
int js_isstring(js_State *J, int idx);
|
||||
int js_isprimitive(js_State *J, int idx);
|
||||
int js_isobject(js_State *J, int idx);
|
||||
int js_iscallable(js_State *J, int idx);
|
||||
|
||||
int js_toboolean(js_State *J, int idx);
|
||||
double js_tonumber(js_State *J, int idx);
|
||||
const char *js_tostring(js_State *J, int idx);
|
||||
|
||||
double js_tointeger(js_State *J, int idx);
|
||||
int js_toint32(js_State *J, int idx);
|
||||
unsigned int js_touint32(js_State *J, int idx);
|
||||
short js_toint16(js_State *J, int idx);
|
||||
unsigned short js_touint16(js_State *J, int idx);
|
||||
|
||||
int js_gettop(js_State *J);
|
||||
void js_settop(js_State *J, int idx);
|
||||
void js_pop(js_State *J, int n);
|
||||
void js_copy(js_State *J, int idx);
|
||||
void js_remove(js_State *J, int idx);
|
||||
void js_insert(js_State *J, int idx);
|
||||
void js_replace(js_State* J, int idx);
|
||||
|
||||
void js_concat(js_State *J);
|
||||
int js_compare(js_State *J);
|
||||
int js_equal(js_State *J);
|
||||
int js_strictequal(js_State *J);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jsobject.h"
|
||||
#include "jsrun.h"
|
||||
#include "jsstate.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
static int jsB_Array(js_State *J, int n) { return 0; }
|
||||
static int jsB_new_Array(js_State *J, int n) { return 0; }
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jsobject.h"
|
||||
#include "jsrun.h"
|
||||
#include "jsstate.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
static int jsB_new_Boolean(js_State *J, int n)
|
||||
{
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jsobject.h"
|
||||
#include "jsrun.h"
|
||||
#include "jsstate.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
static int Ep_toString(js_State *J, int n)
|
||||
{
|
||||
js_getproperty(J, 0, "name");
|
||||
js_pushliteral(J, ": ");
|
||||
jsR_concat(J);
|
||||
js_concat(J);
|
||||
js_getproperty(J, 0, "message");
|
||||
jsR_concat(J);
|
||||
js_concat(J);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jscompile.h"
|
||||
#include "jsobject.h"
|
||||
#include "jsrun.h"
|
||||
#include "jsstate.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
static int jsB_new_Function(js_State *J, int n) { return 0; }
|
||||
static int jsB_Function(js_State *J, int n) { return 0; }
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jsobject.h"
|
||||
#include "jsrun.h"
|
||||
#include "jsstate.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
static int Math_abs(js_State *J, int nargs) {
|
||||
return js_pushnumber(J, abs(js_tonumber(J, 1))), 1;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jsobject.h"
|
||||
#include "jsrun.h"
|
||||
#include "jsstate.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
static int jsB_new_Number(js_State *J, int n)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jsobject.h"
|
||||
#include "jsrun.h"
|
||||
#include "jsstate.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
static int jsB_new_Object(js_State *J, int n)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jsobject.h"
|
||||
#include "jsrun.h"
|
||||
#include "jsstate.h"
|
||||
#include "jsbuiltin.h"
|
||||
#include "jsutf.h"
|
||||
|
||||
static int jsB_new_String(js_State *J, int n)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jsobject.h"
|
||||
#include "jsrun.h"
|
||||
#include "jsstate.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
static int jsB_print(js_State *J, int argc)
|
||||
{
|
||||
@@ -26,7 +25,7 @@ static int jsB_eval(js_State *J, int argc)
|
||||
{
|
||||
if (!js_isstring(J, -1))
|
||||
return 1;
|
||||
jsR_loadscript(J, "(eval)", js_tostring(J, -1));
|
||||
js_loadstring(J, "(eval)", js_tostring(J, -1));
|
||||
js_copy(J, 0);
|
||||
js_call(J, 0);
|
||||
return 1;
|
||||
|
||||
18
jsbuiltin.h
Normal file
18
jsbuiltin.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef js_builtin_h
|
||||
#define js_builtin_h
|
||||
|
||||
void jsB_init(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);
|
||||
void jsB_initerror(js_State *J);
|
||||
void jsB_initmath(js_State *J);
|
||||
|
||||
void jsB_propf(js_State *J, const char *name, js_CFunction cfun, int n);
|
||||
void jsB_propn(js_State *J, const char *name, double number);
|
||||
void jsB_props(js_State *J, const char *name, const char *string);
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jsparse.h"
|
||||
#include "jscompile.h"
|
||||
#include "jsstate.h"
|
||||
|
||||
#define cexp js_cexp /* collision with math.h */
|
||||
|
||||
|
||||
32
jsconf.h
Normal file
32
jsconf.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef js_conf_h
|
||||
#define js_conf_h
|
||||
|
||||
#define JS_STACKSIZE 256 /* value stack size */
|
||||
#define JS_MINSTACK 20 /* at least this much available when entering a function */
|
||||
#define JS_TRYLIMIT 64 /* exception stack size */
|
||||
#define JS_GCLIMIT 10000 /* run gc cycle every N allocations */
|
||||
|
||||
/* noreturn is a GCC extension */
|
||||
#ifdef __GNUC__
|
||||
#define JS_NORETURN __attribute__((noreturn))
|
||||
#else
|
||||
#ifdef _MSC_VER
|
||||
#define JS_NORETURN __declspec(noreturn)
|
||||
#else
|
||||
#define JS_NORETURN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* GCC can do type checking of printf strings */
|
||||
#ifdef __printflike
|
||||
#define JS_PRINTFLIKE __printflike
|
||||
#else
|
||||
#if __GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7
|
||||
#define JS_PRINTFLIKE(fmtarg, firstvararg) \
|
||||
__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
|
||||
#else
|
||||
#define JS_PRINTFLIKE(fmtarg, firstvararg)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
2
jsdump.c
2
jsdump.c
@@ -1,4 +1,4 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jsparse.h"
|
||||
#include "jscompile.h"
|
||||
#include "jsobject.h"
|
||||
|
||||
10
jsgc.c
10
jsgc.c
@@ -1,8 +1,7 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jscompile.h"
|
||||
#include "jsobject.h"
|
||||
#include "jsrun.h"
|
||||
#include "jsstate.h"
|
||||
|
||||
static void jsG_markobject(js_State *J, int mark, js_Object *obj);
|
||||
|
||||
@@ -147,7 +146,7 @@ void js_gc(js_State *J, int report)
|
||||
genv, nenv, gfun, nfun, gobj, nobj);
|
||||
}
|
||||
|
||||
void js_close(js_State *J)
|
||||
void js_freestate(js_State *J)
|
||||
{
|
||||
js_Function *fun, *nextfun;
|
||||
js_Object *obj, *nextobj;
|
||||
@@ -160,8 +159,9 @@ void js_close(js_State *J)
|
||||
for (obj = J->gcobj; obj; obj = nextobj)
|
||||
nextobj = obj->gcnext, jsG_freeobject(J, obj);
|
||||
|
||||
js_freestrings(J);
|
||||
jsS_freestrings(J);
|
||||
|
||||
free(J->buf.text);
|
||||
free(J->lexbuf.text);
|
||||
free(J->stack);
|
||||
free(J);
|
||||
}
|
||||
|
||||
135
jsi.h
Normal file
135
jsi.h
Normal file
@@ -0,0 +1,135 @@
|
||||
#ifndef jsi_h
|
||||
#define jsi_h
|
||||
|
||||
#include "js.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <setjmp.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
enum { JS_REGEXP_G = 1, JS_REGEXP_I = 2, JS_REGEXP_M = 4 }; /* RegExp flags */
|
||||
|
||||
enum { JS_HNONE, JS_HNUMBER, JS_HSTRING }; /* Hint to ToPrimitive() */
|
||||
|
||||
typedef struct js_Value js_Value;
|
||||
typedef struct js_Object js_Object;
|
||||
|
||||
typedef struct js_Ast js_Ast;
|
||||
typedef struct js_Function js_Function;
|
||||
typedef struct js_Environment js_Environment;
|
||||
|
||||
typedef struct js_StringNode js_StringNode;
|
||||
void jsS_dumpstrings(js_State *J);
|
||||
void jsS_freestrings(js_State *J);
|
||||
|
||||
JS_NORETURN void jsR_throwError(js_State *J, const char *message);
|
||||
JS_NORETURN void jsR_throwEvalError(js_State *J, const char *message);
|
||||
JS_NORETURN void jsR_throwRangeError(js_State *J, const char *message);
|
||||
JS_NORETURN void jsR_throwReferenceError(js_State *J, const char *message);
|
||||
JS_NORETURN void jsR_throwSyntaxError(js_State *J, const char *message);
|
||||
JS_NORETURN void jsR_throwTypeError(js_State *J, const char *message);
|
||||
JS_NORETURN void jsR_throwURIError(js_State *J, const char *message);
|
||||
|
||||
js_Object *jsR_newcconstructor(js_State *J, js_CFunction cfunction, js_CFunction cconstructor);
|
||||
|
||||
const char *jsR_stringfromnumber(js_State *J, double number);
|
||||
double jsR_numberfromstring(js_State *J, const char *string);
|
||||
|
||||
void js_newfunction(js_State *J, js_Function *function, js_Environment *scope);
|
||||
void js_newscript(js_State *J, js_Function *function);
|
||||
void js_dup(js_State *J);
|
||||
void js_rot(js_State *J, int n);
|
||||
void js_rot2(js_State *J);
|
||||
void js_rot3(js_State *J);
|
||||
|
||||
/* Exception handling */
|
||||
|
||||
typedef struct js_Jumpbuf js_Jumpbuf;
|
||||
|
||||
struct js_Jumpbuf
|
||||
{
|
||||
jmp_buf buf;
|
||||
js_Environment *E;
|
||||
int top, bot;
|
||||
short *pc;
|
||||
};
|
||||
|
||||
void js_savetry(js_State *J, short *pc);
|
||||
|
||||
#define js_trypc(J, PC) \
|
||||
(js_savetry(J, PC), setjmp(J->trybuf[J->trylen++].buf))
|
||||
|
||||
#define js_try(J) \
|
||||
(js_savetry(J, NULL), setjmp(J->trybuf[J->trylen++].buf))
|
||||
|
||||
#define js_endtry(J) \
|
||||
(--J->trylen)
|
||||
|
||||
/* State struct */
|
||||
|
||||
struct js_State
|
||||
{
|
||||
js_StringNode *strings;
|
||||
|
||||
/* parser input source */
|
||||
const char *filename;
|
||||
const char *source;
|
||||
int line;
|
||||
|
||||
/* lexer state */
|
||||
struct { char *text; size_t len, cap; } lexbuf;
|
||||
int lexline;
|
||||
int lexchar;
|
||||
int lasttoken;
|
||||
int newline;
|
||||
|
||||
/* parser state */
|
||||
int lookahead;
|
||||
const char *text;
|
||||
double number;
|
||||
js_Ast *gcast; /* list of allocated nodes to free after parsing */
|
||||
|
||||
/* compiler state */
|
||||
int strict;
|
||||
|
||||
/* runtime environment */
|
||||
js_Object *Object_prototype;
|
||||
js_Object *Array_prototype;
|
||||
js_Object *Function_prototype;
|
||||
js_Object *Boolean_prototype;
|
||||
js_Object *Number_prototype;
|
||||
js_Object *String_prototype;
|
||||
|
||||
js_Object *Error_prototype;
|
||||
js_Object *EvalError_prototype;
|
||||
js_Object *RangeError_prototype;
|
||||
js_Object *ReferenceError_prototype;
|
||||
js_Object *SyntaxError_prototype;
|
||||
js_Object *TypeError_prototype;
|
||||
js_Object *URIError_prototype;
|
||||
|
||||
js_Object *G;
|
||||
js_Environment *E;
|
||||
|
||||
/* execution stack */
|
||||
int top, bot;
|
||||
js_Value *stack;
|
||||
|
||||
/* garbage collector list */
|
||||
int gcmark;
|
||||
int gccounter;
|
||||
js_Environment *gcenv;
|
||||
js_Function *gcfun;
|
||||
js_Object *gcobj;
|
||||
|
||||
/* exception stack */
|
||||
int trylen;
|
||||
js_Jumpbuf trybuf[JS_TRYLIMIT];
|
||||
};
|
||||
|
||||
#endif
|
||||
19
jsintern.c
19
jsintern.c
@@ -1,5 +1,4 @@
|
||||
#include "js.h"
|
||||
#include "jsstate.h"
|
||||
#include "jsi.h"
|
||||
|
||||
/* Use an AA-tree to quickly look up interned strings. */
|
||||
|
||||
@@ -66,26 +65,26 @@ static js_StringNode *insert(js_StringNode *node, const char *string, const char
|
||||
return newstringnode(string, result);
|
||||
}
|
||||
|
||||
static void printstringnode(js_StringNode *node, int level)
|
||||
static void dumpstringnode(js_StringNode *node, int level)
|
||||
{
|
||||
int i;
|
||||
if (node->left != &sentinel)
|
||||
printstringnode(node->left, level + 1);
|
||||
dumpstringnode(node->left, level + 1);
|
||||
printf("%d: ", node->level);
|
||||
for (i = 0; i < level; ++i)
|
||||
putchar('\t');
|
||||
printf("'%s'\n", node->string);
|
||||
if (node->right != &sentinel)
|
||||
printstringnode(node->right, level + 1);
|
||||
dumpstringnode(node->right, level + 1);
|
||||
}
|
||||
|
||||
void js_printstrings(js_State *J)
|
||||
void jsS_dumpstrings(js_State *J)
|
||||
{
|
||||
js_StringNode *root = J->strings;
|
||||
printf("--- string dump ---\n");
|
||||
printf("interned strings {\n");
|
||||
if (root && root != &sentinel)
|
||||
printstringnode(root, 0);
|
||||
printf("---\n");
|
||||
dumpstringnode(root, 1);
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
static void js_freestringnode(js_State *J, js_StringNode *node)
|
||||
@@ -95,7 +94,7 @@ static void js_freestringnode(js_State *J, js_StringNode *node)
|
||||
free(node);
|
||||
}
|
||||
|
||||
void js_freestrings(js_State *J)
|
||||
void jsS_freestrings(js_State *J)
|
||||
{
|
||||
if (J->strings && J->strings != &sentinel)
|
||||
js_freestringnode(J, J->strings);
|
||||
|
||||
79
jslex.c
79
jslex.c
@@ -1,10 +1,27 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jslex.h"
|
||||
#include "jsstate.h"
|
||||
#include "jsutf.h"
|
||||
|
||||
#define nelem(a) (sizeof (a) / sizeof (a)[0])
|
||||
|
||||
JS_NORETURN static int jsY_error(js_State *J, const char *fmt, ...) JS_PRINTFLIKE(2,3);
|
||||
|
||||
static int jsY_error(js_State *J, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[512];
|
||||
char msgbuf[256];
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(msgbuf, 256, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
snprintf(buf, 256, "%s:%d: ", J->filename, J->lexline);
|
||||
strcat(buf, msgbuf);
|
||||
|
||||
jsR_throwSyntaxError(J, buf);
|
||||
}
|
||||
|
||||
static const char *tokenstring[] = {
|
||||
"(end-of-file)",
|
||||
"'\\x01'", "'\\x02'", "'\\x03'", "'\\x04'", "'\\x05'", "'\\x06'", "'\\x07'",
|
||||
@@ -48,7 +65,7 @@ static const char *tokenstring[] = {
|
||||
"'void'", "'while'", "'with'",
|
||||
};
|
||||
|
||||
const char *jsP_tokenstring(int token)
|
||||
const char *jsY_tokenstring(int token)
|
||||
{
|
||||
if (token >= 0 && token < nelem(tokenstring))
|
||||
if (tokenstring[token])
|
||||
@@ -135,7 +152,7 @@ static inline int tohex(int c)
|
||||
#define PEEK (J->lexchar)
|
||||
#define NEXT() next(J)
|
||||
#define ACCEPT(x) (PEEK == x ? (NEXT(), 1) : 0)
|
||||
#define EXPECT(x) (ACCEPT(x) || (jsP_error(J, "expected '%c'", x), 0))
|
||||
#define EXPECT(x) (ACCEPT(x) || (jsY_error(J, "expected '%c'", x), 0))
|
||||
|
||||
static void next(js_State *J)
|
||||
{
|
||||
@@ -164,33 +181,33 @@ static void unescape(js_State *J)
|
||||
return;
|
||||
}
|
||||
error:
|
||||
jsP_error(J, "unexpected escape sequence");
|
||||
jsY_error(J, "unexpected escape sequence");
|
||||
}
|
||||
}
|
||||
|
||||
static void textinit(js_State *J)
|
||||
{
|
||||
if (!J->buf.text) {
|
||||
J->buf.cap = 4096;
|
||||
J->buf.text = malloc(J->buf.cap);
|
||||
if (!J->lexbuf.text) {
|
||||
J->lexbuf.cap = 4096;
|
||||
J->lexbuf.text = malloc(J->lexbuf.cap);
|
||||
}
|
||||
J->buf.len = 0;
|
||||
J->lexbuf.len = 0;
|
||||
}
|
||||
|
||||
static inline void textpush(js_State *J, Rune c)
|
||||
{
|
||||
int n = runelen(c);
|
||||
if (J->buf.len + n > J->buf.cap) {
|
||||
J->buf.cap = J->buf.cap * 2;
|
||||
J->buf.text = realloc(J->buf.text, J->buf.cap);
|
||||
if (J->lexbuf.len + n > J->lexbuf.cap) {
|
||||
J->lexbuf.cap = J->lexbuf.cap * 2;
|
||||
J->lexbuf.text = realloc(J->lexbuf.text, J->lexbuf.cap);
|
||||
}
|
||||
J->buf.len += runetochar(J->buf.text + J->buf.len, &c);
|
||||
J->lexbuf.len += runetochar(J->lexbuf.text + J->lexbuf.len, &c);
|
||||
}
|
||||
|
||||
static inline char *textend(js_State *J)
|
||||
{
|
||||
textpush(J, 0);
|
||||
return J->buf.text;
|
||||
return J->lexbuf.text;
|
||||
}
|
||||
|
||||
static inline void lexlinecomment(js_State *J)
|
||||
@@ -218,7 +235,7 @@ static inline double lexhex(js_State *J)
|
||||
{
|
||||
double n = 0;
|
||||
if (!ishex(PEEK))
|
||||
return jsP_error(J, "malformed hexadecimal number");
|
||||
return jsY_error(J, "malformed hexadecimal number");
|
||||
while (ishex(PEEK)) {
|
||||
n = n * 16 + tohex(PEEK);
|
||||
NEXT();
|
||||
@@ -230,7 +247,7 @@ static inline double lexinteger(js_State *J)
|
||||
{
|
||||
double n = 0;
|
||||
if (!isdec(PEEK))
|
||||
return jsP_error(J, "malformed number");
|
||||
return jsY_error(J, "malformed number");
|
||||
while (isdec(PEEK)) {
|
||||
n = n * 10 + (PEEK - '0');
|
||||
NEXT();
|
||||
@@ -272,7 +289,7 @@ static inline int lexnumber(js_State *J)
|
||||
return TK_NUMBER;
|
||||
}
|
||||
if (isdec(PEEK))
|
||||
return jsP_error(J, "number with leading zero");
|
||||
return jsY_error(J, "number with leading zero");
|
||||
n = 0;
|
||||
if (ACCEPT('.'))
|
||||
n += lexfraction(J);
|
||||
@@ -290,7 +307,7 @@ static inline int lexnumber(js_State *J)
|
||||
}
|
||||
|
||||
if (isidentifierstart(PEEK))
|
||||
return jsP_error(J, "number with letter suffix");
|
||||
return jsY_error(J, "number with letter suffix");
|
||||
|
||||
J->number = n;
|
||||
return TK_NUMBER;
|
||||
@@ -346,10 +363,10 @@ static inline int lexstring(js_State *J)
|
||||
|
||||
while (PEEK != q) {
|
||||
if (PEEK == 0 || PEEK == '\n')
|
||||
return jsP_error(J, "string not terminated");
|
||||
return jsY_error(J, "string not terminated");
|
||||
if (ACCEPT('\\')) {
|
||||
if (lexescape(J))
|
||||
return jsP_error(J, "malformed escape sequence");
|
||||
return jsY_error(J, "malformed escape sequence");
|
||||
} else {
|
||||
textpush(J, PEEK);
|
||||
NEXT();
|
||||
@@ -387,7 +404,6 @@ static int lexregexp(js_State *J)
|
||||
{
|
||||
const char *s;
|
||||
int g, m, i;
|
||||
int c;
|
||||
|
||||
/* already consumed initial '/' */
|
||||
|
||||
@@ -396,11 +412,11 @@ static int lexregexp(js_State *J)
|
||||
/* regexp body */
|
||||
while (PEEK != '/') {
|
||||
if (PEEK == 0 || PEEK == '\n') {
|
||||
return jsP_error(J, "regular expression not terminated");
|
||||
return jsY_error(J, "regular expression not terminated");
|
||||
} else if (ACCEPT('\\')) {
|
||||
textpush(J, '\\');
|
||||
if (PEEK == 0 || PEEK == '\n')
|
||||
return jsP_error(J, "regular expression not terminated");
|
||||
return jsY_error(J, "regular expression not terminated");
|
||||
textpush(J, PEEK);
|
||||
NEXT();
|
||||
} else {
|
||||
@@ -415,16 +431,15 @@ static int lexregexp(js_State *J)
|
||||
/* regexp flags */
|
||||
g = i = m = 0;
|
||||
|
||||
c = PEEK;
|
||||
while (isidentifierpart(PEEK)) {
|
||||
if (ACCEPT('g')) ++g;
|
||||
else if (ACCEPT('i')) ++i;
|
||||
else if (ACCEPT('m')) ++m;
|
||||
else return jsP_error(J, "illegal flag in regular expression: %c", PEEK);
|
||||
else return jsY_error(J, "illegal flag in regular expression: %c", PEEK);
|
||||
}
|
||||
|
||||
if (g > 1 || i > 1 || m > 1)
|
||||
return jsP_error(J, "duplicated flag in regular expression");
|
||||
return jsY_error(J, "duplicated flag in regular expression");
|
||||
|
||||
J->text = js_intern(J, s);
|
||||
J->number = 0;
|
||||
@@ -471,7 +486,7 @@ static int lex(js_State *J)
|
||||
continue;
|
||||
} else if (ACCEPT('*')) {
|
||||
if (lexcomment(J))
|
||||
return jsP_error(J, "multi-line comment not terminated");
|
||||
return jsY_error(J, "multi-line comment not terminated");
|
||||
continue;
|
||||
} else if (isregexpcontext(J->lasttoken)) {
|
||||
return lexregexp(J);
|
||||
@@ -621,16 +636,16 @@ static int lex(js_State *J)
|
||||
|
||||
textend(J);
|
||||
|
||||
return findkeyword(J, J->buf.text);
|
||||
return findkeyword(J, J->lexbuf.text);
|
||||
}
|
||||
|
||||
if (PEEK >= 0x20 && PEEK <= 0x7E)
|
||||
return jsP_error(J, "unexpected character: '%c'", PEEK);
|
||||
return jsP_error(J, "unexpected character: \\u%04X", PEEK);
|
||||
return jsY_error(J, "unexpected character: '%c'", PEEK);
|
||||
return jsY_error(J, "unexpected character: \\u%04X", PEEK);
|
||||
}
|
||||
}
|
||||
|
||||
void jsP_initlex(js_State *J, const char *filename, const char *source)
|
||||
void jsY_initlex(js_State *J, const char *filename, const char *source)
|
||||
{
|
||||
J->filename = filename;
|
||||
J->source = source;
|
||||
@@ -639,7 +654,7 @@ void jsP_initlex(js_State *J, const char *filename, const char *source)
|
||||
next(J); /* load first lookahead character */
|
||||
}
|
||||
|
||||
int jsP_lex(js_State *J)
|
||||
int jsY_lex(js_State *J)
|
||||
{
|
||||
return J->lasttoken = lex(J);
|
||||
}
|
||||
|
||||
9
jslex.h
9
jslex.h
@@ -66,12 +66,9 @@ enum
|
||||
TK_WITH,
|
||||
};
|
||||
|
||||
const char *jsP_tokenstring(int token);
|
||||
const char *jsY_tokenstring(int token);
|
||||
|
||||
void jsP_initlex(js_State *J, const char *filename, const char *source);
|
||||
int jsP_lex(js_State *J);
|
||||
|
||||
JS_NORETURN int jsP_error(js_State *J, const char *fmt, ...);
|
||||
void jsP_warning(js_State *J, const char *fmt, ...);
|
||||
void jsY_initlex(js_State *J, const char *filename, const char *source);
|
||||
int jsY_lex(js_State *J);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jscompile.h"
|
||||
#include "jsobject.h"
|
||||
#include "jsrun.h"
|
||||
#include "jsstate.h"
|
||||
#include "jsutf.h"
|
||||
|
||||
static js_Object *jsR_newfunction(js_State *J, js_Function *function, js_Environment *scope)
|
||||
|
||||
18
jsobject.h
18
jsobject.h
@@ -2,9 +2,8 @@
|
||||
#define js_object_h
|
||||
|
||||
typedef enum js_Type js_Type;
|
||||
typedef struct js_Value js_Value;
|
||||
|
||||
typedef enum js_Class js_Class;
|
||||
|
||||
typedef struct js_Property js_Property;
|
||||
|
||||
enum js_Type {
|
||||
@@ -31,12 +30,6 @@ enum js_Class {
|
||||
JS_CMATH,
|
||||
};
|
||||
|
||||
enum {
|
||||
JS_HNONE,
|
||||
JS_HNUMBER,
|
||||
JS_HSTRING,
|
||||
};
|
||||
|
||||
struct js_Value
|
||||
{
|
||||
js_Type type;
|
||||
@@ -79,6 +72,13 @@ struct js_Property
|
||||
js_Value value;
|
||||
};
|
||||
|
||||
js_Value js_tovalue(js_State *J, int idx);
|
||||
js_Value js_toprimitive(js_State *J, int idx, int hint);
|
||||
js_Object *js_toobject(js_State *J, int idx);
|
||||
|
||||
void js_pushvalue(js_State *J, js_Value v);
|
||||
void js_pushobject(js_State *J, js_Object *v);
|
||||
|
||||
/* jsvalue.c */
|
||||
int jsR_toboolean(js_State *J, const js_Value *v);
|
||||
double jsR_tonumber(js_State *J, const js_Value *v);
|
||||
@@ -105,6 +105,4 @@ js_Object *js_toobject(js_State *J, int idx);
|
||||
void js_dumpobject(js_State *J, js_Object *obj);
|
||||
void js_dumpvalue(js_State *J, js_Value v);
|
||||
|
||||
JS_NORETURN void jsR_error(js_State *J, const char *fmt, ...);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jsparse.h"
|
||||
|
||||
static inline int i32(double d)
|
||||
|
||||
66
jsparse.c
66
jsparse.c
@@ -1,7 +1,6 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jslex.h"
|
||||
#include "jsparse.h"
|
||||
#include "jsstate.h"
|
||||
|
||||
#define nelem(a) (sizeof (a) / sizeof (a)[0])
|
||||
|
||||
@@ -18,7 +17,7 @@
|
||||
#define STM3(x,a,b,c) jsP_newnode(J, STM_ ## x, a, b, c, 0)
|
||||
#define STM4(x,a,b,c,d) jsP_newnode(J, STM_ ## x, a, b, c, d)
|
||||
|
||||
#define TOKSTR jsP_tokenstring(J->lookahead)
|
||||
#define TOKSTR jsY_tokenstring(J->lookahead)
|
||||
|
||||
static js_Ast *expression(js_State *J, int notin);
|
||||
static js_Ast *assignment(js_State *J, int notin);
|
||||
@@ -26,6 +25,34 @@ static js_Ast *memberexp(js_State *J);
|
||||
static js_Ast *statement(js_State *J);
|
||||
static js_Ast *funbody(js_State *J);
|
||||
|
||||
JS_NORETURN static void jsP_error(js_State *J, const char *fmt, ...) JS_PRINTFLIKE(2,3);
|
||||
|
||||
static void jsP_error(js_State *J, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[512];
|
||||
char msgbuf[256];
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(msgbuf, 256, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
snprintf(buf, 256, "%s:%d: ", J->filename, J->lexline);
|
||||
strcat(buf, msgbuf);
|
||||
|
||||
jsR_throwSyntaxError(J, buf);
|
||||
}
|
||||
|
||||
static void jsP_warning(js_State *J, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
fprintf(stderr, "%s:%d: warning: ", J->filename, J->lexline);
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
js_Ast *jsP_newnode(js_State *J, int type, js_Ast *a, js_Ast *b, js_Ast *c, js_Ast *d)
|
||||
{
|
||||
js_Ast *node = malloc(sizeof(js_Ast));
|
||||
@@ -74,7 +101,7 @@ void jsP_freeparse(js_State *J)
|
||||
|
||||
static inline void next(js_State *J)
|
||||
{
|
||||
J->lookahead = jsP_lex(J);
|
||||
J->lookahead = jsY_lex(J);
|
||||
}
|
||||
|
||||
static inline int accept(js_State *J, int t)
|
||||
@@ -90,7 +117,7 @@ static inline void expect(js_State *J, int t)
|
||||
{
|
||||
if (accept(J, t))
|
||||
return;
|
||||
jsP_error(J, "unexpected token: %s (expected %s)", TOKSTR, jsP_tokenstring(t));
|
||||
jsP_error(J, "unexpected token: %s (expected %s)", TOKSTR, jsY_tokenstring(t));
|
||||
}
|
||||
|
||||
static void semicolon(js_State *J)
|
||||
@@ -838,38 +865,11 @@ static js_Ast *funbody(js_State *J)
|
||||
return a;
|
||||
}
|
||||
|
||||
void jsP_warning(js_State *J, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
fprintf(stderr, "%s:%d: warning: ", J->filename, J->lexline);
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
int jsP_error(js_State *J, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[512];
|
||||
char msgbuf[256];
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(msgbuf, 256, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
snprintf(buf, 256, "%s:%d: ", J->filename, J->lexline);
|
||||
strcat(buf, msgbuf);
|
||||
|
||||
jsR_throwSyntaxError(J, buf);
|
||||
}
|
||||
|
||||
js_Ast *jsP_parse(js_State *J, const char *filename, const char *source)
|
||||
{
|
||||
js_Ast *p, *last;
|
||||
|
||||
jsP_initlex(J, filename, source);
|
||||
jsY_initlex(J, filename, source);
|
||||
|
||||
next(J);
|
||||
p = script(J);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#ifndef js_parse_h
|
||||
#define js_parse_h
|
||||
|
||||
enum
|
||||
typedef enum js_AstType js_AstType;
|
||||
|
||||
enum js_AstType
|
||||
{
|
||||
AST_LIST,
|
||||
AST_FUNDEC,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jsobject.h"
|
||||
#include "jsstate.h"
|
||||
|
||||
/*
|
||||
Use an AA-tree to quickly look up properties in objects:
|
||||
|
||||
47
jsrun.c
47
jsrun.c
@@ -1,9 +1,7 @@
|
||||
#include "js.h"
|
||||
#include "jsobject.h"
|
||||
#include "jsparse.h"
|
||||
#include "jsi.h"
|
||||
#include "jscompile.h"
|
||||
#include "jsobject.h"
|
||||
#include "jsrun.h"
|
||||
#include "jsstate.h"
|
||||
|
||||
static void jsR_run(js_State *J, js_Function *F);
|
||||
|
||||
@@ -42,7 +40,7 @@ static inline unsigned int touint32(double n)
|
||||
#define TOP (J->top)
|
||||
#define BOT (J->bot)
|
||||
|
||||
static void js_pushvalue(js_State *J, js_Value v)
|
||||
void js_pushvalue(js_State *J, js_Value v)
|
||||
{
|
||||
STACK[TOP] = v;
|
||||
++TOP;
|
||||
@@ -127,7 +125,7 @@ int js_iscallable(js_State *J, int idx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *js_typeof(js_State *J, int idx)
|
||||
static const char *js_typeof(js_State *J, int idx)
|
||||
{
|
||||
switch (stackidx(J, idx)->type) {
|
||||
case JS_TUNDEFINED: return "undefined";
|
||||
@@ -708,7 +706,7 @@ static void jsR_run(js_State *J, js_Function *F)
|
||||
/* Additive operators */
|
||||
|
||||
case OP_ADD:
|
||||
jsR_concat(J);
|
||||
js_concat(J);
|
||||
break;
|
||||
|
||||
case OP_SUB:
|
||||
@@ -743,19 +741,19 @@ static void jsR_run(js_State *J, js_Function *F)
|
||||
|
||||
/* Relational operators */
|
||||
|
||||
case OP_LT: b = jsR_compare(J); js_pushboolean(J, b < 0); break;
|
||||
case OP_GT: b = jsR_compare(J); js_pushboolean(J, b > 0); break;
|
||||
case OP_LE: b = jsR_compare(J); js_pushboolean(J, b <= 0); break;
|
||||
case OP_GE: b = jsR_compare(J); js_pushboolean(J, b >= 0); break;
|
||||
case OP_LT: b = js_compare(J); js_pushboolean(J, b < 0); break;
|
||||
case OP_GT: b = js_compare(J); js_pushboolean(J, b > 0); break;
|
||||
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
|
||||
|
||||
/* Equality */
|
||||
|
||||
case OP_EQ: b = jsR_equal(J); js_pushboolean(J, b); break;
|
||||
case OP_NE: b = jsR_equal(J); js_pushboolean(J, !b); break;
|
||||
case OP_STRICTEQ: b = jsR_strictequal(J); js_pushboolean(J, b); break;
|
||||
case OP_STRICTNE: b = jsR_strictequal(J); js_pushboolean(J, !b); break;
|
||||
case OP_EQ: b = js_equal(J); js_pushboolean(J, b); break;
|
||||
case OP_NE: b = js_equal(J); js_pushboolean(J, !b); break;
|
||||
case OP_STRICTEQ: b = js_strictequal(J); js_pushboolean(J, b); break;
|
||||
case OP_STRICTNE: b = js_strictequal(J); js_pushboolean(J, !b); break;
|
||||
|
||||
/* Binary bitwise operators */
|
||||
|
||||
@@ -814,22 +812,3 @@ static void jsR_run(js_State *J, js_Function *F)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void jsR_loadscript(js_State *J, const char *filename, const char *source)
|
||||
{
|
||||
js_Ast *P;
|
||||
js_Function *F;
|
||||
|
||||
if (js_try(J)) {
|
||||
jsP_freeparse(J);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
P = jsP_parse(J, filename, source);
|
||||
jsP_optimize(J, P);
|
||||
F = jsC_compile(J, P);
|
||||
jsP_freeparse(J);
|
||||
js_newscript(J, F);
|
||||
|
||||
js_endtry(J);
|
||||
}
|
||||
|
||||
77
jsrun.h
77
jsrun.h
@@ -1,6 +1,8 @@
|
||||
#ifndef js_run_h
|
||||
#define js_run_h
|
||||
|
||||
js_Environment *jsR_newenvironment(js_State *J, js_Object *variables, js_Environment *outer);
|
||||
|
||||
struct js_Environment
|
||||
{
|
||||
js_Environment *outer;
|
||||
@@ -10,79 +12,4 @@ struct js_Environment
|
||||
int gcmark;
|
||||
};
|
||||
|
||||
/* private */
|
||||
void jsB_init(js_State *J);
|
||||
void jsB_propf(js_State *J, const char *name, js_CFunction cfun, int n);
|
||||
void jsB_propn(js_State *J, const char *name, double number);
|
||||
void jsB_props(js_State *J, const char *name, const char *string);
|
||||
|
||||
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);
|
||||
void 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);
|
||||
js_Value js_tovalue(js_State *J, int idx);
|
||||
void jsR_concat(js_State *J);
|
||||
int jsR_compare(js_State *J);
|
||||
int jsR_equal(js_State *J);
|
||||
int jsR_strictequal(js_State *J);
|
||||
|
||||
const char *jsR_stringfromnumber(js_State *J, double number);
|
||||
double jsR_numberfromstring(js_State *J, const char *string);
|
||||
|
||||
/* public */
|
||||
|
||||
void js_call(js_State *J, int n);
|
||||
void js_construct(js_State *J, int n);
|
||||
|
||||
void js_getglobal(js_State *J, const char *name);
|
||||
void js_setglobal(js_State *J, const char *name);
|
||||
void js_getownproperty(js_State *J, int idx, const char *name);
|
||||
void js_getproperty(js_State *J, int idx, const char *name);
|
||||
void js_setproperty(js_State *J, int idx, const char *name);
|
||||
int js_nextproperty(js_State *J, int idx);
|
||||
|
||||
void js_pushglobal(js_State *J);
|
||||
void js_pushundefined(js_State *J);
|
||||
void js_pushnull(js_State *J);
|
||||
void js_pushboolean(js_State *J, int v);
|
||||
void js_pushnumber(js_State *J, double v);
|
||||
void js_pushliteral(js_State *J, const char *v);
|
||||
void js_pushstring(js_State *J, const char *v);
|
||||
|
||||
void js_newobject(js_State *J);
|
||||
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, int length);
|
||||
|
||||
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);
|
||||
int js_isnumber(js_State *J, int idx);
|
||||
int js_isstring(js_State *J, int idx);
|
||||
int js_isprimitive(js_State *J, int idx);
|
||||
int js_isobject(js_State *J, int idx);
|
||||
int js_iscallable(js_State *J, int idx);
|
||||
|
||||
int js_toboolean(js_State *J, int idx);
|
||||
double js_tonumber(js_State *J, int idx);
|
||||
const char *js_tostring(js_State *J, int idx);
|
||||
|
||||
double js_tointeger(js_State *J, int idx);
|
||||
int js_toint32(js_State *J, int idx);
|
||||
unsigned int js_touint32(js_State *J, int idx);
|
||||
short js_toint16(js_State *J, int idx);
|
||||
unsigned short js_touint16(js_State *J, int idx);
|
||||
|
||||
void js_pop(js_State *J, int n);
|
||||
void js_dup(js_State *J);
|
||||
void js_copy(js_State *J, int idx);
|
||||
void js_rot(js_State *J, int n);
|
||||
void js_rot2(js_State *J);
|
||||
void js_rot3(js_State *J);
|
||||
|
||||
#endif
|
||||
|
||||
30
jsstate.c
30
jsstate.c
@@ -1,11 +1,27 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jsparse.h"
|
||||
#include "jscompile.h"
|
||||
#include "jsobject.h"
|
||||
#include "jsrun.h"
|
||||
#include "jsstate.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
void js_loadstring(js_State *J, const char *source)
|
||||
void js_loadstring(js_State *J, const char *filename, const char *source)
|
||||
{
|
||||
jsR_loadscript(J, "(string)", source);
|
||||
js_Ast *P;
|
||||
js_Function *F;
|
||||
|
||||
if (js_try(J)) {
|
||||
jsP_freeparse(J);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
P = jsP_parse(J, filename, source);
|
||||
jsP_optimize(J, P);
|
||||
F = jsC_compile(J, P);
|
||||
jsP_freeparse(J);
|
||||
js_newscript(J, F);
|
||||
|
||||
js_endtry(J);
|
||||
}
|
||||
|
||||
void js_loadfile(js_State *J, const char *filename)
|
||||
@@ -47,7 +63,7 @@ void js_loadfile(js_State *J, const char *filename)
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
jsR_loadscript(J, filename, s);
|
||||
js_loadstring(J, filename, s);
|
||||
|
||||
free(s);
|
||||
fclose(f);
|
||||
@@ -60,7 +76,7 @@ int js_dostring(js_State *J, const char *source)
|
||||
fprintf(stderr, "libjs: %s\n", js_tostring(J, -1));
|
||||
return 1;
|
||||
}
|
||||
js_loadstring(J, source);
|
||||
js_loadstring(J, "(string)", source);
|
||||
js_pushglobal(J);
|
||||
js_call(J, 0);
|
||||
js_pop(J, 1);
|
||||
@@ -87,6 +103,8 @@ js_State *js_newstate(void)
|
||||
js_State *J = malloc(sizeof *J);
|
||||
memset(J, 0, sizeof(*J));
|
||||
|
||||
J->stack = malloc(JS_STACKSIZE * sizeof *J->stack);
|
||||
|
||||
J->gcmark = 1;
|
||||
|
||||
J->G = jsR_newobject(J, JS_COBJECT, NULL);
|
||||
|
||||
91
jsstate.h
91
jsstate.h
@@ -1,91 +0,0 @@
|
||||
#ifndef js_state_h
|
||||
#define js_state_h
|
||||
|
||||
#include "jsobject.h" /* for js_Value */
|
||||
|
||||
#define JS_STACKSIZE 256
|
||||
#define JS_TRYLIMIT 64
|
||||
#define JS_GCLIMIT 10000 /* run gc cycle every N allocations */
|
||||
|
||||
void js_savetry(js_State *J, short *pc);
|
||||
|
||||
#define js_trypc(J, PC) \
|
||||
(js_savetry(J, PC), setjmp(J->trybuf[J->trylen++].buf))
|
||||
|
||||
#define js_try(J) \
|
||||
(js_savetry(J, NULL), setjmp(J->trybuf[J->trylen++].buf))
|
||||
|
||||
#define js_endtry(J) \
|
||||
(--J->trylen)
|
||||
|
||||
typedef struct js_Jumpbuf js_Jumpbuf;
|
||||
|
||||
struct js_Jumpbuf
|
||||
{
|
||||
jmp_buf buf;
|
||||
js_Environment *E;
|
||||
int top, bot;
|
||||
short *pc;
|
||||
};
|
||||
|
||||
struct js_State
|
||||
{
|
||||
js_StringNode *strings;
|
||||
|
||||
/* input */
|
||||
const char *filename;
|
||||
const char *source;
|
||||
int line;
|
||||
|
||||
/* lexer */
|
||||
struct { char *text; size_t len, cap; } buf;
|
||||
int lexline;
|
||||
int lexchar;
|
||||
int lasttoken;
|
||||
int newline;
|
||||
|
||||
/* parser */
|
||||
int lookahead;
|
||||
const char *text;
|
||||
double number;
|
||||
js_Ast *gcast; /* list of allocated nodes to free after parsing */
|
||||
|
||||
/* compiler */
|
||||
int strict;
|
||||
|
||||
/* runtime environment */
|
||||
js_Object *Object_prototype;
|
||||
js_Object *Array_prototype;
|
||||
js_Object *Function_prototype;
|
||||
js_Object *Boolean_prototype;
|
||||
js_Object *Number_prototype;
|
||||
js_Object *String_prototype;
|
||||
|
||||
js_Object *Error_prototype;
|
||||
js_Object *EvalError_prototype;
|
||||
js_Object *RangeError_prototype;
|
||||
js_Object *ReferenceError_prototype;
|
||||
js_Object *SyntaxError_prototype;
|
||||
js_Object *TypeError_prototype;
|
||||
js_Object *URIError_prototype;
|
||||
|
||||
js_Object *G;
|
||||
js_Environment *E;
|
||||
|
||||
/* garbage collector list */
|
||||
int gcmark;
|
||||
int gccounter;
|
||||
js_Environment *gcenv;
|
||||
js_Function *gcfun;
|
||||
js_Object *gcobj;
|
||||
|
||||
/* exception stack */
|
||||
int trylen;
|
||||
js_Jumpbuf trybuf[JS_TRYLIMIT];
|
||||
|
||||
/* execution stack */
|
||||
int top, bot;
|
||||
js_Value stack[JS_STACKSIZE];
|
||||
};
|
||||
|
||||
#endif
|
||||
3
jsutf.c
3
jsutf.c
@@ -11,10 +11,9 @@
|
||||
* ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "js.h"
|
||||
#include "jsutf.h"
|
||||
|
||||
#define uchar jsU_uchar
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "js.h"
|
||||
#include "jsutf.h"
|
||||
|
||||
#define bsearch jsU_bsearch
|
||||
|
||||
11
jsvalue.c
11
jsvalue.c
@@ -1,6 +1,5 @@
|
||||
#include "js.h"
|
||||
#include "jsi.h"
|
||||
#include "jsobject.h"
|
||||
#include "jsrun.h"
|
||||
|
||||
const char *jsR_stringfromnumber(js_State *J, double n)
|
||||
{
|
||||
@@ -139,7 +138,7 @@ js_Object *jsR_toobject(js_State *J, const js_Value *v)
|
||||
jsR_throwTypeError(J, "cannot convert value to object");
|
||||
}
|
||||
|
||||
void jsR_concat(js_State *J)
|
||||
void js_concat(js_State *J)
|
||||
{
|
||||
js_Value va = js_toprimitive(J, -2, JS_HNONE);
|
||||
js_Value vb = js_toprimitive(J, -1, JS_HNONE);
|
||||
@@ -160,7 +159,7 @@ void jsR_concat(js_State *J)
|
||||
}
|
||||
}
|
||||
|
||||
int jsR_compare(js_State *J)
|
||||
int js_compare(js_State *J)
|
||||
{
|
||||
js_Value va = js_toprimitive(J, -2, JS_HNUMBER);
|
||||
js_Value vb = js_toprimitive(J, -1, JS_HNUMBER);
|
||||
@@ -174,7 +173,7 @@ int jsR_compare(js_State *J)
|
||||
}
|
||||
}
|
||||
|
||||
int jsR_equal(js_State *J)
|
||||
int js_equal(js_State *J)
|
||||
{
|
||||
js_Value va = js_tovalue(J, -2);
|
||||
js_Value vb = js_tovalue(J, -1);
|
||||
@@ -211,7 +210,7 @@ retry:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int jsR_strictequal(js_State *J)
|
||||
int js_strictequal(js_State *J)
|
||||
{
|
||||
js_Value va = js_tovalue(J, -2);
|
||||
js_Value vb = js_tovalue(J, -1);
|
||||
|
||||
Reference in New Issue
Block a user