void X86::declareMatrix(int decl_type, int type, string name, list<string> dims) { int size = 1; for(list<string>::iterator it = dims.begin(); it != dims.end(); it++) { size *= atoi((*it).c_str()); } if(decl_type == VAR_GLOBAL) { stringstream s; switch(type) { case TIPO_INTEIRO: case TIPO_REAL: case TIPO_CARACTERE: case TIPO_LOGICO: case TIPO_LITERAL: s << X86::makeID(name) << " times " << size << " dd 0"; break; default: GPTDisplay::self()->showError("Erro interno: tipo nao suportado (X86::declarePrimitive)."); exit(1); } writeDATA(s.str()); } else if(decl_type == VAR_PARAM) { _subprograms[currentScope()].declareParam(name, type, size); } else if(decl_type == VAR_LOCAL) { _subprograms[currentScope()].declareLocal(name, size); } else { GPTDisplay::self()->showError("Erro interno: X86::declareMatrix)."); exit(1); } }
void X86::declarePrimitive(int decl_type, const string& name, int type) { stringstream s; if(decl_type == VAR_GLOBAL) { //all sizes have 32 bits (double word) switch(type) { case TIPO_INTEIRO: case TIPO_REAL: case TIPO_CARACTERE: case TIPO_LITERAL: case TIPO_LOGICO: s << X86::makeID(name) << " dd 0"; writeDATA(s.str()); break; default: GPTDisplay::self()->showError("Erro interno: tipo nao suportado (X86::declarePrimitive)."); exit(1); } } else if(decl_type == VAR_PARAM) { _subprograms[currentScope()].declareParam(name, type); } else if(decl_type == VAR_LOCAL) { _subprograms[currentScope()].declareLocal(name); } else { GPTDisplay::self()->showError("Erro interno: X86::declarePrimitive)."); exit(1); } }
Node* NodeGen::uncommonBranch(PRegBList* exprStack, bool restartSend) { assert(SICDeferUncommonBranches, "shouldn't use uncommon traps"); Node* n = APPEND(new UncommonNode(exprStack, restartSend)); assert(currentScope()->isCodeScope(), "must be non-access"); ((SCodeScope*)currentScope())->addSend(exprStack); current = NULL; return n; }
void NodeGen::loadArg(fint argNo, PReg* from, bool isPrimCall) { Unused(isPrimCall); assert(currentScope()->isCodeScope(), "oops"); SCodeScope* s = (SCodeScope*)currentScope(); fint bci = s->bci(); Location l = argNo == -1 ? ReceiverReg : ArgLocation(argNo); // weird arg numbering - 0 is 1st arg, not receiver // uses aren't right yet (call should have use) -fix this loadArg(from, new ArgSAPReg(s, l, true, false, bci, bci)); }
BackendScope::~BackendScope() { assert(nextScope == nullptr); deactivate(); if (priorScope) { priorScope->activate(); currentScope().set(priorScope); assert(priorScope->nextScope == this); priorScope->nextScope = nullptr; } else { currentScope().set(nullptr); } }
BackendScope::BackendScope(RendererBackend& backend_, ScopeType scopeType_) : priorScope(currentScope().get()), nextScope(nullptr), backend(backend_), scopeType(scopeType_) { if (priorScope) { assert(priorScope->nextScope == nullptr); priorScope->nextScope = this; priorScope->deactivate(); } activate(); currentScope().set(this); }
void SymbolTreeBuilder::visit(ConditionNode& node) { node.setScope(currentScope()); if (node.hasConditionComponent()) { _curStatment = node.condition(); node.condition()->accept(*this); // check condition expression if (!_expResult.type->isPromotableToBoolean()) { throw SemanticException("Condition expression can not be promoted to boolean\n", node); } } if (node.hasOnTrueComponent()) { // begin new scope beginScope(); node.onTrue()->accept(*this); endScope(); } if (node.hasOnFalseComponent()) { // begin new scope beginScope(); node.onFalse()->accept(*this); endScope(); } }
void SymbolTreeBuilder::visit(ReturnNode& node) { if (!_curFunctionDecl) { throw SemanticException("Return statement outside function scope\n", node); } const char* function_name = _curFunctionDecl->symbolName(); const FunctionType* func_type = cast_type<FunctionType>(_curFunctionDecl->symbolType()); const Type* func_return = func_type->typeOfReturnValue(); // current return type if (!func_return->isVoidType() && !node.expression()) { std::stringstream stream; stream <<"Function '" << function_name << "' has return type '" << func_return->typeString() << "', but we are not returning any" << std::endl; throw SemanticException(stream.str(), node); } if (node.expression()) { if (func_return->isVoidType()) { std::stringstream stream; stream <<"Function '" << function_name << "' has return type '" << func_return->typeString() << "', but we are returning type '" << _expResult.type->typeString() <<"'" << std::endl; throw SemanticException(stream.str(), node); } node.expression()->accept(*this); // check if the return types match if(!_expResult.type->isPromotableTo(func_return)) { std::stringstream stream; stream <<"Function '" << function_name << "' has return type '" << func_return->typeString() << "', but we are returning type '" << _expResult.type->typeString() <<"'" << std::endl; throw SemanticException(stream.str(), node); } _expResult.symbol->markReturnValue(); } node.setScope(currentScope()); node.setNodeType(_expResult.type); }
void SymbolTreeBuilder::visit(CompareOperatorNode& node) { node.setScope(currentScope()); node.expressionLeft()->accept(*this); ExpressionResult left_type = _expResult; node.expressionRight()->accept(*this); // evaluate right type ExpressionResult right_type = _expResult; if (!right_type.type->isPromotableTo(left_type.type)) { std::stringstream stream; stream <<"Cannot convert right expression to left, expression type " << _expResult.type->typeString() <<" cannot be cast to " << left_type.type->typeString() << std::endl; throw SemanticException(stream.str(), node); } _expResult = left_type; Symbol* tmp_sym = _curScope->declareTemporarySymbol(_expResult.type); YAL_ASSERT(tmp_sym); _curStatment->addSymbolToScope(tmp_sym); _expResult = ExpressionResult(BuiltinType::GetBuiltinType(BuiltinType::kBool), tmp_sym); node.setNodeType(_expResult.type); node.setExpressionResult(_expResult); }
void SymbolTreeBuilder::visit(VariableAccessNode& node) { node.setScope(currentScope()); const char* symbol_name = node.variableName(); auto sym = _curScope->resolveSymbol(symbol_name); if (!sym) { std::stringstream stream; stream << "Symbol '" << symbol_name << "' is undefined" << std::endl; throw SemanticException(stream.str(), node); } if (!sym->isVariable()) { std::stringstream stream; stream << "Symbol '" << symbol_name << "' is not a variable" << std::endl; throw SemanticException(stream.str(), node); } _expResult = ExpressionResult(sym->symbolType(), sym); node.setNodeType(_expResult.type); node.setExpressionResult(_expResult); sym->touchRead(); }
const SymTabEntry* SymTabMgr::lookUpInScope(string name, SymTabEntry::Kind k) const { const SymTabEntry *ste = currentScope(k); if ((ste != NULL) && (ste->symTab() != NULL)) { ste = ste->symTab()->lookUp(name); return ste; } else return NULL; }
void SymbolTreeBuilder::visit(CodeBodyNode& node) { node.setScope(currentScope()); for(auto& v : node.statements) { _curStatment = v.get(); v->accept(*this); } }
void SymbolTreeBuilder::visit(StringCreateNode& node) { node.setScope(currentScope()); node.constantNode()->accept(*this); Symbol* tmp_sym = _curScope->declareTemporarySymbol(StringType::GetType(), Symbol::kFlagNewObject); _curStatment->addSymbolToScope(tmp_sym); _expResult = ExpressionResult(StringType::GetType(), tmp_sym); node.setNodeType(_expResult.type); node.setExpressionResult(_expResult); }
void QSCheckData::registerType( QSClass *t ) { Q_ASSERT( !t->asClass() ); QSClass * scope = currentScope(); // ### Uncertain as to use identifier or name here? QSMember member; Q_ASSERT( !scope->member( 0, t->identifier(), &member ) ); scope->addStaticVariableMember( t->identifier(), env()->typeClass()->createType(t), AttributeExecutable ); }
void SymbolTreeBuilder::visit(ArgumentDeclNode& node) { node.setScope(currentScope()); if (node.isCustomType()) { throw SemanticException("Custom types not yet supported!!!\n", node); } YAL_ASSERT(_curFunctionDecl); auto sym = _curScope->resolveSymbol(node.argumentName()); if (sym && sym->scope() == _curScope) { std::stringstream stream; stream <<"Variable '" << node.argumentName() << "' has already been declared as an argument" << std::endl; throw SemanticException(stream.str(), node); } Type* arg_data_type = node.argumentType(); if (node.isCustomType()) { /*sym = _curScope->resolveSymbol(node.argumentId()); if (!sym) { _formater.format("Could not find type '%s'\n", node.argumentId()); logError(node); return; } if (sym->isVariable()) { _formater.format("Symbol type '%s' cannot be a variable name\n", node.argumentId()); logError(node); return; } arg_data_type = sym->astNode()->nodeType();*/ } const Symbol* result = _curScope->declareSymbol(node.argumentName(), arg_data_type, Symbol::kFlagAssignable | Symbol::kFlagFunctionParam | Symbol::kFlagVariable); (void) result; YAL_ASSERT(result); node.setNodeType(arg_data_type); }
Node* NodeGen::restart(MergeNode* loopStart, PRegBList* exprStack, SplitSig* s) { Node* n = APPEND(new RestartNode(exprStack, s, loopStart)); // reset current so that any code generated after the restart will // be ignored in later phases since there is no path reaching it // Next line added by dmu 4/26/07 to try to fix bug: // inlined [3] loop had nsends of 0, but needed mask for call to InterruptCheck ((SCodeScope*)currentScope())->addSend(exprStack); current = new NopNode; return n; }
void NodeGen::pathAssign(PReg* rcvr, realSlotRef* path, PReg* val, bool checkStore) { COMMENT("Begin slot assignment"); int32 offset = smiOop(path->desc->data)->byte_count() - Mem_Tag; if (path->holder->is_object_or_map()) { PReg* t = new TempPReg(currentScope()); t = loadPath(path->holder, rcvr, t); APPEND(new StoreOffsetNode(val, t, offset, checkStore)); } else { fatal("don't support vframe lookups"); } }
void SymbolTreeBuilder::visit(FunctionDeclBaseNode& node) { node.setScope(currentScope()); const char* func_name = node.functionNameWithType(); auto sym = _curScope->resolveSymbol(func_name); if (sym) { std::stringstream stream; stream << "Symbol name '" << func_name << "' already delcared" << std::endl; throw SemanticException(stream.str(), node); } // check for object type if (node.isObjectFunction()) { Type* object_type = node.objectType(); if (object_type->isUndefined()) { std::stringstream stream; stream << "Function's object type '" << object_type->typeString() << "'" << "for function '" <<func_name << "' is undefined." << std::endl; throw SemanticException(stream.str(), node); } const char* builtin_function = object_type->builtinFunctionSymName(node.functionName()); if (builtin_function) { std::stringstream stream; stream << "Can not declare function '" << func_name << "'" << " for type '" <<object_type->typeString() << "' since it conflicts with a builtin function." << std::endl; throw SemanticException(stream.str(), node); } } }
void SymbolTreeBuilder::visit(PrintArgsNode& node) { node.setScope(currentScope()); for(auto& v : node.expressions) { // optimize for strings StringCreateNode* str_node = ast_cast<StringCreateNode>(v.get()); if (str_node) { v = (std::move(str_node->constantNodePtr())); v->setParentNode(&node); } v->accept(*this); } }
void SymbolTreeBuilder::visit(AssignOperatorNode& node) { node.setScope(currentScope()); node.expressionLeft()->accept(*this); ExpressionResult left_exp_result = _expResult; if (!left_exp_result.symbol || (left_exp_result.symbol && !left_exp_result.symbol->isAssignable())) { throw SemanticException("Expression is not assignable", node); } node.expressionRight()->accept(*this); // validate types if (!_expResult.type->isPromotableTo(left_exp_result.type)) { std::stringstream stream; stream <<"Cannot convert right expression to left, expression type " << _expResult.type->typeString() <<" cannot be cast to " << left_exp_result.type->typeString() << std::endl; throw SemanticException(stream.str(), node); } _expResult.symbol->markAssigned(); if (node.assignOperatorType() == kOperatorTypeCopy && !left_exp_result.type->isObjectType() && left_exp_result.symbol->isTemporary()) { _curStatment->removeSymbolFromScope(_expResult.symbol); _curScope->eraseSymbol(_expResult.symbol); node.expressionRight()->setExpressionResult(ExpressionResult(_expResult.type, left_exp_result.symbol)); } node.setNodeType(left_exp_result.type); node.setExpressionResult(left_exp_result); left_exp_result.symbol->touchWrite(); }
void SymbolTreeBuilder::visit(WhileLoopNode& node) { node.setScope(currentScope()); _curStatment = &node; node.condition()->accept(*this); // check condition expression if (!_expResult.type->isPromotableToBoolean()) { throw SemanticException("Condition expression can not be promoted to boolean\n", node); } // begin new scope beginScope(); node.code()->accept(*this); endScope(); }
void X86::writeAttribution(int e1, int e2, pair<pair<int, bool>, string>& lv) { writeTEXT("pop eax"); writeTEXT("pop ecx"); writeCast(e1, e2); stringstream s; Symbol symb = _stable.getSymbol(currentScope(), lv.second, true); s << "lea edx, [" << X86::makeID(lv.second) << "]"; writeTEXT(s.str()); s.str(""); s << "lea edx, [edx + ecx * SIZEOF_DWORD]"; writeTEXT(s.str()); s.str(""); s << "mov [edx], eax"; writeTEXT(s.str()); }
void SymbolTreeBuilder::visit(ArgumentDeclsNode& node) { if (node.arguments().size() > kMaxFunctionArgs) { std::stringstream stream; stream <<"Function '" <<_curFunctionCall->symbolName() << "' exceeds maximum arg count (" << kMaxFunctionArgs << ")" << std::endl; throw SemanticException(stream.str(), node); } node.setScope(currentScope()); for(auto& v : node.arguments()) { v->accept(*this); } }
void SymbolTreeBuilder::visit(ConstantNode& node) { node.setScope(currentScope()); // check module if a constant that matches this value is available if (!node.constantValue().valueFitsInByteCode()) { ModuleConstant* mod_constant = _parserState->module.constant(node.constantValue()); if (!mod_constant) { _parserState->module.addConstant(new ModuleConstant(node.constantValue())); } } Symbol* tmp_sym = _curScope->declareTemporarySymbol(node.constantType()); YAL_ASSERT(tmp_sym); _curStatment->addSymbolToScope(tmp_sym); _expResult = ExpressionResult(node.constantType(), tmp_sym); node.setNodeType(_expResult.type); node.setExpressionResult(_expResult); }
void SymbolTreeBuilder::visit(FunctionCallArgsNode& node) { YAL_ASSERT(_curFunctionCall); node.setScope(currentScope()); FunctionType* func_type = cast_type<FunctionType>(_curFunctionCall->symbolType()); YAL_ASSERT(func_type); const yal_u32 nargs = func_type->argumentCount(); if (nargs != node.expressions.size()) { std::stringstream stream; stream <<"Function '" <<_curFunctionCall->symbolName() << "' expects"<< nargs << "arguments, you have provided " << node.expressions.size() << std::endl; throw SemanticException(stream.str(), node); } yal_u32 idx = 0; for(auto& v : node.expressions) { v->accept(*this); const Type* arg_type = func_type->typeOfArgument(idx); if (!_expResult.type->isPromotableTo(arg_type)) { std::stringstream stream; stream <<"Function '" <<_curFunctionCall->symbolName() << "' argument "<< idx << "expects type '" << arg_type->typeString() << "', but you have provided type '" << _expResult.type->typeString() << "'" << std::endl; throw SemanticException(stream.str(), node); } ++idx; } }
void SymbolTreeBuilder::visit(SingleOperatorNode& node) { node.setScope(currentScope()); node.expression()->accept(*this); const OperatorType op_type = node.singleOperatorType(); const bool requires_signed_int = OperatorRequiresSignedType(op_type); const bool requires_integer = OperatorRequiresInteger(op_type); if (requires_signed_int && !_expResult.type->isSignedType()) { std::stringstream stream; stream << "Operator '" << OperatorTypeToStr(node.singleOperatorType()) << "' requires that right expression has a signed type" << std::endl; throw SemanticException(stream.str(), node); } if (requires_integer && !_expResult.type->isInteger()) { std::stringstream stream; stream << "Operator '" << OperatorTypeToStr(node.singleOperatorType()) << "' requires that right expression has an integer result" << std::endl; throw SemanticException(stream.str(), node); } Symbol* tmp_sym = _curScope->declareTemporarySymbol(_expResult.type, _expResult.type->isObjectType() ? Symbol::kFlagNewObject : 0); _curStatment->addSymbolToScope(tmp_sym); _expResult = ExpressionResult(_expResult.type, tmp_sym); node.setNodeType(_expResult.type); node.setExpressionResult(_expResult); }
/** * Implement abstract operation from NativeImportBase. */ bool AdaImport::parseStmt() { const int srcLength = m_source.count(); QString keyword = m_source[m_srcIndex]; UMLDoc *umldoc = UMLApp::app()->document(); //uDebug() << '"' << keyword << '"'; if (keyword == QLatin1String("with")) { if (m_inGenericFormalPart) { // mapping of generic formal subprograms or packages is not yet implemented return false; } while (++m_srcIndex < srcLength && m_source[m_srcIndex] != QLatin1String(";")) { QStringList components = m_source[m_srcIndex].toLower().split(QLatin1Char('.')); const QString& prefix = components.first(); if (prefix == QLatin1String("system") || prefix == QLatin1String("ada") || prefix == QLatin1String("gnat") || prefix == QLatin1String("interfaces") || prefix == QLatin1String("text_io") || prefix == QLatin1String("unchecked_conversion") || prefix == QLatin1String("unchecked_deallocation")) { if (advance() != QLatin1String(",")) break; continue; } parseStems(components); if (advance() != QLatin1String(",")) break; } return true; } if (keyword == QLatin1String("generic")) { m_inGenericFormalPart = true; return true; } if (keyword == QLatin1String("package")) { const QString& name = advance(); QStringList parentPkgs = name.toLower().split(QLatin1Char('.')); parentPkgs.pop_back(); // exclude the current package parseStems(parentPkgs); UMLObject *ns = NULL; if (advance() == QLatin1String("is")) { ns = Import_Utils::createUMLObject(UMLObject::ot_Package, name, currentScope(), m_comment); if (m_source[m_srcIndex + 1] == QLatin1String("new")) { m_srcIndex++; QString pkgName = advance(); UMLObject *gp = Import_Utils::createUMLObject(UMLObject::ot_Package, pkgName, currentScope()); gp->setStereotype(QLatin1String("generic")); // Add binding from instantiator to instantiatee UMLAssociation *assoc = new UMLAssociation(Uml::AssociationType::Dependency, ns, gp); assoc->setUMLPackage(umldoc->rootFolder(Uml::ModelType::Logical)); assoc->setStereotype(QLatin1String("bind")); // Work around missing display of stereotype in AssociationWidget: assoc->setName(assoc->stereotype(true)); umldoc->addAssociation(assoc); skipStmt(); } else { pushScope(static_cast<UMLPackage*>(ns)); } } else if (m_source[m_srcIndex] == QLatin1String("renames")) { m_renaming[name] = advance(); } else { uError() << "unexpected: " << m_source[m_srcIndex]; skipStmt(QLatin1String("is")); } if (m_inGenericFormalPart) { if (ns) ns->setStereotype(QLatin1String("generic")); m_inGenericFormalPart = false; } return true; } if (m_inGenericFormalPart) return false; // skip generic formal parameter (not yet implemented) if (keyword == QLatin1String("subtype")) { QString name = advance(); advance(); // "is" QString base = expand(advance()); base.remove(QLatin1String("Standard."), Qt::CaseInsensitive); UMLObject *type = umldoc->findUMLObject(base, UMLObject::ot_UMLObject, currentScope()); if (type == NULL) { type = Import_Utils::createUMLObject(UMLObject::ot_Datatype, base, currentScope()); } UMLObject *subtype = Import_Utils::createUMLObject(type->baseType(), name, currentScope(), m_comment); UMLAssociation *assoc = new UMLAssociation(Uml::AssociationType::Dependency, subtype, type); assoc->setUMLPackage(umldoc->rootFolder(Uml::ModelType::Logical)); assoc->setStereotype(QLatin1String("subtype")); // Work around missing display of stereotype in AssociationWidget: assoc->setName(assoc->stereotype(true)); umldoc->addAssociation(assoc); skipStmt(); return true; } if (keyword == QLatin1String("type")) { QString name = advance(); QString next = advance(); if (next == QLatin1String("(")) { uDebug() << name << ": discriminant handling is not yet implemented"; // @todo Find out how to map discriminated record to UML. // For now, we just create a pro forma empty record. Import_Utils::createUMLObject(UMLObject::ot_Class, name, currentScope(), m_comment, QLatin1String("record")); skipStmt(QLatin1String("end")); if ((next = advance()) == QLatin1String("case")) m_srcIndex += 2; // skip "case" ";" skipStmt(); return true; } if (next == QLatin1String(";")) { // forward declaration Import_Utils::createUMLObject(UMLObject::ot_Class, name, currentScope(), m_comment); return true; } if (next != QLatin1String("is")) { uError() << "expecting \"is\""; return false; } next = advance(); if (next == QLatin1String("(")) { // enum type UMLObject *ns = Import_Utils::createUMLObject(UMLObject::ot_Enum, name, currentScope(), m_comment); UMLEnum *enumType = static_cast<UMLEnum*>(ns); while ((next = advance()) != QLatin1String(")")) { Import_Utils::addEnumLiteral(enumType, next, m_comment); m_comment.clear(); if (advance() != QLatin1String(",")) break; } skipStmt(); return true; } bool isTaggedType = false; if (next == QLatin1String("abstract")) { m_isAbstract = true; next = advance(); } if (next == QLatin1String("tagged")) { isTaggedType = true; next = advance(); } if (next == QLatin1String("limited") || next == QLatin1String("task") || next == QLatin1String("protected") || next == QLatin1String("synchronized")) { next = advance(); // we can't (yet?) represent that } if (next == QLatin1String("private") || next == QLatin1String("interface") || next == QLatin1String("record") || (next == QLatin1String("null") && m_source[m_srcIndex+1] == QLatin1String("record"))) { UMLObject::ObjectType t = (next == QLatin1String("interface") ? UMLObject::ot_Interface : UMLObject::ot_Class); UMLObject *ns = Import_Utils::createUMLObject(t, name, currentScope(), m_comment); if (t == UMLObject::ot_Interface) { while ((next = advance()) == QLatin1String("and")) { UMLClassifier *klass = static_cast<UMLClassifier*>(ns); QString base = expand(advance()); UMLObject *p = Import_Utils::createUMLObject(UMLObject::ot_Interface, base, currentScope()); UMLClassifier *parent = static_cast<UMLClassifier*>(p); Import_Utils::createGeneralization(klass, parent); } } else { ns->setAbstract(m_isAbstract); } m_isAbstract = false; if (isTaggedType) { if (! m_classesDefinedInThisScope.contains(ns)) m_classesDefinedInThisScope.append(ns); } else { ns->setStereotype(QLatin1String("record")); } if (next == QLatin1String("record")) m_klass = static_cast<UMLClassifier*>(ns); else skipStmt(); return true; } if (next == QLatin1String("new")) { QString base = expand(advance()); QStringList baseInterfaces; while ((next = advance()) == QLatin1String("and")) { baseInterfaces.append(expand(advance())); } const bool isExtension = (next == QLatin1String("with")); UMLObject::ObjectType t; if (isExtension || m_isAbstract) { t = UMLObject::ot_Class; } else { base.remove(QLatin1String("Standard."), Qt::CaseInsensitive); UMLObject *known = umldoc->findUMLObject(base, UMLObject::ot_UMLObject, currentScope()); t = (known ? known->baseType() : UMLObject::ot_Datatype); } UMLObject *ns = Import_Utils::createUMLObject(t, base, NULL); UMLClassifier *parent = static_cast<UMLClassifier*>(ns); ns = Import_Utils::createUMLObject(t, name, currentScope(), m_comment); if (isExtension) { next = advance(); if (next == QLatin1String("null") || next == QLatin1String("record")) { UMLClassifier *klass = static_cast<UMLClassifier*>(ns); Import_Utils::createGeneralization(klass, parent); if (next == QLatin1String("record")) { // Set the m_klass for attributes. m_klass = klass; } if (baseInterfaces.count()) { t = UMLObject::ot_Interface; QStringList::Iterator end(baseInterfaces.end()); for (QStringList::Iterator bi(baseInterfaces.begin()); bi != end; ++bi) { ns = Import_Utils::createUMLObject(t, *bi, currentScope()); parent = static_cast<UMLClassifier*>(ns); Import_Utils::createGeneralization(klass, parent); } } } } skipStmt(); return true; } // Datatypes: TO BE DONE return false; } if (keyword == QLatin1String("private")) { m_currentAccess = Uml::Visibility::Private; return true; } if (keyword == QLatin1String("end")) { if (m_klass) { if (advance() != QLatin1String("record")) { uError() << "end: expecting \"record\" at " << m_source[m_srcIndex]; } m_klass = NULL; } else if (scopeIndex()) { if (advance() != QLatin1String(";")) { QString scopeName = currentScope()->fullyQualifiedName(); if (scopeName.toLower() != m_source[m_srcIndex].toLower()) uError() << "end: expecting " << scopeName << ", found " << m_source[m_srcIndex]; } popScope(); m_currentAccess = Uml::Visibility::Public; // @todo make a stack for this } else { uError() << "importAda: too many \"end\""; } skipStmt(); return true; } // subprogram if (keyword == QLatin1String("not")) keyword = advance(); if (keyword == QLatin1String("overriding")) keyword = advance(); if (keyword == QLatin1String("function") || keyword == QLatin1String("procedure")) { const QString& name = advance(); QString returnType; if (advance() != QLatin1String("(")) { // Unlike an Ada package, a UML package does not support // subprograms. // In order to map those, we would need to create a UML // class with stereotype <<utility>> for the Ada package. uDebug() << "ignoring parameterless " << keyword << " " << name; skipStmt(); return true; } UMLClassifier *klass = NULL; UMLOperation *op = NULL; const uint MAX_PARNAMES = 16; while (m_srcIndex < srcLength && m_source[m_srcIndex] != QLatin1String(")")) { QString parName[MAX_PARNAMES]; uint parNameCount = 0; do { if (parNameCount >= MAX_PARNAMES) { uError() << "MAX_PARNAMES is exceeded at " << name; break; } parName[parNameCount++] = advance(); } while (advance() == QLatin1String(",")); if (m_source[m_srcIndex] != QLatin1String(":")) { uError() << "importAda: expecting ':'"; skipStmt(); break; } const QString &direction = advance(); QString typeName; Uml::ParameterDirection::Enum dir = Uml::ParameterDirection::In; if (direction == QLatin1String("access")) { // Oops, we have to improvise here because there // is no such thing as "access" in UML. // So we use the next best thing, "inout". // Better ideas, anyone? dir = Uml::ParameterDirection::InOut; typeName = advance(); } else if (direction == QLatin1String("in")) { if (m_source[m_srcIndex + 1] == QLatin1String("out")) { dir = Uml::ParameterDirection::InOut; m_srcIndex++; } typeName = advance(); } else if (direction == QLatin1String("out")) { dir = Uml::ParameterDirection::Out; typeName = advance(); } else { typeName = direction; // In Ada, the default direction is "in" } typeName.remove(QLatin1String("Standard."), Qt::CaseInsensitive); typeName = expand(typeName); if (op == NULL) { // In Ada, the first parameter indicates the class. UMLObject *type = Import_Utils::createUMLObject(UMLObject::ot_Class, typeName, currentScope()); UMLObject::ObjectType t = type->baseType(); if ((t != UMLObject::ot_Interface && (t != UMLObject::ot_Class || type->stereotype() == QLatin1String("record"))) || !m_classesDefinedInThisScope.contains(type)) { // Not an instance bound method - we cannot represent it. skipStmt(QLatin1String(")")); break; } klass = static_cast<UMLClassifier*>(type); op = Import_Utils::makeOperation(klass, name); // The controlling parameter is suppressed. parNameCount--; if (parNameCount) { for (uint i = 0; i < parNameCount; ++i) { parName[i] = parName[i + 1]; } } } for (uint i = 0; i < parNameCount; ++i) { UMLAttribute *att = Import_Utils::addMethodParameter(op, typeName, parName[i]); att->setParmKind(dir); } if (advance() != QLatin1String(";")) break; } if (keyword == QLatin1String("function")) { if (advance() != QLatin1String("return")) { if (klass) uError() << "importAda: expecting \"return\" at function " << name; return false; } returnType = expand(advance()); returnType.remove(QLatin1String("Standard."), Qt::CaseInsensitive); } bool isAbstract = false; if (advance() == QLatin1String("is") && advance() == QLatin1String("abstract")) isAbstract = true; if (klass != NULL && op != NULL) Import_Utils::insertMethod(klass, op, m_currentAccess, returnType, false, isAbstract, false, false, m_comment); skipStmt(); return true; } if (keyword == QLatin1String("task") || keyword == QLatin1String("protected")) { // Can task and protected objects/types be mapped to UML? QString name = advance(); if (name == QLatin1String("type")) { name = advance(); } QString next = advance(); if (next == QLatin1String("(")) { skipStmt(QLatin1String(")")); // skip discriminant next = advance(); } if (next == QLatin1String("is")) skipStmt(QLatin1String("end")); skipStmt(); return true; } if (keyword == QLatin1String("for")) { // rep spec QString typeName = advance(); QString next = advance(); if (next == QLatin1String("'")) { advance(); // skip qualifier next = advance(); } if (next == QLatin1String("use")) { if (advance() == QLatin1String("record")) skipStmt(QLatin1String("end")); } else { uError() << "importAda: expecting \"use\" at rep spec of " << typeName; } skipStmt(); return true; } // At this point we're only interested in attribute declarations. if (m_klass == NULL || keyword == QLatin1String("null")) { skipStmt(); return true; } const QString& name = keyword; if (advance() != QLatin1String(":")) { uError() << "adaImport: expecting \":\" at " << name << " " << m_source[m_srcIndex]; skipStmt(); return true; } QString nextToken = advance(); if (nextToken == QLatin1String("aliased")) nextToken = advance(); QString typeName = expand(nextToken); QString initialValue; if (advance() == QLatin1String(":=")) { initialValue = advance(); QString token; while ((token = advance()) != QLatin1String(";")) { initialValue.append(QLatin1Char(' ') + token); } } UMLObject *o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name, typeName, m_comment); if (o) { UMLAttribute *attr = static_cast<UMLAttribute*>(o); attr->setInitialValue(initialValue); } skipStmt(); return true; }
void NodeGen::testStackOverflow(PRegBList* exprStack, SplitSig* sig) { APPEND(new InterruptCheckNode(exprStack, sig)); ((SCodeScope*)currentScope())->addSend(exprStack); }
void NodeGen::exitScope (SSelfScope* s) { assert(currentScope() == s, "exiting wrong scope"); scopeStack->pop(); }
const char* NodeGen::splitCondBranch( MergeNode* targetNode, bool isBackwards, PReg* targetPR, SExpr* testExpr, BranchBCTargetStack* targetStack, SExprStack* exprStack, PRegBList* exprStackPRs, SplitSig* s ) { // try to split a conditional branch bc to avoid materializing // the boolean // local splitting only for now assert(targetPR->isConstPReg(), "cond branch must be testing for constant"); oop targetOop = ((ConstPReg*)targetPR)->constant; if (!testExpr->isMergeSExpr()) return "testExpr not MergeSExpr"; if (!((MergeSExpr*)testExpr)->isSplittable()) return "textExpr not splittable"; SExprBList* exprs = ((MergeSExpr*)testExpr)->exprs; assert(testExpr->node(), "splittable implies node()"); Node* preceedingMerge = testExpr->node(); if (current != preceedingMerge) return "not local"; // local only for now if ( preceedingMerge->nPredecessors() != exprs->length() ) return "would have to iterate over predecessors"; fint i; for ( i = 0; i < exprs->length(); ++i) { SExpr* e = exprs->nth(i); Node* n = e->node(); if ( !preceedingMerge->isPredecessor(n) ) return "merge not immediately after expr node"; if ( !e->isConstantSExpr() ) return "merge contains non-constant expression"; } MergeNode* mergeForBranching = new MergeNode("for branching"); MergeNode* mergeForFallingThrough = new MergeNode("for falling through"); mergeForBranching ->setScope(currentScope()); mergeForFallingThrough->setScope(currentScope()); for ( i = 0; i < exprs->length(); ++i) { SExpr* e = exprs->nth(i); Node* n = e->node(); MergeNode* mn = e->constant() == targetOop ? mergeForBranching : mergeForFallingThrough; mn->setPrev(n); n->moveNext(preceedingMerge, mn); } while (preceedingMerge->nPredecessors()) preceedingMerge->removePrev(preceedingMerge->prev(0)); current = mergeForBranching; branchCode( targetNode, isBackwards, NULL, NULL, targetStack, exprStack, exprStackPRs, s); append(mergeForFallingThrough); return NULL; }