<commit_before>#include "js.h"
#include "jsobject.h"
#include "jscompile.h"
#include "jsrun.h"
#include "jsstate.h"

static js_Value stack[256];
static int top = 0;
static int bot = 0;

static inline double tointeger(double n)
{
	double sign = n < 0 ? -1 : 1;
	if (isnan(n)) return 0;
	if (n == 0 || isinf(n)) return n;
	return sign * floor(abs(n));
}

static inline int toint32(double n)
{
	double two32 = 4294967296.0;
	double two31 = 2147483648.0;

	if (!isfinite(n) || n == 0)
		return 0;

	n = fmod(n, two32);
	n = n >= 0 ? floor(n) : ceil(n) + two32;
	if (n >= two31)
		return n - two32;
	else
		return n;
}

static inline unsigned int touint32(double n)
{
	return toint32(n);
}

static void js_pushvalue(js_State *J, js_Value v)
{
	stack[top] = v;
	++top;
}

void js_pushundefined(js_State *J)
{
	stack[top].type = JS_TUNDEFINED;
	++top;
}

void js_pushnull(js_State *J)
{
	stack[top].type = JS_TNULL;
	++top;
}

void js_pushboolean(js_State *J, int v)
{
	stack[top].type = JS_TBOOLEAN;
	stack[top].u.boolean = !!v;
	++top;
}

void js_pushnumber(js_State *J, double v)
{
	stack[top].type = JS_TNUMBER;
	stack[top].u.number = v;
	++top;
}

void js_pushstring(js_State *J, const char *v)
{
	stack[top].type = JS_TSTRING;
	stack[top].u.string = v;
	++top;
}

void js_pushobject(js_State *J, js_Object *v)
{
	stack[top].type = JS_TOBJECT;
	stack[top].u.object = v;
	++top;
}

static int stackidx(js_State *J, int idx)
{
	if (idx < 0)
		return top + idx;
	return bot + idx;
}

int js_isundefined(js_State *J, int idx)
{
	idx = stackidx(J, idx);
	return stack[idx].type == JS_TUNDEFINED;
}

int js_isstring(js_State *J, int idx)
{
	idx = stackidx(J, idx);
	return stack[idx].type == JS_TSTRING;
}

int js_iscfunction(js_State *J, int idx)
{
	idx = stackidx(J, idx);
	return stack[idx].type == JS_TCFUNCTION;
}

js_Value js_tovalue(js_State *J, int idx)
{
	idx = stackidx(J, idx);
	return stack[idx];
}

int js_toboolean(js_State *J, int idx)
{
	const char *s;
	double n;
	idx = stackidx(J, idx);
	switch (stack[idx].type) {
	case JS_TUNDEFINED: return 0;
	case JS_TNULL: return 0;
	case JS_TBOOLEAN: return stack[idx].u.boolean;
	case JS_TNUMBER: n = stack[idx].u.number; return n != 0 || !isnan(n);
	case JS_TSTRING: s = stack[idx].u.string; return s[0] != 0;
	default: return 1;
	}
}

double js_tonumber(js_State *J, int idx)
{
	idx = stackidx(J, idx);
	switch (stack[idx].type) {
	case JS_TUNDEFINED: return NAN;
	case JS_TNULL: return 0;
	case JS_TBOOLEAN: return stack[idx].u.boolean;
	case JS_TNUMBER: return stack[idx].u.number;
	case JS_TSTRING: return strtod(stack[idx].u.string, NULL);
	default: return 0;
	}
}

double js_tointeger(js_State *J, int idx)
{
	return toint32(js_tonumber(J, idx));
}

const char *js_tostring(js_State *J, int idx)
{
	char buf[20];
	idx = stackidx(J, idx);
	switch (stack[idx].type) {
	case JS_TUNDEFINED: return "undefined";
	case JS_TNULL: return "null";
	case JS_TBOOLEAN: return stack[idx].u.boolean ? "true" : "false";
	case JS_TNUMBER: sprintf(buf, "%.9g", stack[idx].u.number); return js_intern(J, buf);
	case JS_TSTRING: return stack[idx].u.string;
	default: return "undefined";
	}
}

js_Object *js_toobject(js_State *J, int idx)
{
	idx = stackidx(J, idx);
	switch (stack[idx].type) {
	case JS_TUNDEFINED: jsR_error(J, "TypeError");
	case JS_TNULL: jsR_error(J, "TypeError");
	case JS_TBOOLEAN: jsR_error(J, "new Boolean()");
	case JS_TNUMBER: jsR_error(J, "new Number()");
	case JS_TSTRING: jsR_error(J, "new String()");
	case JS_TOBJECT: return stack[idx].u.object;
	default: jsR_error(J, "TypeError");
	}
	return NULL;
}

void js_pop(js_State *J, int n)
{
	top -= n;
}

void js_dup(js_State *J)
{
	stack[top] = stack[top-1];
	++top;
}

void js_dup2(js_State *J)
{
	stack[top] = stack[top-2];
	stack[top+1] = stack[top-1];
	top += 2;
}

void js_rot2(js_State *J)
{
	/* A B -> B A */
	js_Value tmp = stack[top-1];	/* A B (B) */
	stack[top-1] = stack[top-2];	/* A A */
	stack[top-2] = tmp;		/* B A */
}

void js_rot3(js_State *J)
{
	/* A B C -> C A B */
	js_Value tmp = stack[top-1];	/* A B C (C) */
	stack[top-1] = stack[top-2];	/* A B B */
	stack[top-2] = stack[top-3];	/* A A B */
	stack[top-3] = tmp;		/* C A B */
}

void js_rot3pop2(js_State *J)
{
	/* A B C -> C */
	stack[top-3] = stack[top-1];
	top -= 2;
}

void js_dup1rot4(js_State *J)
{
	/* A B C -> C A B C */
	stack[top] = stack[top-1];	/* A B C C */
	stack[top-1] = stack[top-2];	/* A B B C */
	stack[top-2] = stack[top-3];	/* A A B C */
	stack[top-3] = stack[top];	/* C A B C */
	++top;
}

void js_trap(js_State *J)
{
}

static void runfun(js_State *J, js_Function *F, js_Object *E)
{
	js_Function **FT = F->funtab;
	double *NT = F->numtab;
	const char **ST = F->strtab;
	short *pcstart = F->code;
	short *pc = F->code;
	int opcode, offset;

	const char *str;
	js_Object *obj;
	js_Property *ref;
	double x, y;
	int b;

	while (1) {
		opcode = *pc++;
		switch (opcode) {
		case OP_POP: js_pop(J, 1); break;
		case OP_DUP: js_dup(J); break;
		case OP_DUP2: js_dup2(J); break;
		case OP_ROT2: js_rot2(J); break;
		case OP_ROT3: js_rot3(J); break;
		case OP_DUP1ROT4: js_dup1rot4(J); break;

		case OP_NUMBER_0: js_pushnumber(J, 0); break;
		case OP_NUMBER_1: js_pushnumber(J, 1); break;
		case OP_NUMBER_X: js_pushnumber(J, *pc++); break;
		case OP_NUMBER: js_pushnumber(J, NT[*pc++]); break;
		case OP_STRING: js_pushstring(J, ST[*pc++]); break;
		// case OP_CLOSURE: break;

		case OP_UNDEF: js_pushundefined(J); break;
		case OP_NULL: js_pushnull(J); break;
		case OP_TRUE: js_pushboolean(J, 1); break;
		case OP_FALSE: js_pushboolean(J, 0); break;

		case OP_THIS: js_pushnull(J); break;

		case OP_NEWOBJECT: js_pushobject(J, js_newobject(J)); break;
		case OP_NEWARRAY: js_pushobject(J, js_newobject(J)); break;

		case OP_FUNDEC:
			ref = js_setproperty(J, E, ST[*pc++]);
//			if (ref)
//				ref->value = js_toclosure(J, -1);
			js_pop(J, 1);
			break;

		case OP_VARDEC: pc++; break;
			ref = js_setproperty(J, E, ST[*pc++]);
			break;

		case OP_GETVAR:
			ref = js_getproperty(J, E, ST[*pc++]);
			if (ref)
				js_pushvalue(J, ref->value);
			else
				js_pushundefined(J);
			break;

		case OP_SETVAR:
			ref = js_setproperty(J, E, ST[*pc++]);
			if (ref)
				ref->value = js_tovalue(J, -1);
			break;

		// OP_DELVAR

		case OP_IN:
			str = js_tostring(J, -2);
			obj = js_toobject(J, -1);
			ref = js_getproperty(J, obj, str);
			js_pop(J, 2);
			js_pushboolean(J, ref != NULL);
			break;

		case OP_GETPROP:
			obj = js_toobject(J, -2);
			str = js_tostring(J, -1);
			ref = js_getproperty(J, obj, str);
			js_pop(J, 2);
			if (ref)
				js_pushvalue(J, ref->value);
			else
				js_pushundefined(J);
			break;

		case OP_SETPROP:
			obj = js_toobject(J, -3);
			str = js_tostring(J, -2);
			ref = js_setproperty(J, obj, str);
			if (ref)
				ref->value = js_tovalue(J, -1);
			js_rot3pop2(J);
			break;

		// OP_DELPROP

		case OP_NEXTPROP:
			obj = js_toobject(J, -2);
			if (js_isundefined(J, -1))
				ref = js_firstproperty(J, obj);
			else
				ref = js_nextproperty(J, obj, js_tostring(J, -1));
			if (ref) {
				js_pop(J, 1);
				js_pushstring(J, ref->name);
				js_pushboolean(J, 1);
			} else {
				js_pop(J, 2);<commit_msg>js_pushlstring() for pushing literal (and interned strings).<commit_after>#include "js.h"
#include "jsobject.h"
#include "jscompile.h"
#include "jsrun.h"
#include "jsstate.h"

static js_Value stack[256];
static int top = 0;
static int bot = 0;

static inline double tointeger(double n)
{
	double sign = n < 0 ? -1 : 1;
	if (isnan(n)) return 0;
	if (n == 0 || isinf(n)) return n;
	return sign * floor(abs(n));
}

static inline int toint32(double n)
{
	double two32 = 4294967296.0;
	double two31 = 2147483648.0;

	if (!isfinite(n) || n == 0)
		return 0;

	n = fmod(n, two32);
	n = n >= 0 ? floor(n) : ceil(n) + two32;
	if (n >= two31)
		return n - two32;
	else
		return n;
}

static inline unsigned int touint32(double n)
{
	return toint32(n);
}

static void js_pushvalue(js_State *J, js_Value v)
{
	stack[top] = v;
	++top;
}

void js_pushundefined(js_State *J)
{
	stack[top].type = JS_TUNDEFINED;
	++top;
}

void js_pushnull(js_State *J)
{
	stack[top].type = JS_TNULL;
	++top;
}

void js_pushboolean(js_State *J, int v)
{
	stack[top].type = JS_TBOOLEAN;
	stack[top].u.boolean = !!v;
	++top;
}

void js_pushnumber(js_State *J, double v)
{
	stack[top].type = JS_TNUMBER;
	stack[top].u.number = v;
	++top;
}

void js_pushlstring(js_State *J, const char *v)
{
	stack[top].type = JS_TSTRING;
	stack[top].u.string = v;
	++top;
}

void js_pushstring(js_State *J, const char *v)
{
	stack[top].type = JS_TSTRING;
	stack[top].u.string = js_intern(J, v);
	++top;
}

void js_pushobject(js_State *J, js_Object *v)
{
	stack[top].type = JS_TOBJECT;
	stack[top].u.object = v;
	++top;
}

static int stackidx(js_State *J, int idx)
{
	if (idx < 0)
		return top + idx;
	return bot + idx;
}

int js_isundefined(js_State *J, int idx)
{
	idx = stackidx(J, idx);
	return stack[idx].type == JS_TUNDEFINED;
}

int js_isstring(js_State *J, int idx)
{
	idx = stackidx(J, idx);
	return stack[idx].type == JS_TSTRING;
}

int js_iscfunction(js_State *J, int idx)
{
	idx = stackidx(J, idx);
	return stack[idx].type == JS_TCFUNCTION;
}

js_Value js_tovalue(js_State *J, int idx)
{
	idx = stackidx(J, idx);
	return stack[idx];
}

int js_toboolean(js_State *J, int idx)
{
	const char *s;
	double n;
	idx = stackidx(J, idx);
	switch (stack[idx].type) {
	case JS_TUNDEFINED: return 0;
	case JS_TNULL: return 0;
	case JS_TBOOLEAN: return stack[idx].u.boolean;
	case JS_TNUMBER: n = stack[idx].u.number; return n != 0 || !isnan(n);
	case JS_TSTRING: s = stack[idx].u.string; return s[0] != 0;
	default: return 1;
	}
}

double js_tonumber(js_State *J, int idx)
{
	idx = stackidx(J, idx);
	switch (stack[idx].type) {
	case JS_TUNDEFINED: return NAN;
	case JS_TNULL: return 0;
	case JS_TBOOLEAN: return stack[idx].u.boolean;
	case JS_TNUMBER: return stack[idx].u.number;
	case JS_TSTRING: return strtod(stack[idx].u.string, NULL);
	default: return 0;
	}
}

double js_tointeger(js_State *J, int idx)
{
	return toint32(js_tonumber(J, idx));
}

const char *js_tostring(js_State *J, int idx)
{
	char buf[20];
	idx = stackidx(J, idx);
	switch (stack[idx].type) {
	case JS_TUNDEFINED: return "undefined";
	case JS_TNULL: return "null";
	case JS_TBOOLEAN: return stack[idx].u.boolean ? "true" : "false";
	case JS_TNUMBER: sprintf(buf, "%.9g", stack[idx].u.number); return js_intern(J, buf);
	case JS_TSTRING: return stack[idx].u.string;
	default: return "undefined";
	}
}

js_Object *js_toobject(js_State *J, int idx)
{
	idx = stackidx(J, idx);
	switch (stack[idx].type) {
	case JS_TUNDEFINED: jsR_error(J, "TypeError");
	case JS_TNULL: jsR_error(J, "TypeError");
	case JS_TBOOLEAN: jsR_error(J, "new Boolean()");
	case JS_TNUMBER: jsR_error(J, "new Number()");
	case JS_TSTRING: jsR_error(J, "new String()");
	case JS_TOBJECT: return stack[idx].u.object;
	default: jsR_error(J, "TypeError");
	}
	return NULL;
}

void js_pop(js_State *J, int n)
{
	top -= n;
}

void js_dup(js_State *J)
{
	stack[top] = stack[top-1];
	++top;
}

void js_dup2(js_State *J)
{
	stack[top] = stack[top-2];
	stack[top+1] = stack[top-1];
	top += 2;
}

void js_rot2(js_State *J)
{
	/* A B -> B A */
	js_Value tmp = stack[top-1];	/* A B (B) */
	stack[top-1] = stack[top-2];	/* A A */
	stack[top-2] = tmp;		/* B A */
}

void js_rot3(js_State *J)
{
	/* A B C -> C A B */
	js_Value tmp = stack[top-1];	/* A B C (C) */
	stack[top-1] = stack[top-2];	/* A B B */
	stack[top-2] = stack[top-3];	/* A A B */
	stack[top-3] = tmp;		/* C A B */
}

void js_rot3pop2(js_State *J)
{
	/* A B C -> C */
	stack[top-3] = stack[top-1];
	top -= 2;
}

void js_dup1rot4(js_State *J)
{
	/* A B C -> C A B C */
	stack[top] = stack[top-1];	/* A B C C */
	stack[top-1] = stack[top-2];	/* A B B C */
	stack[top-2] = stack[top-3];	/* A A B C */
	stack[top-3] = stack[top];	/* C A B C */
	++top;
}

void js_trap(js_State *J)
{
}

static void runfun(js_State *J, js_Function *F, js_Object *E)
{
	js_Function **FT = F->funtab;
	double *NT = F->numtab;
	const char **ST = F->strtab;
	short *pcstart = F->code;
	short *pc = F->code;
	int opcode, offset;

	const char *str;
	js_Object *obj;
	js_Property *ref;
	double x, y;
	int b;

	while (1) {
		opcode = *pc++;
		switch (opcode) {
		case OP_POP: js_pop(J, 1); break;
		case OP_DUP: js_dup(J); break;
		case OP_DUP2: js_dup2(J); break;
		case OP_ROT2: js_rot2(J); break;
		case OP_ROT3: js_rot3(J); break;
		case OP_DUP1ROT4: js_dup1rot4(J); break;

		case OP_NUMBER_0: js_pushnumber(J, 0); break;
		case OP_NUMBER_1: js_pushnumber(J, 1); break;
		case OP_NUMBER_X: js_pushnumber(J, *pc++); break;
		case OP_NUMBER: js_pushnumber(J, NT[*pc++]); break;
		case OP_STRING: js_pushlstring(J, ST[*pc++]); break;
		// case OP_CLOSURE: break;

		case OP_UNDEF: js_pushundefined(J); break;
		case OP_NULL: js_pushnull(J); break;
		case OP_TRUE: js_pushboolean(J, 1); break;
		case OP_FALSE: js_pushboolean(J, 0); break;

		case OP_THIS: js_pushnull(J); break;

		case OP_NEWOBJECT: js_pushobject(J, js_newobject(J)); break;
		case OP_NEWARRAY: js_pushobject(J, js_newobject(J)); break;

		case OP_FUNDEC:
			ref = js_setproperty(J, E, ST[*pc++]);
//			if (ref)
//				ref->value = js_toclosure(J, -1);
			js_pop(J, 1);
			break;

		case OP_VARDEC: pc++; break;
			ref = js_setproperty(J, E, ST[*pc++]);
			break;

		case OP_GETVAR:
			ref = js_getproperty(J, E, ST[*pc++]);
			if (ref)
				js_pushvalue(J, ref->value);
			else
				js_pushundefined(J);
			break;

		case OP_SETVAR:
			ref = js_setproperty(J, E, ST[*pc++]);
			if (ref)
				ref->value = js_tovalue(J, -1);
			break;

		// OP_DELVAR

		case OP_IN:
			str = js_tostring(J, -2);
			obj = js_toobject(J, -1);
			ref = js_getproperty(J, obj, str);
			js_pop(J, 2);
			js_pushboolean(J, ref != NULL);
			break;

		case OP_GETPROP:
			obj = js_toobject(J, -2);
			str = js_tostring(J, -1);
			ref = js_getproperty(J, obj, str);
			js_pop(J, 2);
			if (ref)
				js_pushvalue(J, ref->value);
			else
				js_pushundefined(J);
			break;

		case OP_SETPROP:
			obj = js_toobject(J, -3);
			str = js_tostring(J, -2);
			ref = js_setproperty(J, obj, str);
			if (ref)
				ref->value = js_tovalue(J, -1);
			js_rot3pop2(J);
			break;

		// OP_DELPROP

		case OP_NEXTPROP:
			obj = js_toobject(J, -2);
			if (js_isundefined(J, -1))
				ref = js_firstproperty(J, obj);
			else
				ref = js_nextproperty(J, obj, js_tostring(J, -1));
			if (ref) {
				js_pop(J, 1);
				js_pushlstring(J, ref->name);
				js_pushboolean(J, 1);
			} else {
				js_pop(J, 2);
{'fraction_non_alphanumeric': 0.17185665953186494, 'fraction_numerical': 0.01878063937029621, 'mean_word_length': 3.7379784102060842, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4644101', 'n_tokens_mistral': 6877, 'n_tokens_neox': 6420, 'n_words': 1553}