llvm::Value* MemberAccess::getPointer(Context &context) { if (isStatic) { // find class Class *cls = targetClass->getClass(context); if (!cls) throw SymbolNotFound("No such class '" + targetClass->getName() + "'"); if (cls->getMangleName()[0] == 'J') throw InvalidType("'" + cls->getFullName() + "' is an interface"); // find symbol Symbol *symbol = cls->findSymbol(identifier->getName()); if (!symbol) throw SymbolNotFound("No such static member '" + identifier->getName() + "' in class '" + cls->getFullName() + "'"); if (symbol->type != Symbol::STATIC_MEMBER_VAR) throw InvalidType("'" + identifier->getName() + "' in '" + targetClass->getName() + "' is not a static member variable"); // check permission if (symbol->data.identifier.isPrivate && cls != context.currentClass) throw CompileException("'" + identifier->getName() + "' is private"); if (symbol->data.identifier.isProtected && !Class::isA(context.currentClass, cls)) throw CompileException("'" + identifier->getName() + "' is protected"); return symbol->data.identifier.value; } else { // find class if (!target->getType(context)->isObject()) throw InvalidType(std::string("Access member of a ") + target->getType(context)->getName()); Class *cls = target->getType(context)->getClass(); // find symbol Symbol *symbol = cls->findSymbol(identifier->getName()); if (!symbol) throw SymbolNotFound(std::string("No such member variable in class ") + cls->getName()); if (symbol->type != Symbol::MEMBER_VAR) throw InvalidType("'" + identifier->getName() + "' in '" + targetClass->getName() + "' is not a member variable"); // check permission if (symbol->data.identifier.isPrivate && cls != context.currentClass) throw CompileException("'" + identifier->getName() + "' is private"); if (symbol->data.identifier.isProtected && !Class::isA(context.currentClass, cls)) throw CompileException("'" + identifier->getName() + "' is protected"); return addDebugLoc( context, context.getBuilder().CreateStructGEP( nullptr, target->load(context), symbol->data.member.index), loc); } }
Type* MemberAccess::getType(Context &context) { if (isStatic) { Class *cls = targetClass->getClass(context); if (!cls) throw SymbolNotFound("No such class '" + targetClass->getName() + "'"); if (cls->getMangleName()[0] == 'J') throw InvalidType("'" + cls->getFullName() + "' is an interface"); Symbol *symbol = cls->findSymbol(identifier->getName()); if (!symbol) throw SymbolNotFound("No such static member '" + identifier->getName() + "' in class '" + cls->getFullName() + "'"); return symbol->data.identifier.type; } else { if (!target->getType(context)->isObject()) throw InvalidType(std::string("Access member of a ") + target->getType(context)->getName()); Class *cls = target->getType(context)->getClass(); Symbol *symbol = cls->findSymbol(identifier->getName()); if (!symbol) throw SymbolNotFound(std::string("No such member variable in class ") + cls->getName()); return symbol->data.member.type; } }
JValue::ObjectIterator::ObjectIterator(jvalue_ref parent) : _parent(0) , _at_end(false) { _key_value.key = 0; _key_value.value = 0; if (UNLIKELY(!jobject_iter_init(&_it, parent))) throw InvalidType("Can't iterate over non-object"); _parent = jvalue_copy(parent); _at_end = !jobject_iter_next(&_it, &_key_value); }
Attribute::Attribute(std::string n, int in) throw (InvalidType, EmptyName){ while(!n.empty()) //strip space { if(n.at(0) == ' ') n.erase(0,0); else break; } if(n.empty()) throw EmptyName(); name=n; if( in > 5 || in < 0) throw InvalidType(); ident=in; }
void PathHandler::isRegularFile() const { if (exists(path_)) { if (!is_regular_file(path_)) { if (is_directory(path_)) { throw InvalidType(std::string("Error in ") + "\"PathHandler::isRegularFile\":\n " + path_.generic_string() + "\n is a directory, not a file."); } else { throw InvalidType(std::string("Error in ") + "\"PathHandler::isRegularFile\":\n " + path_.generic_string() + "\n exists but it is neither a regular file nor a directory."); } } } else { throw NonExistent(std::string("Error in ") + "\"PathHandler::isRegularFile\":\n " + path_.generic_string() + "\n does not exist."); } }
void PathHandler::isRootFilename() const { if (is_directory(path_)) { throw InvalidType(std::string("Error in ") + "\"PathHandler::isRootFilename\":\n " + path_.generic_string() + "\n is a directory, not a root filename."); } else { if (!is_directory(path_.parent_path())) { throw NonExistent(std::string("Error in ") + "\"PathHandler::isRootFilename\":\n " + "The parent path of the output root filename is\n " + path_.parent_path().generic_string() + "\n This is not an existing directory."); } } }
Type* FunctionCall::getType(Context &context) { Symbol *symbol = NULL; if (target) symbol = target->getType(context)->getClass()->findSymbol(identifier->getName()); else if (identifier->getName().rfind("::") != std::string::npos) { Class *targetClass = context.findClass(identifier->getName().substr(0, identifier->getName().rfind("::"))); if (!targetClass) throw SymbolNotFound(identifier->getName().substr(0, identifier->getName().rfind("::"))); symbol = targetClass->findSymbol(identifier->getName().substr(identifier->getName().rfind("::") + 2)); } else symbol = context.currentClass->findSymbol(identifier->getName()); if (!symbol) throw SymbolNotFound(identifier->getName()); switch (symbol->type) { case Symbol::STATIC_FUNCTION: return symbol->data.static_function.function->getReturnType(); case Symbol::FUNCTION: return symbol->data.function.function->getReturnType(); default: throw InvalidType("calling a symbol which is not a function"); } }
llvm::Value* FunctionCall::load(Context &context) { std::vector<Type*> actual_type; for (std::list<Expression*>::iterator it = arg_list.begin(); it != arg_list.end(); it++) actual_type.push_back((*it)->getType(context)); Symbol *symbol = NULL; Class *targetClass = NULL; if (target == NULL) { // static call or self call if (identifier->getName().rfind("::") != std::string::npos) { // static call // find class targetClass = context.findClass(identifier->getName().substr(0, identifier->getName().rfind("::"))); if (!targetClass) throw SymbolNotFound("Class '" + identifier->getName().substr(0, identifier->getName().rfind("::")) + "'"); // find function symbol = targetClass->findSymbol(identifier->getName().substr(identifier->getName().rfind("::") + 2)); if (!symbol) throw SymbolNotFound("Function '" + identifier->getName() + "'"); // match the best override symbol = bestMatch(symbol, actual_type, context); if (!symbol) throw SymbolNotFound("No matching call for '" + Function::genName(identifier->getName(), actual_type) + "'"); // check symbol is static function if (symbol->type != Symbol::STATIC_FUNCTION) throw InvalidType("'" + symbol->data.function.function->getName() + "' is not a static function"); // check symbol's permission if (symbol->data.static_function.isPrivate && targetClass != context.currentClass) throw CompileException("function '" + symbol->data.static_function.function->getName() + "' is private"); if (symbol->data.static_function.isProtected && !Class::isA(context.currentClass, targetClass)) throw CompileException("function '" + symbol->data.static_function.function->getName() + "' is protected"); } else { // self call targetClass = context.currentClass; // find function symbol = targetClass->findSymbol(identifier->getName()); if (!symbol) throw SymbolNotFound("'" + identifier->getName() + "'"); symbol = bestMatch(symbol, actual_type, context); if (!symbol) throw SymbolNotFound("No matching call for '" + Function::genName(identifier->getName(), actual_type) + "'"); } } else { // member function call targetClass = target->getType(context)->getClass(); // find function symbol = targetClass->findSymbol(identifier->getName()); if (!symbol) throw SymbolNotFound("Function '" + identifier->getName() + "'"); symbol = bestMatch(symbol, actual_type, context); if (!symbol) throw SymbolNotFound("No matching call for '" + Function::genName(identifier->getName(), actual_type) + "'"); // check symbol is normal function if (symbol->type != Symbol::FUNCTION) throw InvalidType("function '" + symbol->data.static_function.function->getName() + "' is not a member function"); // check symbol's permission if (symbol->data.static_function.isPrivate && targetClass != context.currentClass) throw CompileException("function '" + symbol->data.static_function.function->getName() + "' is private"); if (symbol->data.static_function.isProtected && !Class::isA(context.currentClass, targetClass)) throw CompileException("function '" + symbol->data.static_function.function->getName() + "' is protected"); } llvm::Value *function; std::vector<llvm::Value*> arg_code; switch (symbol->type) { case Symbol::FUNCTION: { Expression *tmpTarget = target ? target : new Identifier("this"); if (!tmpTarget->getType(context)->isObject()) throw InvalidType(std::string("calling a function of ") + tmpTarget->getType(context)->getName()); llvm::Value *thisval = tmpTarget->load(context); if (!target) delete tmpTarget; if (targetClass->getMangleName()[0] == 'J') { // locate vtable function = addDebugLoc( context, context.getBuilder().CreateLoad( thisval ), loc ); // for interface call, we have to recalculate the object base address // load offset from vtable llvm::Value *baseOffset = addDebugLoc( context, context.getBuilder().CreateLoad( addDebugLoc( context, context.getBuilder().CreateStructGEP( nullptr, function, 0 ), loc ) ), loc ); // calculate the base address thisval = addDebugLoc( context, context.getBuilder().CreateIntToPtr( addDebugLoc( context, context.getBuilder().CreateSub( addDebugLoc( context, context.getBuilder().CreatePtrToInt( thisval, context.getBuilder().getInt32Ty() ), loc ), baseOffset ), loc ), context.getBuilder().getInt8PtrTy(0) ), loc ); } else { // locate vtable function = addDebugLoc( context, context.getBuilder().CreateLoad( addDebugLoc( context, context.getBuilder().CreateStructGEP( nullptr, thisval, symbol->data.function.vtableOffset ), loc ) ), loc ); // for object call, we only need type cast thisval = context.getBuilder().CreatePointerCast( thisval, context.getBuilder().getInt8PtrTy(0) ); } // add thisval as the first argument arg_code.push_back(thisval); // load function pointer from vtable function = addDebugLoc( context, context.getBuilder().CreateLoad( addDebugLoc( context, context.getBuilder().CreateStructGEP( nullptr, function, symbol->data.function.funcPtrOffset ), loc ) ), loc ); break; } case Symbol::STATIC_FUNCTION: function = symbol->data.static_function.function->getLLVMFunction(context); if (target) throw CompileException("Calling a static function of an object"); break; default: throw InvalidType("calling a symbol which is not a function"); } // load remaining arguments { Function *func = symbol->type == Symbol::FUNCTION ? symbol->data.function.function : symbol->data.static_function.function; Function::arg_iterator it2 = func->arg_begin(); for (std::list<Expression*>::iterator it = arg_list.begin(); it != arg_list.end(); it++, it2++) arg_code.push_back(Type::cast(context, (*it)->getType(context), (*it)->load(context), it2->first)); } // do the call llvm::Value *ans = addDebugLoc( context, context.getBuilder().CreateCall(function, llvm::ArrayRef<llvm::Value*>(arg_code)), loc); return ans; }
llvm::Value* Op2::load(Context &context) { if (op == ASSIGN) { llvm::Value *tmp = right->load(context); tmp = Type::cast(context, right->getType(context), tmp, left->getType(context)); addDebugLoc( context, left->store(context, tmp), loc); return tmp; } Type *ansType = Type::higherType(left->getType(context), right->getType(context)); llvm::Value *lhs = Type::cast(context, left->getType(context), left->load(context), ansType); llvm::Value *rhs = Type::cast(context, right->getType(context), right->load(context), ansType); // pre type check switch (op) { case ADD: case ADD_ASSIGN: case SUB: case SUB_ASSIGN: case MUL: case MUL_ASSIGN: case DIV: case DIV_ASSIGN: case PWR: case PWR_ASSIGN: case MOD: case MOD_ASSIGN: case LT: case GT: case LEQ: case GEQ: case EQ: case NEQ: if (!ansType->isNumber() && !ansType->isString()) throw InvalidType(std::string("can't apply operator ") + OpNames[op] + " to " + left->getType(context)->getName() + " and " + right->getType(context)->getName()); break; case LSH: case LSH_ASSIGN: case RSH: case RSH_ASSIGN: case BIT_OR: case BIT_OR_ASSIGN: case BIT_AND: case BIT_AND_ASSIGN: case BIT_XOR: case BIT_XOR_ASSIGN: if (!ansType->isInt()) throw InvalidType(std::string("can't apply operator ") + OpNames[op] + " to " + left->getType(context)->getName() + " and " + right->getType(context)->getName()); break; case LOG_OR: case LOG_OR_ASSIGN: case LOG_AND: case LOG_AND_ASSIGN: case LOG_XOR: case LOG_XOR_ASSIGN: if (!ansType->isBool()) throw InvalidType(std::string("can't apply operator ") + OpNames[op] + " to " + left->getType(context)->getName() + " and " + right->getType(context)->getName()); break; case ASSIGN: // this has been handled before break; } switch (op) { case ADD_ASSIGN: case ADD: { llvm::Value *tmp; if (ansType->isFloat()) tmp = addDebugLoc(context, context.getBuilder().CreateFAdd(lhs, rhs), loc); else tmp = addDebugLoc(context, context.getBuilder().CreateAdd(lhs, rhs), loc); if (hasAssign(op)) { tmp = Type::cast(context, ansType, tmp, left->getType(context)); addDebugLoc( context, left->store(context, tmp), loc); } return tmp; } case SUB_ASSIGN: case SUB: { llvm::Value *tmp; if (ansType->isFloat()) tmp = addDebugLoc(context, context.getBuilder().CreateFSub(lhs, rhs), loc); else tmp = addDebugLoc(context, context.getBuilder().CreateSub(lhs, rhs), loc); if (hasAssign(op)) { tmp = Type::cast(context, ansType, tmp, left->getType(context)); addDebugLoc( context, left->store(context, tmp), loc); } return tmp; } case MUL_ASSIGN: case MUL: { llvm::Value *tmp; if (ansType->isFloat()) tmp = addDebugLoc(context, context.getBuilder().CreateFMul(lhs, rhs), loc); else tmp = addDebugLoc(context, context.getBuilder().CreateMul(lhs, rhs), loc); if (hasAssign(op)) { tmp = Type::cast(context, ansType, tmp, left->getType(context)); addDebugLoc( context, left->store(context, tmp), loc); } return tmp; } case DIV_ASSIGN: case DIV: { llvm::Value *tmp; if (ansType->isFloat()) tmp = addDebugLoc(context, context.getBuilder().CreateFDiv(lhs, rhs), loc); else if (ansType->isUnsigned) tmp = addDebugLoc(context, context.getBuilder().CreateUDiv(lhs, rhs), loc); else tmp = addDebugLoc(context, context.getBuilder().CreateSDiv(lhs, rhs), loc); if (hasAssign(op)) { tmp = Type::cast(context, ansType, tmp, left->getType(context)); addDebugLoc( context, left->store(context, tmp), loc); } return tmp; } case MOD_ASSIGN: case MOD: { llvm::Value *tmp; if (ansType->isUnsigned) tmp = addDebugLoc(context, context.getBuilder().CreateURem(lhs, rhs), loc); else tmp = addDebugLoc(context, context.getBuilder().CreateSRem(lhs, rhs), loc); if (hasAssign(op)) { tmp = Type::cast(context, ansType, tmp, left->getType(context)); addDebugLoc( context, left->store(context, tmp), loc); } return tmp; } case LSH_ASSIGN: case LSH: { llvm::Value *tmp = addDebugLoc(context, context.getBuilder().CreateShl(lhs, rhs), loc); if (hasAssign(op)) { tmp = Type::cast(context, ansType, tmp, left->getType(context)); addDebugLoc( context, left->store(context, tmp), loc); } return tmp; } case RSH_ASSIGN: case RSH: { llvm::Value *tmp; if (ansType->isUnsigned) tmp = addDebugLoc(context, context.getBuilder().CreateLShr(lhs, rhs), loc); else tmp = addDebugLoc(context, context.getBuilder().CreateAShr(lhs, rhs), loc); if (hasAssign(op)) { tmp = Type::cast(context, ansType, tmp, left->getType(context)); addDebugLoc( context, left->store(context, tmp), loc); } return tmp; } case LT: if (ansType->isFloat()) return addDebugLoc(context, context.getBuilder().CreateFCmpOLT(lhs, rhs), loc); else if (ansType->isInt()) { if (ansType->isUnsigned) return addDebugLoc(context, context.getBuilder().CreateICmpULT(lhs, rhs), loc); else return addDebugLoc(context, context.getBuilder().CreateICmpSLT(lhs, rhs), loc); } else if (ansType->isString()) throw NotImplemented("comparison of string"); break; case LEQ: if (ansType->isFloat()) return addDebugLoc(context, context.getBuilder().CreateFCmpOLE(lhs, rhs), loc); else if (ansType->isInt()) { if (ansType->isUnsigned) return addDebugLoc(context, context.getBuilder().CreateICmpULE(lhs, rhs), loc); else return addDebugLoc(context, context.getBuilder().CreateICmpSLE(lhs, rhs), loc); } else if (ansType->isString()) throw NotImplemented("comparison of string"); break; case GT: if (ansType->isFloat()) return addDebugLoc(context, context.getBuilder().CreateFCmpOGT(lhs, rhs), loc); else if (ansType->isInt()) { if (ansType->isUnsigned) return addDebugLoc(context, context.getBuilder().CreateICmpUGT(lhs, rhs), loc); else return addDebugLoc(context, context.getBuilder().CreateICmpSGT(lhs, rhs), loc); } else if (ansType->isString()) throw NotImplemented("comparison of string"); break; case GEQ: if (ansType->isFloat()) return addDebugLoc(context, context.getBuilder().CreateFCmpOGE(lhs, rhs), loc); else if (ansType->isInt()) { if (ansType->isUnsigned) return addDebugLoc(context, context.getBuilder().CreateICmpUGE(lhs, rhs), loc); else return addDebugLoc(context, context.getBuilder().CreateICmpSGE(lhs, rhs), loc); } else if (ansType->isString()) throw NotImplemented("comparison of string"); break; case ASSIGN: // this has been handled before break; case EQ: if (ansType->isFloat()) return addDebugLoc(context, context.getBuilder().CreateFCmpOEQ(lhs, rhs), loc); else if (ansType->isInt()) return addDebugLoc(context, context.getBuilder().CreateICmpEQ(lhs, rhs), loc); else if (ansType->isString()) throw NotImplemented("comparison of string"); break; case NEQ: if (ansType->isFloat()) return addDebugLoc(context, context.getBuilder().CreateFCmpONE(lhs, rhs), loc); else if (ansType->isInt()) return addDebugLoc(context, context.getBuilder().CreateICmpNE(lhs, rhs), loc); else if (ansType->isString()) throw NotImplemented("comparison of string"); break; case LOG_AND_ASSIGN: case BIT_AND_ASSIGN: case LOG_AND: case BIT_AND: { llvm::Value *tmp = context.getBuilder().CreateAnd(lhs, rhs); if (hasAssign(op)) { tmp = Type::cast(context, ansType, tmp, left->getType(context)); addDebugLoc( context, left->store(context, tmp), loc); } return tmp; } case LOG_OR_ASSIGN: case BIT_OR_ASSIGN: case LOG_OR: case BIT_OR: { llvm::Value *tmp = context.getBuilder().CreateOr(lhs, rhs); if (hasAssign(op)) { tmp = Type::cast(context, ansType, tmp, left->getType(context)); addDebugLoc( context, left->store(context, tmp), loc); } return tmp; } case LOG_XOR_ASSIGN: case BIT_XOR_ASSIGN: case LOG_XOR: case BIT_XOR: { llvm::Value *tmp = context.getBuilder().CreateXor(lhs, rhs); if (hasAssign(op)) { tmp = Type::cast(context, ansType, tmp, left->getType(context)); addDebugLoc( context, left->store(context, tmp), loc); } return tmp; } case PWR: case PWR_ASSIGN: throw NotImplemented(std::string("operator '") + OpNames[op] + "'"); } throw CompileException("Shouldn't reach here"); }
Expression::Constant Op2::loadConstant() { Type* higherType = Type::higherType(left->getTypeConstant(), right->getTypeConstant()); Expression::Constant ans; switch (op) { case ADD_ASSIGN: case SUB_ASSIGN: case MUL_ASSIGN: case DIV_ASSIGN: case MOD_ASSIGN: case PWR_ASSIGN: case BIT_OR_ASSIGN: case BIT_AND_ASSIGN: case BIT_XOR_ASSIGN: case LOG_OR_ASSIGN: case LOG_AND_ASSIGN: case LOG_XOR_ASSIGN: case LSH_ASSIGN: case RSH_ASSIGN: throw InvalidType(std::string("can't apply operator ") + OpNames[op] + " to constant"); default: break; } if (higherType->isInt()) if (higherType->isUnsigned) switch (op) { case ADD: if (left->getTypeConstant()->isUnsigned) ans._uint64 = left->loadConstant()._uint64; else ans._uint64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._uint64 += right->loadConstant()._uint64; else ans._uint64 += right->loadConstant()._int64; return ans; case SUB: if (left->getTypeConstant()->isUnsigned) ans._uint64 = left->loadConstant()._uint64; else ans._uint64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._uint64 -= right->loadConstant()._uint64; else ans._uint64 -= right->loadConstant()._int64; return ans; case MUL: if (left->getTypeConstant()->isUnsigned) ans._uint64 = left->loadConstant()._uint64; else ans._uint64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._uint64 *= right->loadConstant()._uint64; else ans._uint64 *= right->loadConstant()._int64; return ans; case DIV: if (left->getTypeConstant()->isUnsigned) ans._uint64 = left->loadConstant()._uint64; else ans._uint64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._uint64 /= right->loadConstant()._uint64; else ans._uint64 /= right->loadConstant()._int64; return ans; case MOD: if (left->getTypeConstant()->isUnsigned) ans._uint64 = left->loadConstant()._uint64; else ans._uint64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._uint64 %= right->loadConstant()._uint64; else ans._uint64 %= right->loadConstant()._int64; return ans; case PWR: if (left->getTypeConstant()->isUnsigned) ans._uint64 = left->loadConstant()._uint64; else ans._uint64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._uint64 = pow(ans._uint64, right->loadConstant()._uint64); else ans._uint64 = pow(ans._uint64, right->loadConstant()._int64); return ans; case LT: if (left->getTypeConstant()->isUnsigned) ans._uint64 = left->loadConstant()._uint64; else ans._uint64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._bool = ans._uint64 < right->loadConstant()._uint64; else ans._bool = ans._uint64 < right->loadConstant()._int64; return ans; case LEQ: if (left->getTypeConstant()->isUnsigned) ans._uint64 = left->loadConstant()._uint64; else ans._uint64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._bool = ans._uint64 <= right->loadConstant()._uint64; else ans._bool = ans._uint64 <= right->loadConstant()._int64; return ans; case GT: if (left->getTypeConstant()->isUnsigned) ans._uint64 = left->loadConstant()._uint64; else ans._uint64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._bool = ans._uint64 > right->loadConstant()._uint64; else ans._bool = ans._uint64 > right->loadConstant()._int64; return ans; case GEQ: if (left->getTypeConstant()->isUnsigned) ans._uint64 = left->loadConstant()._uint64; else ans._uint64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._bool = ans._uint64 >= right->loadConstant()._uint64; else ans._bool = ans._uint64 >= right->loadConstant()._int64; return ans; default: throw NotImplemented(std::string("operator ") + OpNames[op] + " not implemented"); } else switch (op) { case ADD: if (left->getTypeConstant()->isUnsigned) ans._int64 = left->loadConstant()._uint64; else ans._int64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._int64 += right->loadConstant()._uint64; else ans._int64 += right->loadConstant()._int64; return ans; case SUB: if (left->getTypeConstant()->isUnsigned) ans._int64 = left->loadConstant()._uint64; else ans._int64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._int64 -= right->loadConstant()._uint64; else ans._int64 -= right->loadConstant()._int64; return ans; case MUL: if (left->getTypeConstant()->isUnsigned) ans._int64 = left->loadConstant()._uint64; else ans._int64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._int64 *= right->loadConstant()._uint64; else ans._int64 *= right->loadConstant()._int64; return ans; case DIV: if (left->getTypeConstant()->isUnsigned) ans._int64 = left->loadConstant()._uint64; else ans._int64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._int64 /= right->loadConstant()._uint64; else ans._int64 /= right->loadConstant()._int64; return ans; case MOD: if (left->getTypeConstant()->isUnsigned) ans._int64 = left->loadConstant()._uint64; else ans._int64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._int64 %= right->loadConstant()._uint64; else ans._int64 %= right->loadConstant()._int64; return ans; case PWR: if (left->getTypeConstant()->isUnsigned) ans._int64 = left->loadConstant()._uint64; else ans._int64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._int64 = pow(ans._int64, right->loadConstant()._uint64); else ans._int64 = pow(ans._int64, right->loadConstant()._int64); return ans; case LT: if (left->getTypeConstant()->isUnsigned) ans._int64 = left->loadConstant()._uint64; else ans._int64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._bool = ans._int64 < right->loadConstant()._uint64; else ans._bool = ans._int64 < right->loadConstant()._int64; return ans; case LEQ: if (left->getTypeConstant()->isUnsigned) ans._int64 = left->loadConstant()._uint64; else ans._int64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._bool = ans._int64 <= right->loadConstant()._uint64; else ans._bool = ans._int64 <= right->loadConstant()._int64; return ans; case GT: if (left->getTypeConstant()->isUnsigned) ans._int64 = left->loadConstant()._uint64; else ans._int64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._bool = ans._int64 > right->loadConstant()._uint64; else ans._bool = ans._int64 > right->loadConstant()._int64; return ans; case GEQ: if (left->getTypeConstant()->isUnsigned) ans._int64 = left->loadConstant()._uint64; else ans._int64 = left->loadConstant()._int64; if (right->getTypeConstant()->isUnsigned) ans._bool = ans._int64 >= right->loadConstant()._uint64; else ans._bool = ans._int64 >= right->loadConstant()._int64; return ans; default: throw NotImplemented(std::string("operator ") + OpNames[op] + " not implemented"); } else if (higherType->isFloat()) switch (op) { case ADD: if (left->getTypeConstant()->isInt()) if (left->getTypeConstant()->isUnsigned) ans._double = left->loadConstant()._uint64; else ans._double = left->loadConstant()._int64; else ans._double = left->loadConstant()._double; if (right->getTypeConstant()->isFloat()) if (right->getTypeConstant()->isUnsigned) ans._double += right->loadConstant()._uint64; else ans._double += right->loadConstant()._int64; else ans._double += right->loadConstant()._double; return ans; case SUB: if (left->getTypeConstant()->isInt()) if (left->getTypeConstant()->isUnsigned) ans._double = left->loadConstant()._uint64; else ans._double = left->loadConstant()._int64; else ans._double = left->loadConstant()._double; if (right->getTypeConstant()->isFloat()) if (right->getTypeConstant()->isUnsigned) ans._double -= right->loadConstant()._uint64; else ans._double -= right->loadConstant()._int64; else ans._double -= right->loadConstant()._double; return ans; case MUL: if (left->getTypeConstant()->isInt()) if (left->getTypeConstant()->isUnsigned) ans._double = left->loadConstant()._uint64; else ans._double = left->loadConstant()._int64; else ans._double = left->loadConstant()._double; if (right->getTypeConstant()->isFloat()) if (right->getTypeConstant()->isUnsigned) ans._double *= right->loadConstant()._uint64; else ans._double *= right->loadConstant()._int64; else ans._double *= right->loadConstant()._double; return ans; case DIV: if (left->getTypeConstant()->isInt()) if (left->getTypeConstant()->isUnsigned) ans._double = left->loadConstant()._uint64; else ans._double = left->loadConstant()._int64; else ans._double = left->loadConstant()._double; if (right->getTypeConstant()->isFloat()) if (right->getTypeConstant()->isUnsigned) ans._double /= right->loadConstant()._uint64; else ans._double /= right->loadConstant()._int64; else ans._double /= right->loadConstant()._double; return ans; case LSH: case RSH: case MOD: throw InvalidType(std::string("can't apply operator ") + OpNames[op] + " to " + left->getTypeConstant()->getName() + " and " + right->getTypeConstant()->getName()); case LT: if (left->getTypeConstant()->isInt()) if (left->getTypeConstant()->isUnsigned) ans._double = left->loadConstant()._uint64; else ans._double = left->loadConstant()._int64; else ans._double = left->loadConstant()._double; if (right->getTypeConstant()->isInt()) if (right->getTypeConstant()->isUnsigned) ans._bool = ans._double < right->loadConstant()._uint64; else ans._bool = ans._double < right->loadConstant()._int64; else ans._bool = ans._double < right->loadConstant()._double; return ans; case LEQ: if (left->getTypeConstant()->isInt()) if (left->getTypeConstant()->isUnsigned) ans._double = left->loadConstant()._uint64; else ans._double = left->loadConstant()._int64; else ans._double = left->loadConstant()._double; if (right->getTypeConstant()->isInt()) if (right->getTypeConstant()->isUnsigned) ans._bool = ans._double <= right->loadConstant()._uint64; else ans._bool = ans._double <= right->loadConstant()._int64; else ans._bool = ans._double <= right->loadConstant()._double; return ans; case GT: if (left->getTypeConstant()->isInt()) if (left->getTypeConstant()->isUnsigned) ans._double = left->loadConstant()._uint64; else ans._double = left->loadConstant()._int64; else ans._double = left->loadConstant()._double; if (right->getTypeConstant()->isInt()) if (right->getTypeConstant()->isUnsigned) ans._bool = ans._double > right->loadConstant()._uint64; else ans._bool = ans._double > right->loadConstant()._int64; else ans._bool = ans._double > right->loadConstant()._double; return ans; case GEQ: if (left->getTypeConstant()->isInt()) if (left->getTypeConstant()->isUnsigned) ans._double = left->loadConstant()._uint64; else ans._double = left->loadConstant()._int64; else ans._double = left->loadConstant()._double; if (right->getTypeConstant()->isInt()) if (right->getTypeConstant()->isUnsigned) ans._bool = ans._double >= right->loadConstant()._uint64; else ans._bool = ans._double >= right->loadConstant()._int64; else ans._bool = ans._double >= right->loadConstant()._double; return ans; default: throw NotImplemented(std::string("operator ") + OpNames[op] + " not implemented"); } else if (higherType->isString()) throw NotImplemented("constant string calculate"); throw NotImplemented(std::string("constant caculation ") + left->getTypeConstant()->getName() + OpNames[op] + right->getTypeConstant()->getName()); }
void parser(action *lexems, int size) { stack<StackType> stackMemory; StackType buf; buf.code = S; buf.name = ""; stackMemory.push(buf); int i = 0; while(!stackMemory.empty()) { bool flag = false, f = false; buf = stackMemory.top(); if(i < size -1 ) print_el(array[i]), cout<<" ", print_el(array[i+1]); else print_el(array[i]); cout<<" ? "; print_stack(stackMemory); stackMemory.pop(); // cout<<" "<<lexems[i].id_name<<""<<endl; if(lexems[i].code == buf.code) { if(lexems[i].code == id || lexems[i].code == lable) f = true, i++; else if(lexems[i].id_name == buf.name) f = true, i++; } else switch(buf.code) { f = false; case S: if(lexems[i].code == keyword && lexems[i].id_name == "$") return; if(lexems[i].code == semicolon ) rules2(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "dim" ) rules1(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "set") rules2(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "do") rules2(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "for") rules2(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "if") rules2(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "cin") rules2(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "cout") rules2(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "goto") rules2(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "fail") rules2(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "select") rules2(stackMemory), f = true; if(lexems[i].code == lable) rules2(stackMemory), f = true; if(!f) throw InvalidBegin(); break; case X: if(lexems[i].code == keyword && lexems[i].id_name == "dim" ) rules3(stackMemory), f = true; if(!f) throw InvalidDeclaringVariables(); break; case X1: if(lexems[i].code == semicolon) { if(lexems[i+1].code == keyword && lexems[i+1].id_name == "$" ) rules6(stackMemory), f = true; if(lexems[i+1].code == keyword && lexems[i+1].id_name == "dim" ) rules7(stackMemory), f = true; if(!f) rules8(stackMemory), f = true; //if(lexems[i+1].code == keyword && lexems[i+1].id_name == "set") rules8(stackMemory), f = true; // if(lexems[i+1].code != keyword) rules8(stackMemory), f = true; //else rules8(stackMemory), f = true; } if(!f) throw InvalidType(); break; case G: if(lexems[i].code == id) { f = true; if(lexems[i+1].code == coma) rules10(stackMemory); else rules9(stackMemory); } if(!f) throw InvalidDeclaring(); break; case TYPE: if(lexems[i].code == keyword) { if(lexems[i].id_name == "BV") rules5(stackMemory), f = true; if(lexems[i].id_name == "INT") rules4(stackMemory), f = true; } if(!f) throw InvalidType(); break; case P: if(lexems[i].code == semicolon ) if(lexems[i+1].code == keyword && lexems[i+1].id_name == "$" ) rules11(stackMemory), f = true; if(lexems[i+1].code == keyword && lexems[i+1].id_name == "case" ) rules11(stackMemory), f = true; if(lexems[i+1].code == keyword && lexems[i+1].id_name == "ni" ) rules11(stackMemory), f = true; if(lexems[i+1].code == keyword && lexems[i+1].id_name == "otherwise" ) rules11(stackMemory), f = true; if(lexems[i+1].code == keyword && lexems[i+1].id_name == "while" ) rules11(stackMemory), f = true; if(lexems[i+1].code == keyword && lexems[i+1].id_name == "od" ) rules11(stackMemory), f = true; if(lexems[i+1].code == keyword && lexems[i+1].id_name == "else" ) rules11(stackMemory), f = true; if(lexems[i+1].code == keyword && lexems[i+1].id_name == "fi" ) rules11(stackMemory), f = true; if(!f) rules12(stackMemory), f = true; if(!f) throw InvalidEnd(); break; case O: if(lexems[i].code == semicolon )rules13(stackMemory), f = true; // if(lexems[i].code == keyword && lexems[i].id_name == "case") rules13(stackMemory), f = true; // if(lexems[i].code == keyword && lexems[i].id_name == "otherwise") rules13(stackMemory), f = true; // if(lexems[i].code == keyword && lexems[i].id_name == "ni") rules13(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "set") rules14(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "do") rules15(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "for") rules27(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "if") rules30(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "cin") rules33(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "cout") rules36(stackMemory), f = true; if(lexems[i].code == lable) if(lexems[i+1].code == keyword && lexems[i+1].id_name == "$") rules39(stackMemory), f = true; else rules40(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "goto") rules41(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "fail") if(lexems[i+1].code == semicolon) rules42(stackMemory), f = true; else rules43(stackMemory), f = true; // cout<<lexems[i].id_name<<endl; if(lexems[i].code == keyword && lexems[i].id_name == "select") rules44(stackMemory), f = true; if(!f) throw InvalidOperator(); break; case W: if(lexems[i].code == semicolon) rules16(stackMemory), f = true; if(lexems[i].code == lable) rules16(stackMemory), f = true; if(lexems[i].code == keyword) { if(lexems[i].id_name == "set" || lexems[i].id_name == "do" || lexems[i].id_name == "for" ) rules16(stackMemory), f = true; if(lexems[i].id_name == "cin" || lexems[i].id_name == "cout" ) rules16(stackMemory), f = true; if(lexems[i].id_name == "while") rules17(stackMemory), f = true; if(lexems[i].code == lable)rules16(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "goto") rules16(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "fail") rules16(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "select") rules16(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "if") rules16(stackMemory), f = true; } if(!f) throw InvalidOperatorWhile(); break; case W1: if(lexems[i].code == semicolon) rules18(stackMemory), f = true; if(lexems[i].code == lable) rules18(stackMemory), f = true; if(lexems[i].code == keyword) { if(lexems[i].id_name == "set" || lexems[i].id_name == "do" || lexems[i].id_name == "for" || lexems[i].id_name == "cout" || lexems[i].id_name == "cin" ) rules18(stackMemory), f = true; if(lexems[i].id_name == "goto") rules18(stackMemory), f = true; if(lexems[i].id_name == "if") rules18(stackMemory), f = true; if(lexems[i].id_name == "fail") rules18(stackMemory), f = true; if(lexems[i].id_name == "select") rules18(stackMemory), f = true; if(lexems[i].id_name == "od") rules19(stackMemory), f = true; } if(!f) throw InvalidOperatorWhile(); break; case T: if(lexems[i].code == id || lexems[i].code == CONST || lexems[i].code == lbr || lexems[i].code == otr || lexems[i].code == lfs || lexems[i].code == rs || lexems[i].code == ls) rules20(stackMemory), f = true; if(!f) throw InvalidTest(); break; case T1: if(lexems[i].code == Equal) rules21(stackMemory), f = true; if(lexems[i].code == not_equal) rules22(stackMemory), f = true; if(lexems[i].code == more) rules23(stackMemory), f = true; if(lexems[i].code == Less) rules24(stackMemory), f = true; if(lexems[i].code == more_or_equal) rules25(stackMemory), f = true; if(lexems[i].code == less_or_equal) rules26(stackMemory), f = true; if(!f) throw InvalidRatio(); break; case F: if(lexems[i].code == keyword && lexems[i].id_name == "by") rules28(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "do") rules29(stackMemory), f = true; if(!f) throw InvalidOperatorFor(); break; case N: if(lexems[i].code == keyword && lexems[i].id_name == "else") rules31(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "fi") rules32(stackMemory), f = true; if(!f) throw InvalidOperatorIf(); break; case I: if(lexems[i].code == semicolon ) rules34(stackMemory), f = true; if(lexems[i].code == in ) rules35(stackMemory), f = true; if(!f) throw InvalidOperatorCin(); break; case U: if(lexems[i].code == semicolon ) rules37(stackMemory), f = true; if(lexems[i].code == out ) rules38(stackMemory), f = true; if(!f) throw InvalidOperatorCout(); break; case K: if(lexems[i].code == keyword && lexems[i].id_name == "case") rules45(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "otherwise") rules46(stackMemory), f = true; if(lexems[i].code == keyword && lexems[i].id_name == "ni") rules47(stackMemory), f = true; if(!f) throw InvalidOperatorSelect(); break; case E: if(lexems[i].code == id || lexems[i].code == CONST || lexems[i].code == lbr || lexems[i].code == otr || lexems[i].code == lfs || lexems[i].code == rs || lexems[i].code == ls) rules48(stackMemory), f = true; if(!f) throw InvalidExpression(); break; case A: if(lexems[i].code == id || lexems[i].code == CONST || lexems[i].code == lbr || lexems[i].code == otr || lexems[i].code == lfs || lexems[i].code == rs || lexems[i].code == ls) rules49(stackMemory), f = true; if(!f) throw InvalidExpression(); break; case B: if(lexems[i].code == id || lexems[i].code == CONST || lexems[i].code == lbr || lexems[i].code == otr || lexems[i].code == lfs || lexems[i].code == rs || lexems[i].code == ls) rules50(stackMemory), f = true; if(!f) throw InvalidExpression(); break; case D: if(lexems[i].code == id || lexems[i].code == CONST || lexems[i].code == lbr || lexems[i].code == otr || lexems[i].code == lfs || lexems[i].code == rs || lexems[i].code == ls) rules51(stackMemory), f = true; if(!f) throw InvalidExpression(); break; case H: if(lexems[i].code == id || lexems[i].code == CONST || lexems[i].code == lbr || lexems[i].code == otr || lexems[i].code == lfs || lexems[i].code == rs || lexems[i].code == ls) rules52(stackMemory), f = true; if(!f) throw InvalidExpression(); break; case J: if(lexems[i].code == id || lexems[i].code == CONST || lexems[i].code == lbr || lexems[i].code == otr || lexems[i].code == lfs ) rules55(stackMemory), f = true; if(lexems[i].code == rs) rules53(stackMemory), f = true; if(lexems[i].code == ls) rules54(stackMemory), f = true; if(!f) throw InvalidExpression(); break; case L: if(lexems[i].code == id || lexems[i].code == CONST || lexems[i].code == lbr || lexems[i].code == otr) rules57(stackMemory), f = true; if(lexems[i].code == lfs) rules56(stackMemory), f = true; if(!f) throw InvalidExpression(); break; case Z: if(lexems[i].code == id) rules59(stackMemory), f = true; if(lexems[i].code == CONST) rules60(stackMemory), f = true; if(lexems[i].code == lbr) rules61(stackMemory), f = true; if(lexems[i].code == otr) rules58(stackMemory), f = true; if(!f) throw InvalidExpression(); break; case ID: if(lexems[i].code == id) { if(lexems[i+1].code == AND) rules77(stackMemory), f = true; if(lexems[i+1].code == OR) rules78(stackMemory), f = true; if(lexems[i+1].code == Xor) rules79(stackMemory), f = true; if(lexems[i+1].code == ssh) rules80(stackMemory), f = true; if(lexems[i+1].code == sl) rules81(stackMemory), f = true; if(lexems[i+1].code == conc) rules82(stackMemory), f = true; if(lexems[i+1].code == scolar) rules83(stackMemory), f = true; if(lexems[i+1].code == sp) rules84(stackMemory), f = true; if(lexems[i+1].code == multy) rules85(stackMemory), f = true; if(lexems[i+1].code == DEV) rules86(stackMemory), f = true; if(lexems[i+1].code == MOD) rules87(stackMemory), f = true; if(lexems[i+1].code == add) rules88(stackMemory), f = true; if(lexems[i+1].code == sub) rules89(stackMemory), f = true; if(!f) rules90(stackMemory), f = true; } if(!f) throw InvalidExpression(); break; case C: if(lexems[i].code == CONST) { if(lexems[i+1].code == AND) rules92(stackMemory), f = true; if(lexems[i+1].code == OR) rules93(stackMemory), f = true; if(lexems[i+1].code == Xor) rules94(stackMemory), f = true; if(lexems[i+1].code == ssh) rules95(stackMemory), f = true; if(lexems[i+1].code == sl) rules96(stackMemory), f = true; if(lexems[i+1].code == conc) rules97(stackMemory), f = true; if(lexems[i+1].code == scolar) rules98(stackMemory), f = true; if(lexems[i+1].code == sp) rules99(stackMemory), f = true; if(lexems[i+1].code == multy) rules100(stackMemory), f = true; if(lexems[i+1].code == DEV) rules101(stackMemory), f = true; if(lexems[i+1].code == MOD) rules102(stackMemory), f = true; if(lexems[i+1].code == add) rules103(stackMemory), f = true; if(lexems[i+1].code == sub) rules104(stackMemory), f = true; if(!f) rules105(stackMemory), f = true; } if(!f) throw InvalidExpression(); break; case SH: if(lexems[i].code == rbr) { if(lexems[i+1].code == AND) rules62(stackMemory), f = true; if(lexems[i+1].code == OR) rules63(stackMemory), f = true; if(lexems[i+1].code == Xor) rules64(stackMemory), f = true; if(lexems[i+1].code == ssh) rules65(stackMemory), f = true; if(lexems[i+1].code == sl) rules66(stackMemory), f = true; if(lexems[i+1].code == conc) rules67(stackMemory), f = true; if(lexems[i+1].code == scolar) rules68(stackMemory), f = true; if(lexems[i+1].code == sp) rules69(stackMemory), f = true; if(lexems[i+1].code == multy) rules70(stackMemory), f = true; if(lexems[i+1].code == DEV) rules71(stackMemory), f = true; if(lexems[i+1].code == MOD) rules72(stackMemory), f = true; if(lexems[i+1].code == add) rules73(stackMemory), f = true; if(lexems[i+1].code == sub) rules74(stackMemory), f = true; if(!f) rules75(stackMemory), f = true; } if(!f) throw InvalidExpression(); break; case G1: if(lexems[i].code == id) { f = true; if(lexems[i+1].code == coma) rules107(stackMemory); else rules106(stackMemory); } if(!f) throw InvalidDeclaring(); break; default: cout<<"ERRRRORRRRR"<<endl; return; } } cout<<lexems[i].id_name<<""<<endl; if(lexems[i].id_name == "$" && stackMemory.empty()) cout<<"acc"<<endl; else cout<<"fail"<<endl; }