Пример #1
0
Файл: eval.c Проект: 7hens/yas
static Value _evalCall (Procedure self, Exp a, Exp b) {
	Value at = NULL, me = NULL;
	if (a->type == MEMBER_EXP) {
		at = _EVAL(a->u.binary->a);
		me = Value_get(at, _EVAL(a->u.binary->b));
	} else if ((a->type == AT_EXP || a->type == ME_EXP) && a->u.unary) {
		at = a->type == AT_EXP ? self->at : self->me;
		me = Value_get(at, _EVAL(a->u.unary));
	} else {
		me = _EVAL(a);
	}
	return _evalFunction(self, at, me, b);
}
Пример #2
0
Файл: vm.c Проект: txus/terrorvm
VALUE VM_run(STATE)
{
  Debugger_load_current_file(state);

  int *ip = CURR_FRAME->fn->code;

  while(1) {
    switch(*ip) {
      case NOOP:
        break;
      case SETLINE: { // debugging
        ip++;
        Debugger_setline(state, *ip);
        break;
      }
      case PUSH: {
        Debugger_evaluate(state);
        ip++;
        debugi("PUSH %i", *ip);
        VALUE value = LITERAL(*ip);
        Stack_push(STACK, value);
        break;
      }
      case PUSHTRUE: {
        Debugger_evaluate(state);
        debugi("PUSHTRUE");
        Stack_push(STACK, TrueObject);
        break;
      }
      case PUSHFALSE: {
        Debugger_evaluate(state);
        debugi("PUSHFALSE");
        Stack_push(STACK, FalseObject);
        break;
      }
      case PUSHNIL: {
        Debugger_evaluate(state);
        debugi("PUSHNIL");
        Stack_push(STACK, NilObject);
        break;
      }
      case JMP: {
        Debugger_evaluate(state);
        ip++;
        int jump = *ip;
        debugi("JMP %i", jump);
        while(jump--) ip++;
        break;
      }
      case JIF: {
        Debugger_evaluate(state);
        ip++;
        int jump = *ip;
        debugi("JIF %i", jump);

        VALUE value = Stack_pop(STACK);
        if (value == FalseObject || value == NilObject) {
          while(jump--) ip++;
        }

        break;
      }
      case JIT: {
        Debugger_evaluate(state);
        ip++;
        int jump = *ip;
        debugi("JIT %i", jump);

        VALUE value = Stack_pop(STACK);
        if (value != FalseObject && value != NilObject) {
          while(jump--) ip++;
        }

        break;
      }
      case GOTO: {
        Debugger_evaluate(state);
        ip++;
        int jump = *ip - 2;

        debugi("GOTO %i", jump);

        ip = CURR_FRAME->fn->code;
        while(jump--) ip++;

        break;
      }
      case GETSLOT: {
        Debugger_evaluate(state);
        ip++;
        debugi("GETSLOT %i", *ip);
        VALUE receiver = Stack_pop(STACK);
        VALUE slot     = LITERAL(*ip);

        check(receiver->type != NilType, "Tried to get a slot from nil.");
        check(slot->type == StringType, "Slot name must be a String.");

        VALUE value = Value_get(receiver, VAL2STR(slot));
        check(value, "Undefined slot %s on object type %i.", VAL2STR(slot), receiver->type);

        Stack_push(STACK, value);
        break;
      }
      case SETSLOT: {
        Debugger_evaluate(state);
        ip++;
        debugi("SETSLOT %i", *ip);
        VALUE value    = Stack_pop(STACK);
        VALUE receiver = Stack_pop(STACK);
        VALUE slot     = LITERAL(*ip);

        check(receiver->type != NilType, "Tried to set a slot on nil.");
        check(slot->type == StringType, "Slot name must be a String.");

        Value_set(state, receiver, VAL2STR(slot), value);
        Stack_push(STACK, value); // push the rhs back to the stack
        break;
      }
      case DEFN: {
        Debugger_evaluate(state);
        ip++;
        debugi("DEFN %i", *ip);
        VALUE fn_name = LITERAL(*ip);
        bstring state_fn = bfromcstr(VAL2STR(fn_name));
        VALUE closure = Closure_new(state, STATE_FN(state_fn), CURR_FRAME);
        bdestroy(state_fn);
        Stack_push(STACK, closure);
        break;
      }
      case MAKEVEC: {
        Debugger_evaluate(state);
        ip++;
        debugi("MAKEVEC %i", *ip);
        int count = *ip;
        DArray *array = DArray_create(sizeof(VALUE), count || 1);

        while(count--) {
          VALUE elem = Stack_pop(STACK);
          check(elem, "Stack underflow.");
          GC_protect(elem);
          DArray_push(array, elem);
        }

        VALUE vector = Vector_new(state, array);
        Stack_push(STACK, vector);
        Vector_each(vector, ^ void (VALUE element) {
          GC_unprotect(element);
        });
        break;
      }
      case SEND: {
        Debugger_evaluate(state);
        ip++;
        int op1 = *ip;
        ip++;
        int op2 = *ip;

        debugi("SEND %i %i", op1, op2);

        VALUE name = LITERAL(op1);
        int argcount = op2;

        DArray *locals = DArray_create(sizeof(VALUE), argcount+1);
        while(argcount--) {
          DArray_push(locals, Stack_pop(STACK));
        }
        VALUE receiver = Stack_pop(STACK);

        // Special chicken-egg case. We cannot define "apply" as a native method
        // on Closure, since that triggers the creation of a new closure ad
        // infinitum, so we have to handle this special function here.
        if(receiver->type == ClosureType &&
           strcmp(VAL2STR(name), "apply") == 0) {

          state->ret = ip; // save where we want to return
          ip = Function_call(state, VAL2FN(receiver), CURR_FRAME->self, locals, VAL2STR(name));
          break;
        }

        VALUE closure = Value_get(receiver, VAL2STR(name));
        check(closure, "Undefined slot %s on object type %i.", VAL2STR(name), receiver->type);

        if (closure->type != ClosureType && closure != NilObject) {
          // GETSLOT
          Stack_push(STACK, closure);
          DArray_destroy(locals);
          break;
        }

#ifdef OPTIMIZE_SEND
        if(op2 == 1 && strcmp(VAL2STR(name), "[]") == 0) { // getslot
          VALUE key = (VALUE)DArray_at(locals, 0);
          Stack_push(STACK, Value_get(receiver, VAL2STR(key)));
          DArray_destroy(locals);
          break;
        }

        if(op2 == 2 && strcmp(VAL2STR(name), "[]=") == 0) { // setslot
          VALUE key   = (VALUE)DArray_at(locals, 0);
          VALUE value = (VALUE)DArray_at(locals, 1);
          Value_set(receiver, VAL2STR(key), value);
          Stack_push(STACK, value);
          DArray_destroy(locals);
          break;
        }
#endif

        state->ret = ip; // save where we want to return
        ip = Function_call(state, VAL2FN(closure), receiver, locals, VAL2STR(name));
        break;
      }
      case PUSHLOBBY: {
        Debugger_evaluate(state);
        debugi("PUSHLOBBY");
        Stack_push(STACK, state->lobby);
        break;
      }
      case PUSHSELF: {
        Debugger_evaluate(state);
        debugi("PUSHSELF");
        Stack_push(STACK, CURR_FRAME->self);
        break;
      }
      case PUSHLOCAL: {
        Debugger_evaluate(state);
        ip++;
        Stack_push(STACK, LOCAL(*ip));
        debugi("PUSHLOCAL %i", *ip);
        break;
      }
      case PUSHLOCALDEPTH: {
        Debugger_evaluate(state);
        ip++;
        int depth = *ip;
        ip++;
        Stack_push(STACK, DEEPLOCAL(depth, *ip));
        debugi("PUSHLOCALDEPTH %i %i", depth, *ip);
        break;
      }
      case SETLOCAL: {
        Debugger_evaluate(state);
        ip++;
        debugi("SETLOCAL %i", *ip);
        LOCALSET(*ip, Stack_peek(STACK));
        break;
      }
      case SETLOCALDEPTH: {
        Debugger_evaluate(state);
        ip++;
        int depth = *ip;
        ip++;
        debugi("SETLOCAL %i %i", depth, *ip);
        DEEPLOCALSET(depth, *ip, Stack_peek(STACK));
        break;
      }
      case POP: {
        Debugger_evaluate(state);
        ip++;
        int count = *ip;
        debugi("POP %i", count);
        check(Stack_count(STACK) >= count, "Stack underflow.");
        while(count--) Stack_pop(STACK);
        break;
      }
      case RET: {
        Debugger_evaluate(state);
        debugi("RET");
        CallFrame *old_frame = Stack_pop(FRAMES);

        ip = old_frame->ret;

        CallFrame_destroy(old_frame);

        check(Stack_count(STACK) > 0, "Stack underflow.");

        if (ip == NULL) return Stack_pop(STACK); // if there's nowhere to return, exit

        break;
      }
      case DUMP: {
        Debugger_evaluate(state);
        debugi("DUMP");
        Stack_print(state, STACK);
        DArray *literals = CURR_FRAME->fn->literals;
        printf("--LITERALS (%i)--\n", DArray_count(literals));
        Value_print_all(state, literals);

        DArray *locals = CURR_FRAME->locals;
        printf("--LOCALS (%i)--\n", DArray_count(locals));
        Value_print_all(state, locals);
        break;
      }
    }
Пример #3
0
Файл: eval.c Проект: 7hens/yas
// ================================================================================================
// Procedure_eval
// ================================================================================================
Value Procedure_eval (Procedure self, Exp exp) {
	if (!(self && exp)) return NULL;
	/*
	if (exp->type != COMMA_EXP) {
		printf("%s: %d, %s\n", at_currentInterpreter->filePath->u.string, exp->lineno, ExpD_toString(exp));
	}
	*/
	at_currentInterpreter->currentExp = exp;
	switch (exp->type) {
		case VALUE_EXP:
			return exp->u.value;
		case IDENTIFIER_EXP:
			return _get(self, exp->u.value);
		case OBJECT_EXP:
			return _evalTrue(self, exp->u.unary);
		case ABS_EXP:case MINUS_EXP:
			return _evalAbs(self, exp->type, exp->u.unary);
		case NOT_EXP:
			return _EVAL(exp->u.unary) ? NULL : at_True;
		case RETURN_EXP:case RETURN_IF_EXP:case RETURN_UNLESS_EXP:
		case BREAK_EXP:case BREAK_IF_EXP:case BREAK_UNLESS_EXP:
		case CONTINUE_EXP:case CONTINUE_IF_EXP:case CONTINUE_UNLESS_EXP: 
			return _evalBreak(self, exp->type, exp->u.unary);
		case AND_EXP:case OR_EXP:
		case EQ_EXP:case NE_EXP:case GT_EXP:case GE_EXP:case LT_EXP:case LE_EXP:
		case CAT_EXP:case ADD_EXP:case SUB_EXP:case MUL_EXP:case DIV_EXP:
			return _evalMath(self, exp->type, exp->u.binary->a, exp->u.binary->b);
		case ASSIGN_EXP:
			//printf("debug: %s\n", ExpD_toString(exp));
			return _evalAssign(self, exp->u.binary->a, _EVAL(exp->u.binary->b));
		case AND_ASSIGN_EXP:case OR_ASSIGN_EXP:
		case EQ_ASSIGN_EXP:case NE_ASSIGN_EXP:
		case GT_ASSIGN_EXP:case GE_ASSIGN_EXP:case LT_ASSIGN_EXP:case LE_ASSIGN_EXP:
		case CAT_ASSIGN_EXP:case ADD_ASSIGN_EXP:case SUB_ASSIGN_EXP:case MUL_ASSIGN_EXP:case DIV_ASSIGN_EXP:
			//printf("debug: %s\n", ExpD_toString(exp));
			return _evalAssign(self, exp->u.binary->a,
				_evalMath(self, ExpType_assign2(exp->type), exp->u.binary->a, exp->u.binary->b));
		case REQUIRE_EXP:
			return _evalRequire(_EVAL(exp->u.unary));
		case AT_EXP:
			if (!exp->u.unary) return self->at;
			return Value_get(self->at, _EVAL(exp->u.unary));
		case ME_EXP:
			if (!exp->u.unary) return self->me;
			return Value_get(self->me, _EVAL(exp->u.unary));
		case MEMBER_EXP:
			return Value_get(_EVAL(exp->u.binary->a), _EVAL(exp->u.binary->b));
		case CALL_EXP:
			return _evalCall(self, exp->u.binary->a, exp->u.binary->b);
		case COMMA_EXP:
			return _evalComma(self, exp->u.binary->a, exp->u.binary->b);
		case CASE_EXP:
			yyerror("syntax error: unexpected case operator.");
			return NULL;
		case COLON_EXP:
			yyerror("syntax error: unexpected colon operator.");
			return NULL;
		case TO_EXP:case LESS_TO_EXP:
			return _evalTo(self, exp->type, exp->u.ternary->a, exp->u.ternary->b, exp->u.ternary->c);
		case ACCESSOR_EXP:
			//printf("debug: %s\n", ExpD_toString(exp));
			return _evalAssign(self, exp->u.binary->a, Value_functionAccessor(self, exp->u.binary->b));
		case FUNCTION_EXP:
			return Value_function(self, exp);
		case WHILE_EXP:case UNTIL_EXP:
			return _evalWhile(Procedure_new(self, self->assoc, self->at, self->me, exp));
		case IN_EXP:case IN_OWN_EXP:
			return _evalForeach(Procedure_new(self, self->assoc, self->at, self->me, exp));
		case IF_EXP:
			return _EVAL(_EVAL(exp->u.ternary->a) ? exp->u.ternary->b : exp->u.ternary->c);
		case SWITCH_EXP:
			return _evalSwitch(self, exp->u.ternary->a, exp->u.ternary->b, exp->u.ternary->c);
		default:
			yyerror("syntax error: unknown expression");
			return NULL;
	}
}