Ejemplo n.º 1
0
OBJ
builtin_if(OBJ env, OBJ argList){
	OBJ condExpr, ifExpr, elseExpr, condValue;
	
	int numArgs = length(argList);
	if( numArgs == 2){
		// case 1: else-less if -> (if cond <expr>)
		elseExpr = js_nil;

	} else if( numArgs == 3){
		// case 2: regular if -> (if cond <ifExpr> <elseExpr>)
		elseExpr = CAR( CDR( CDR( argList )));
	} else {
		js_error("(if): expects 2 or 3 arguments", js_nil);
	}

	condExpr = CAR(argList); 
	ifExpr = CAR( CDR(argList));

	condValue = js_eval(env, condExpr);
	if (condValue == js_true){
		return (js_eval(env, ifExpr));
	}
	if (condValue == js_false){
		return (js_eval(env,elseExpr));
	}

	// TO-DO implement #t #f rules for all kind of OBJs
	js_error("(if): non-boolean condition value", condValue);
	// NOT REACHED
	return js_nil;
}
Ejemplo n.º 2
0
OBJ
builtin_set(OBJ env, OBJ argList) {
    OBJ varName, expr;

    if (!ISCONS(argList)) {
	js_error("(set!) expects 2 arguments:", argList);
    }
    varName = CAR(argList);
    argList = CDR(argList);

    if (!ISCONS(argList)) {
	js_error("(set!) expects 2 arguments:", argList);
    }
    expr = CAR(argList);
    argList = CDR(argList);
    if (argList != js_nil) {
	js_error("(set!) expects 2 arguments:", argList);
    }

    if (!ISSYMBOL(varName)) {
	js_error("(set!) non symbol variable name:", varName);
    }
    if (expr == js_nil) {
	environmentSet(env, varName, expr);
	return js_void;	
    }
    OBJ evaledExpr = js_eval(env, expr);
    environmentSet(env, varName, evaledExpr);
    return js_void;
}
Ejemplo n.º 3
0
static int jerry_task_init (void)
{
  int retcode;

  DECLARE_JS_CODES;

  /* run main.js */
  retcode = js_entry (js_codes[0].source, js_codes[0].length);
  if (retcode != 0)
  {
    printf ("js_entry failed code(%d) [%s]\r\n", retcode, js_codes[0].name);
    js_exit ();
    return -1;
  }
  /* run rest of the js files */
  for (int src = 1; js_codes[src].source; src++)
  {
    retcode = js_eval (js_codes[src].source, js_codes[src].length);
    if (retcode != 0)
    {
      printf ("js_eval failed code(%d) [%s]\r\n", retcode, js_codes[src].name);
      js_exit ();
      return -2;
    }
  }
  return 0;
}
Ejemplo n.º 4
0
OBJ
builtin_include(int numArgs){

	if( numArgs != 1){
		js_error("(include): expects 1 argument", js_nil);
	}
	OBJ arg1 = POP();
	char *fileName;
	FILE *theFile;

	if( !ISSTRING(arg1) ){
		js_error("(include): string arg expected:", arg1);
	}
	fileName = STRINGVAL(arg1);
	theFile = fopen(fileName, "r");
	if( theFile == NULL){
		js_error("(include): cannot open file:", arg1); 	
	}

	OBJ inputStream = newFileStream(theFile);

#ifdef DEBUG
	if( PRINT_INCLUDE->state){
		printIndent(indentLevelForInclude);
	       	fprintf(stdout, "<include file:" YEL " %s" RESET" >\n", fileName);
		indentLevelForInclude++;
	}
	if( CONTINUATION_PASSING->state){
		enterTrampoline1(inputStream);
	} 
	else{
		OBJ expr = js_read(inputStream);
		OBJ result;

		while( expr != js_eof){	
			result = js_eval(globalEnvironment, expr);
			if(PRINT_INCLUDE->state){
				printIndent(indentLevelForInclude);
				js_print(stdout, result,1);
				printf("\n");
			}
			expr = js_read(inputStream);
		}
	}
	if( PRINT_INCLUDE->state){
		indentLevelForInclude--;
		printIndent(indentLevelForInclude);
	       	fprintf(stdout, "<EOF:" YEL " %s" RESET" >\n", fileName);
	}
#else
	enterTrampoline1(inputStream);
#endif
	fclose( inputStream->u.fileStream.file );
	free( inputStream);
	
	return js_void;
}
Ejemplo n.º 5
0
void
jREPL(OBJ input){
	/*
	* Jojo Scheme REPL 
	*/
	for(;;){
		
		OBJ expr, result;
		if(prompt_enabled) printf(CYN "JS> " RESET);
	
		expr = js_read(input);				// R ead
		result = js_eval(globalEnvironment, expr);	// E valuate
		if( result == js_eof) return;
		js_print(stdout, result, 1);			// P rint
								// L oop
		printf("\n");
	}
}
Ejemplo n.º 6
0
static void jsR_run(js_State *J, js_Function *F)
{
	js_Function **FT = F->funtab;
	double *NT = F->numtab;
	const char **ST = F->strtab;
	js_Instruction *pcstart = F->code;
	js_Instruction *pc = F->code;
	enum js_OpCode opcode;
	int offset;

	const char *str;
	js_Object *obj;
	double x, y;
	unsigned int ux, uy;
	int ix, iy, okay;
	int b;

	while (1) {
		if (J->gccounter > JS_GCLIMIT) {
			J->gccounter = 0;
			js_gc(J, 0);
		}

		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_ROT4: js_rot4(J); break;

		case OP_NUMBER_0: js_pushnumber(J, 0); break;
		case OP_NUMBER_1: js_pushnumber(J, 1); break;
		case OP_NUMBER_POS: js_pushnumber(J, *pc++); break;
		case OP_NUMBER_NEG: js_pushnumber(J, -(*pc++)); break;
		case OP_NUMBER: js_pushnumber(J, NT[*pc++]); break;
		case OP_STRING: js_pushliteral(J, ST[*pc++]); break;

		case OP_CLOSURE: js_newfunction(J, FT[*pc++], J->E); break;
		case OP_NEWOBJECT: js_newobject(J); break;
		case OP_NEWARRAY: js_newarray(J); break;
		case OP_NEWREGEXP: js_newregexp(J, ST[pc[0]], pc[1]); pc += 2; 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_copy(J, 0); break;
		case OP_GLOBAL: js_pushobject(J, J->G); break;
		case OP_CURRENT: js_currentfunction(J); break;

		case OP_INITLOCAL:
			STACK[BOT + *pc++] = STACK[--TOP];
			break;

		case OP_GETLOCAL:
			CHECKSTACK(1);
			STACK[TOP++] = STACK[BOT + *pc++];
			break;

		case OP_SETLOCAL:
			STACK[BOT + *pc++] = STACK[TOP-1];
			break;

		case OP_DELLOCAL:
			++pc;
			js_pushboolean(J, 0);
			break;

		case OP_INITVAR:
			js_initvar(J, ST[*pc++], -1);
			js_pop(J, 1);
			break;

		case OP_DEFVAR:
			js_defvar(J, ST[*pc++]);
			break;

		case OP_GETVAR:
			str = ST[*pc++];
			if (!js_hasvar(J, str))
				js_referenceerror(J, "'%s' is not defined", str);
			break;

		case OP_HASVAR:
			if (!js_hasvar(J, ST[*pc++]))
				js_pushundefined(J);
			break;

		case OP_SETVAR:
			js_setvar(J, ST[*pc++]);
			break;

		case OP_DELVAR:
			b = js_delvar(J, ST[*pc++]);
			js_pushboolean(J, b);
			break;

		case OP_IN:
			str = js_tostring(J, -2);
			if (!js_isobject(J, -1))
				js_typeerror(J, "operand to 'in' is not an object");
			b = js_hasproperty(J, -1, str);
			js_pop(J, 2 + b);
			js_pushboolean(J, b);
			break;

		case OP_INITPROP:
			obj = js_toobject(J, -3);
			str = js_tostring(J, -2);
			jsR_setproperty(J, obj, str, stackidx(J, -1));
			js_pop(J, 2);
			break;

		case OP_INITGETTER:
			obj = js_toobject(J, -3);
			str = js_tostring(J, -2);
			jsR_defproperty(J, obj, str, 0, NULL, jsR_tofunction(J, -1), NULL);
			js_pop(J, 2);
			break;

		case OP_INITSETTER:
			obj = js_toobject(J, -3);
			str = js_tostring(J, -2);
			jsR_defproperty(J, obj, str, 0, NULL, NULL, jsR_tofunction(J, -1));
			js_pop(J, 2);
			break;

		case OP_GETPROP:
			str = js_tostring(J, -1);
			obj = js_toobject(J, -2);
			jsR_getproperty(J, obj, str);
			js_rot3pop2(J);
			break;

		case OP_GETPROP_S:
			str = ST[*pc++];
			obj = js_toobject(J, -1);
			jsR_getproperty(J, obj, str);
			js_rot2pop1(J);
			break;

		case OP_SETPROP:
			str = js_tostring(J, -2);
			obj = js_toobject(J, -3);
			jsR_setproperty(J, obj, str, stackidx(J, -1));
			js_rot3pop2(J);
			break;

		case OP_SETPROP_S:
			str = ST[*pc++];
			obj = js_toobject(J, -2);
			jsR_setproperty(J, obj, str, stackidx(J, -1));
			js_rot2pop1(J);
			break;

		case OP_DELPROP:
			str = js_tostring(J, -1);
			obj = js_toobject(J, -2);
			b = jsR_delproperty(J, obj, str);
			js_pop(J, 2);
			js_pushboolean(J, b);
			break;

		case OP_DELPROP_S:
			str = ST[*pc++];
			obj = js_toobject(J, -1);
			b = jsR_delproperty(J, obj, str);
			js_pop(J, 1);
			js_pushboolean(J, b);
			break;

		case OP_ITERATOR:
			if (!js_isundefined(J, -1) && !js_isnull(J, -1)) {
				obj = jsV_newiterator(J, js_toobject(J, -1), 0);
				js_pop(J, 1);
				js_pushobject(J, obj);
			}
			break;

		case OP_NEXTITER:
			obj = js_toobject(J, -1);
			str = jsV_nextiterator(J, obj);
			if (str) {
				js_pushliteral(J, str);
				js_pushboolean(J, 1);
			} else {
				js_pop(J, 1);
				js_pushboolean(J, 0);
			}
			break;

		/* Function calls */

		case OP_EVAL:
			js_eval(J);
			break;

		case OP_CALL:
			js_call(J, *pc++);
			break;

		case OP_NEW:
			js_construct(J, *pc++);
			break;

		/* Unary operators */

		case OP_TYPEOF:
			str = js_typeof(J, -1);
			js_pop(J, 1);
			js_pushliteral(J, str);
			break;

		case OP_POS:
			x = js_tonumber(J, -1);
			js_pop(J, 1);
			js_pushnumber(J, x);
			break;

		case OP_NEG:
			x = js_tonumber(J, -1);
			js_pop(J, 1);
			js_pushnumber(J, -x);
			break;

		case OP_BITNOT:
			ix = js_toint32(J, -1);
			js_pop(J, 1);
			js_pushnumber(J, ~ix);
			break;

		case OP_LOGNOT:
			b = js_toboolean(J, -1);
			js_pop(J, 1);
			js_pushboolean(J, !b);
			break;

		case OP_INC:
			x = js_tonumber(J, -1);
			js_pop(J, 1);
			js_pushnumber(J, x + 1);
			break;

		case OP_DEC:
			x = js_tonumber(J, -1);
			js_pop(J, 1);
			js_pushnumber(J, x - 1);
			break;

		case OP_POSTINC:
			x = js_tonumber(J, -1);
			js_pop(J, 1);
			js_pushnumber(J, x + 1);
			js_pushnumber(J, x);
			break;

		case OP_POSTDEC:
			x = js_tonumber(J, -1);
			js_pop(J, 1);
			js_pushnumber(J, x - 1);
			js_pushnumber(J, x);
			break;

		/* Multiplicative operators */

		case OP_MUL:
			x = js_tonumber(J, -2);
			y = js_tonumber(J, -1);
			js_pop(J, 2);
			js_pushnumber(J, x * y);
			break;

		case OP_DIV:
			x = js_tonumber(J, -2);
			y = js_tonumber(J, -1);
			js_pop(J, 2);
			js_pushnumber(J, x / y);
			break;

		case OP_MOD:
			x = js_tonumber(J, -2);
			y = js_tonumber(J, -1);
			js_pop(J, 2);
			js_pushnumber(J, fmod(x, y));
			break;

		/* Additive operators */

		case OP_ADD:
			js_concat(J);
			break;

		case OP_SUB:
			x = js_tonumber(J, -2);
			y = js_tonumber(J, -1);
			js_pop(J, 2);
			js_pushnumber(J, x - y);
			break;

		/* Shift operators */

		case OP_SHL:
			ix = js_toint32(J, -2);
			uy = js_touint32(J, -1);
			js_pop(J, 2);
			js_pushnumber(J, ix << (uy & 0x1F));
			break;

		case OP_SHR:
			ix = js_toint32(J, -2);
			uy = js_touint32(J, -1);
			js_pop(J, 2);
			js_pushnumber(J, ix >> (uy & 0x1F));
			break;

		case OP_USHR:
			ux = js_touint32(J, -2);
			uy = js_touint32(J, -1);
			js_pop(J, 2);
			js_pushnumber(J, ux >> (uy & 0x1F));
			break;

		/* Relational operators */

		case OP_LT: b = js_compare(J, &okay); js_pop(J, 2); js_pushboolean(J, okay && b < 0); break;
		case OP_GT: b = js_compare(J, &okay); js_pop(J, 2); js_pushboolean(J, okay && b > 0); break;
		case OP_LE: b = js_compare(J, &okay); js_pop(J, 2); js_pushboolean(J, okay && b <= 0); break;
		case OP_GE: b = js_compare(J, &okay); js_pop(J, 2); js_pushboolean(J, okay && b >= 0); break;

		case OP_INSTANCEOF:
			b = js_instanceof(J);
			js_pop(J, 2);
			js_pushboolean(J, b);
			break;

		/* Equality */

		case OP_EQ: b = js_equal(J); js_pop(J, 2); js_pushboolean(J, b); break;
		case OP_NE: b = js_equal(J); js_pop(J, 2); js_pushboolean(J, !b); break;
		case OP_STRICTEQ: b = js_strictequal(J); js_pop(J, 2); js_pushboolean(J, b); break;
		case OP_STRICTNE: b = js_strictequal(J); js_pop(J, 2); js_pushboolean(J, !b); break;

		case OP_JCASE:
			offset = *pc++;
			b = js_strictequal(J);
			if (b) {
				js_pop(J, 2);
				pc = pcstart + offset;
			} else {
				js_pop(J, 1);
			}
			break;

		/* Binary bitwise operators */

		case OP_BITAND:
			ix = js_toint32(J, -2);
			iy = js_toint32(J, -1);
			js_pop(J, 2);
			js_pushnumber(J, ix & iy);
			break;

		case OP_BITXOR:
			ix = js_toint32(J, -2);
			iy = js_toint32(J, -1);
			js_pop(J, 2);
			js_pushnumber(J, ix ^ iy);
			break;

		case OP_BITOR:
			ix = js_toint32(J, -2);
			iy = js_toint32(J, -1);
			js_pop(J, 2);
			js_pushnumber(J, ix | iy);
			break;

		/* Try and Catch */

		case OP_THROW:
			js_throw(J);

		case OP_TRY:
			offset = *pc++;
			if (js_trypc(J, pc)) {
				pc = J->trybuf[J->trytop].pc;
			} else {
				pc = pcstart + offset;
			}
			break;

		case OP_ENDTRY:
			js_endtry(J);
			break;

		case OP_CATCH:
			str = ST[*pc++];
			obj = jsV_newobject(J, JS_COBJECT, NULL);
			js_pushobject(J, obj);
			js_rot2(J);
			js_setproperty(J, -2, str);
			J->E = jsR_newenvironment(J, obj, J->E);
			js_pop(J, 1);
			break;

		case OP_ENDCATCH:
			J->E = J->E->outer;
			break;

		/* With */

		case OP_WITH:
			obj = js_toobject(J, -1);
			J->E = jsR_newenvironment(J, obj, J->E);
			js_pop(J, 1);
			break;

		case OP_ENDWITH:
			J->E = J->E->outer;
			break;

		/* Branching */

		case OP_DEBUGGER:
			js_trap(J, (int)(pc - pcstart) - 1);
			break;

		case OP_JUMP:
			pc = pcstart + *pc;
			break;

		case OP_JTRUE:
			offset = *pc++;
			b = js_toboolean(J, -1);
			js_pop(J, 1);
			if (b)
				pc = pcstart + offset;
			break;

		case OP_JFALSE:
			offset = *pc++;
			b = js_toboolean(J, -1);
			js_pop(J, 1);
			if (!b)
				pc = pcstart + offset;
			break;

		case OP_RETURN:
			return;

		case OP_LINE:
			J->trace[J->tracetop].line = *pc++;
			break;
		}
	}
}
Ejemplo n.º 7
0
OBJ
builtin_define(OBJ env, OBJ argList){

	if( !ISCONS(argList) ){
		js_error("(define): expects at least  2 arguments", js_nil);
	}
	
	OBJ arg1 = CAR(argList);
	argList = CDR(argList);

	if( !ISCONS(argList) ){
		js_error("(define): expects at least  2 arguments", js_nil);
	}

	// case 1: define SYMBOL -> (define symbol expression)
	if( ISSYMBOL(arg1)) {
		OBJ arg2 = CAR(argList);
		argList = CDR(argList);
		if( argList != js_nil ){
			js_error("(define): this form expects exactly 2 arguments", js_nil);
		}
		OBJ value = js_eval(env, arg2);
		environmentPut(env, arg1, value);

#ifdef DEBUG
// PRINT TRACE
if( EVAL_TRACE->state) {
		printIndent(indentLevel);
		fprintf(stdout, RED"DEFINE "RESET);
		js_print(stdout, arg1,1);       
		fprintf(stdout, " -> ");
		js_print(stdout, value,1);

		if( TAG(env) == T_GLOBALENVIRONMENT ){

			fprintf(stdout," in " CYN "GLOBAL" RESET " (%p)\n", env);
		} 
		if( TAG(env) == T_LOCALENVIRONMENT ){
			fprintf(stdout," in " YEL "LOCAL" RESET " (%p)\n", env);
		}
}
#endif

		return js_void;
	}
	// case 2: define CONS ( function ) -> (define (name args*) (body*) )
	if( ISCONS(arg1)){
		
		OBJ name = CAR(arg1);
		if( ISSYMBOL(name) ){
			OBJ formalArgList = CDR(arg1);
			OBJ bodyList = argList;
			OBJ newUDF;

			newUDF = newUserDefinedFunction("anonymous lambda", formalArgList, bodyList);
			newUDF->u.userDefinedFunction.numLocals = count_defines(bodyList);
			newUDF->u.userDefinedFunction.home = env;
			environmentPut(env, name, newUDF);

#ifdef DEBUG
// PRINT TRACE
if( EVAL_TRACE->state ){
			printIndent(indentLevel);
			fprintf(stdout, RED"DEFINE "RESET);
			js_print(stdout, name,1);       
			fprintf(stdout, " -> ");
			js_print(stdout, newUDF,1);

			if( TAG(env) == T_GLOBALENVIRONMENT ){

				fprintf(stdout," in " CYN "GLOBAL" RESET " (%p)\n", env);
			} 
			if( TAG(env) == T_LOCALENVIRONMENT ){
				fprintf(stdout," in " YEL "LOCAL" RESET " (%p)\n", env);
			}
}
#endif
			return js_void;
		}
	}
	error("define form unimplemented", __FILE__, __LINE__);

	// NOT REACHED
	return js_nil;
}