예제 #1
0
파일: Vm.cpp 프로젝트: sourya7/tealang
void Vm::execCode(const SCodeObject &c) {
  Vm::pushCodeObject(c);
  // TODO, if coStack_ is empty, push a NIL object
  // This is in case the user tries to assign a value to a void function call
  while (!coStack_.empty()) {
    if (*opId_ >= static_cast<int>(vecOp_->size())) {
      popCodeObject();
      continue;
    }
    SObject i;
    SObject j;

    Op op = (*vecOp_)[*opId_];
    Opc opc = op.opc_;
    switch (opc) {
    case Opc::ADD:
      DEBUG("OP::ADD");
      BIN_OP(+);
      break;
    case Opc::SUB:
      DEBUG("OP::SUB");
      BIN_OP(-);
      break;
    case Opc::UNARY_SUB:
      DEBUG("OP::UNARY_SUB");
      i = VM_POP();
      j = std::make_shared<IntegerObject>(0);
      VM_PUSH(*j - i);
      break;
    case Opc::MOD:
      DEBUG("OP::MOD");
      BIN_OP(% );
      break;
    case Opc::LT:
      DEBUG("OP::LT");
      BIN_OP(< );
      break;
    case Opc::GT:
      DEBUG("OP::GT");
      BIN_OP(> );
      break;
    case Opc::LEQ:
      DEBUG("OP::LEQ");
      BIN_OP(<= );
      break;
    case Opc::GEQ:
      DEBUG("OP::GEQ");
      BIN_OP(>= );
      break;
    case Opc::EQ:
      DEBUG("OP::EQ");
      BIN_OP(== );
      break;
    case Opc::AND:
      DEBUG("OP::AND");
      BIN_OP(&&);
      break;
    case Opc::OR:
      DEBUG("OP::OR");
      BIN_OP(|| );
      break;
    case Opc::NEQ:
      DEBUG("OP::NEQ");
      BIN_OP(!= );
      break;
    case Opc::MULT:
      DEBUG("OP::MULT");
      BIN_OP(*);
      break;
    case Opc::DIV:
      DEBUG("OP::DIV");
      BIN_OP(/ );
      break;
    case Opc::POWER: 
      DEBUG("OP::POWER"); 
      j = VM_POP();
      i = VM_POP();
      VM_PUSH(std::make_shared<DoubleObject>(pow(i->getDouble(), j->getDouble())));
      break;
    case Opc::WHILE: {
      DEBUG("OP::WHILE");
      assert(op.hasArgA());
      SCodeObject co = codeObject_->getChild(op.getArgA());
      co->setParent(codeObject_);
      pushCodeObject(co);
      continue;
    }
    /*TODO, Better to not have BREAK and CONTINUE in the vm. */
    case Opc::BREAK:
      DEBUG("OP::BREAK")
      while (codeObject_->getBlockType() != BlockType::WHILE) {
        popCodeObject();
      }
      popCodeObject();
      break;
    case Opc::CONTINUE:
      DEBUG("OP::CONTINUE")
      while (codeObject_->getBlockType() != BlockType::WHILE) {
        popCodeObject();
      }
      opId_ = 0;
      continue;
    case Opc::LOAD_CONSTANT:
      DEBUG("OP::PUSH_CONSTANT");
      assert(op.hasArgA());
      i = codeObject_->getConst(op.getArgA());
      VM_PUSH(i);
      break;
    case Opc::LOAD_VALUE:
      DEBUG("OP::LOAD_VALUE");
      assert(op.hasStr());
      i = codeObject_->getValue(op.getStr());
      assert(i != nullptr);
      VM_PUSH(i);
      break;
    case Opc::STORE_VALUE:
      DEBUG("OP::STORE_VALUE");
      assert(op.hasStr());
      i = VM_POP();
      codeObject_->storeValue(op.getStr(), i);
      break;
    case Opc::JMP_IF_ELSE: {
      DEBUG("OP::JMP_IF_ELSE");
      INCR_OP();
      assert(op.hasArgA());
      auto v = VM_POP();
      if (v->isTrue()) {
        SCodeObject ic = codeObject_->getChild(op.getArgA());
        ic->setParent(codeObject_);
        pushCodeObject(ic);
      } else {
        if (op.hasArgB()) {
          SCodeObject ec = codeObject_->getChild(op.getArgB());
          ec->setParent(codeObject_);
          pushCodeObject(ec);
        }
      }
      continue;
    }
    case Opc::INIT_INSTANCE: {
      auto classCo = codeObject_->getParent();
      auto classO = std::make_shared<ClassObject>(classCo);
      VM_PUSH(classO);
      INCR_OP();
      continue;
    }
    case Opc::CALL_METHOD: {
      DEBUG("OP::CALL_METHOD");
      INCR_OP();
      auto method = VM_POP();
      auto instance = VM_POP();
      Vm::callMethod(instance, method);
      continue;
    }
    case Opc::DOT: {
      DEBUG("OP::DOT");
      i = VM_POP();
      j = VM_POP();
      Vm::getMethodProp(j, i);
      break;
    }
    case Opc::CALL: {
      DEBUG("OP::CALL");
      assert(op.hasStr());
      auto fnob = codeObject_->getValue(op.getStr());
      assert(fnob != nullptr);
      INCR_OP();
      Vm::callFunc(fnob);
      continue;
    }
    case Opc::RETURN: {
      // TODO, clean the stack
      assert(op.hasArgA());
      DEBUG("OP::RETURN");
      while (codeObject_->getBlockType() != BlockType::FUNCTION) {
        popCodeObject();
      }
      popCodeObject();
      continue;
    }

    default:
      assert(false && "Not Implemented Yet!");
      break;
    }
    INCR_OP(); // increment the op
  }            // end switch, end for
}
예제 #2
0
SObject IntegerObject::operator/(const SObject &rhs) {
  return std::make_shared<DoubleObject>(getInt() / rhs->getDouble());
}