ref: 40a12fba0dd5bef0dfcdf3067ea021d3a221faf4
parent: 8aa062755760b61f9131a0411e9125bafddc0a4f
author: Tor Andersson <tor@ccxvii.net>
date: Mon Jan 20 11:13:09 EST 2014
Split header into js.h public and jsi.h private. Start cleaning up private function prefixes.
--- a/js.h
+++ b/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>
+#include "jsconf.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
-
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 */
+const char *js_intern(js_State *J, const char *s);
-typedef int (*js_CFunction)(js_State *J, int argc);
+/* 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);
-/* private */
+/* Property attribute flags */
+enum {
+ JS_READONLY = 1,
+ JS_DONTENUM = 2,
+ JS_DONTDELETE = 4,
+};
-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;
+JS_NORETURN void js_throw(js_State *J);
-const char *js_intern(js_State *J, const char *s);
-void js_printstrings(js_State *J);
-void js_freestrings(js_State *J);
+void js_loadstring(js_State *J, const char *filename, const char *source);
+void js_loadfile(js_State *J, const char *filename);
-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 js_call(js_State *J, int n);
+void js_construct(js_State *J, int n);
-JS_NORETURN void js_throw(js_State *J);
-JS_NORETURN void js_error(js_State *J, const char *fmt, ...) __printflike(2,3);
+void js_getglobal(js_State *J, const char *name);
+void js_setglobal(js_State *J, const char *name);
-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_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
--- a/jsbarray.c
+++ b/jsbarray.c
@@ -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; }
--- a/jsbboolean.c
+++ b/jsbboolean.c
@@ -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)
{
--- a/jsberror.c
+++ b/jsberror.c
@@ -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;
}
--- a/jsbfunction.c
+++ b/jsbfunction.c
@@ -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; }
--- a/jsbmath.c
+++ b/jsbmath.c
@@ -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;
--- a/jsbnumber.c
+++ b/jsbnumber.c
@@ -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)
{
--- a/jsbobject.c
+++ b/jsbobject.c
@@ -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)
{
--- a/jsbstring.c
+++ b/jsbstring.c
@@ -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)
--- a/jsbuiltin.c
+++ b/jsbuiltin.c
@@ -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 @@
{
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;
--- /dev/null
+++ b/jsbuiltin.h
@@ -1,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
--- a/jscompile.c
+++ b/jscompile.c
@@ -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 */
--- /dev/null
+++ b/jsconf.h
@@ -1,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
--- a/jsdump.c
+++ b/jsdump.c
@@ -1,4 +1,4 @@
-#include "js.h"
+#include "jsi.h"
#include "jsparse.h"
#include "jscompile.h"
#include "jsobject.h"
--- a/jsgc.c
+++ b/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 @@
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 @@
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);
}
--- /dev/null
+++ b/jsi.h
@@ -1,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
--- a/jsintern.c
+++ b/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 @@
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 @@
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);
--- a/jslex.c
+++ b/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 @@
"'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 @@
#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 @@
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 @@
{
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 @@
{
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 @@
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 @@
}
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 @@
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 @@
{
const char *s;
int g, m, i;
- int c;
/* already consumed initial '/' */
@@ -396,11 +412,11 @@
/* 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 @@
/* 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 @@
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 @@
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 @@
next(J); /* load first lookahead character */
}
-int jsP_lex(js_State *J)
+int jsY_lex(js_State *J)
{
return J->lasttoken = lex(J);
}
--- a/jslex.h
+++ b/jslex.h
@@ -66,12 +66,9 @@
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
--- a/jsobject.c
+++ b/jsobject.c
@@ -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)
--- a/jsobject.h
+++ b/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 @@
JS_CMATH,
};
-enum {
- JS_HNONE,
- JS_HNUMBER,
- JS_HSTRING,
-};
-
struct js_Value
{
js_Type type;
@@ -79,6 +72,13 @@
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);
@@ -104,7 +104,5 @@
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
--- a/jsoptim.c
+++ b/jsoptim.c
@@ -1,4 +1,4 @@
-#include "js.h"
+#include "jsi.h"
#include "jsparse.h"
static inline int i32(double d)
--- a/jsparse.c
+++ b/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 *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 @@
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 @@
{
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 @@
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);
--- a/jsparse.h
+++ b/jsparse.h
@@ -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,
--- a/jsproperty.c
+++ b/jsproperty.c
@@ -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:
--- a/jsrun.c
+++ b/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 @@
#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 @@
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 @@
/* Additive operators */
case OP_ADD:
- jsR_concat(J);
+ js_concat(J);
break;
case OP_SUB:
@@ -743,19 +741,19 @@
/* 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 */
@@ -813,23 +811,4 @@
js_error(J, "illegal instruction: %d (pc=%d)", opcode, (int)(pc - F->code - 1));
}
}
-}
-
-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);
}
--- a/jsrun.h
+++ b/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;
@@ -9,80 +11,5 @@
js_Environment *gcnext;
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
--- a/jsstate.c
+++ b/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 @@
js_throw(J);
}
- jsR_loadscript(J, filename, s);
+ js_loadstring(J, filename, s);
free(s);
fclose(f);
@@ -60,7 +76,7 @@
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);
@@ -86,6 +102,8 @@
{
js_State *J = malloc(sizeof *J);
memset(J, 0, sizeof(*J));
+
+ J->stack = malloc(JS_STACKSIZE * sizeof *J->stack);
J->gcmark = 1;
--- a/jsstate.h
+++ /dev/null
@@ -1,91 +1,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
--- a/jsutf.c
+++ b/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
--- a/jsutftype.c
+++ b/jsutftype.c
@@ -1,4 +1,3 @@
-#include "js.h"
#include "jsutf.h"
#define bsearch jsU_bsearch
--- a/jsvalue.c
+++ b/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 @@
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 @@
}
}
-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_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 @@
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);
--- a/main.c
+++ b/main.c
@@ -13,7 +13,7 @@
js_gc(J, 1);
}
- js_close(J);
+ js_freestate(J);
return 0;
}