void CreateEnumConstructorMethod(Context& context, const AST::Node<AST::TypeInstance>& typeInstanceNode, AST::Function& function, const size_t value) { assert(typeInstanceNode->isEnum()); if (function.hasScope()) { // Function already has a scope; this can happen when // the user has given duplicate enum constructors, in // which case we will have issued an error but continued // onwards to find more errors. return; } auto functionScope = AST::Scope::Create(typeInstanceNode.location()); HeapArray<AST::Value> constructValues; const auto intConstant = Constant::Integer(APInt(value)); const auto intType = getBuiltInType(context, context.getCString("int_t"), {}); constructValues.push_back(AST::Value::Constant(intConstant, intType)); auto internalConstructedValue = AST::Value::InternalConstruct(typeInstanceNode->selfType(), std::move(constructValues)); functionScope->statements().push_back(AST::Statement::Return(std::move(internalConstructedValue))); function.setScope(std::move(functionScope)); }
/** * Função que quebra as sequencias de variaveis e expressões * criando assigns separados. * * @param varlist Lista de variaveis * @param exprlist Lista de expressões */ AST::Node* SymbolTable::assignVar(AST::Node *varlist, AST::Node *exprlist){ AST::Node *retlist = nullptr; AST::Node *rettmp = nullptr; AST::Node *tmp = nullptr; auto var = AST::Variable::cast(varlist); auto expr = exprlist; // Esta parte vai quebrar as sequencias da atribuição (a,b=1,2;) // em assigns separados (a=1; b=2;) // As variaveis rettmp e tmp são usadas para ajudar na quebra das sequencias... // [a,b ==> b é next de a; logo, tenho que fazer 'a' não ter nenhum next] while(var != nullptr){ tmp = var; if(expr != nullptr){ tmp = new AST::BinOp(var,Ops::assign,expr); // Quebra a sequencia de next da expressão expr = expr->getNext(); exprlist->setNext(nullptr); exprlist = expr; } // Quebra a sequencia de next das variaveis var = AST::Variable::cast(var->getNext()); varlist->setNext(nullptr); varlist = var; // Vai sequenciando os assigns criados if(retlist==nullptr){ retlist = rettmp = tmp; }else{ rettmp->setNext(tmp); rettmp = tmp; } } // Retorna a sequencia de assigns return retlist; }
void DeclaratorAST::addPtrOp( AST::Node& ptrOp ) { if( !ptrOp.get() ) return; ptrOp->setParent( this ); m_ptrOpList.append( ptrOp.release() ); }
void DeclaratorAST::addArrayDimension( AST::Node& arrayDimension ) { if( !arrayDimension.get() ) return; arrayDimension->setParent( this ); m_arrayDimensionList.append( arrayDimension.release() ); }
void TemplateArgumentListAST::addArgument( AST::Node& arg ) { if( !arg.get() ) return; arg->setParent( this ); m_argumentList.append( arg.release() ); }
void AccessDeclarationAST::addAccess( AST::Node& access ) { if( !access.get() ) return; access->setParent( this ); m_accessList.append( access.release() ); }
void GroupAST::addNode( AST::Node& node ) { if( !node.get() ) return; node->setParent( this ); m_nodeList.append( node.release() ); }
Debug::VarInfo makeVarInfo(const Debug::VarInfo::Kind kind, const AST::Node<AST::TypeVar>& astTypeVarNode) { assert(astTypeVarNode->isNamed()); Debug::VarInfo varInfo; varInfo.kind = kind; varInfo.name = astTypeVarNode->name(); varInfo.declLocation = astTypeVarNode.location(); // TODO varInfo.scopeLocation = Debug::SourceLocation::Null(); return varInfo; }
Debug::TemplateVarInfo makeTemplateVarInfo(const AST::Node<AST::TemplateTypeVar>& astTemplateVarNode) { Debug::TemplateVarInfo templateVarInfo; templateVarInfo.declLocation = astTemplateVarNode.location(); // TODO templateVarInfo.scopeLocation = Debug::SourceLocation::Null(); return templateVarInfo; }
void FlatZincSpace::setOutput() { if (output == NULL) return; for (unsigned int i=0; i< output->a.size(); i++) { AST::Node* ai = output->a[i]; if (ai->isArray()) { AST::Array* aia = ai->getArray(); int size = aia->a.size(); for (int j=0; j<size; j++) { setOutputElem(aia->a[j]); } } else if (ai->isCall("ifthenelse")) { AST::Array* aia = ai->getCall("ifthenelse")->getArgs(3); setOutputElem(aia->a[1]); setOutputElem(aia->a[2]); } else { setOutputElem(ai); } } }
// Attach the variable to the SemanticAnalysis node tree. void attachVar(Context& context, const String& name, const AST::Node<AST::TypeVar>& astTypeVarNode, SEM::Var* const var, const Debug::VarInfo::Kind varKind) { assert(var->isBasic()); const auto insertResult = insertVar(context.scopeStack().back(), name, var); if (!insertResult.second) { const auto existingVar = insertResult.first->second; throw ErrorException(makeString("Variable name '%s' at position %s duplicates existing variable of the same name at position %s.", name.c_str(), astTypeVarNode.location().toString().c_str(), existingVar->debugInfo()->declLocation.toString().c_str())); } var->setDebugInfo(makeVarInfo(varKind, astTypeVarNode)); }
void FlatZincSpace::print() { firstStageSolutions.growTo(scenario->getVal()); vec<int>& x = firstStageSolutions[scenario->getVal()-1]; x.growTo(firstStageVars.size()); for (int i=0; i<firstStageVars.size(); i++) { x[i] = firstStageVars[i]->getVal(); } if (output == NULL) return; for (unsigned int i=0; i< output->a.size(); i++) { AST::Node* ai = output->a[i]; if (ai->isArray()) { AST::Array* aia = ai->getArray(); int size = aia->a.size(); std::cout << "["; for (int j=0; j<size; j++) { printElem(aia->a[j]); if (j<size-1) cout << ", "; } std::cout << "]"; } else if (ai->isCall("ifthenelse")) { AST::Array* aia = ai->getCall("ifthenelse")->getArgs(3); if (aia->a[0]->isBool()) { if (aia->a[0]->getBool()) printElem(aia->a[1]); else printElem(aia->a[2]); } else if (aia->a[0]->isBoolVar()) { BoolView b = bv[aia->a[0]->getBoolVar()]; if (b.isTrue()) printElem(aia->a[1]); else if (b.isFalse()) printElem(aia->a[2]); else std::cerr << "% Error: Condition not fixed." << std::endl; } else { std::cerr << "% Error: Condition not Boolean." << std::endl; } } else { printElem(ai); } } }
boost::optional<LevelSpecifier> LevelSpecifier::fromNode(const ast::Node& node) { { boost::optional<Depth> optionalLevel = nodeToSensibleLevelSpec(node); if ( optionalLevel ) { return LevelSpecifier(1, *optionalLevel); } } if ( node.isFunctionCall(ids::List) ) { const ast::Operands& operands = node.get<ast::FunctionCall>().getOperands(); switch ( operands.size() ) { default: return boost::none_t(); case 0: //Not documented, but valid return LevelSpecifier( 0, 0 ); case 1: { boost::optional<Depth> optionalLevel = nodeToSensibleLevelSpec(operands[0]); if ( !optionalLevel ) { return boost::none_t(); } return LevelSpecifier( *optionalLevel, *optionalLevel ); } case 2: { boost::optional<Depth> optionalLevelMin = nodeToSensibleLevelSpec(operands[0]); boost::optional<Depth> optionalLevelMax = nodeToSensibleLevelSpec(operands[1]); if ( !optionalLevelMin || !optionalLevelMax ) { return boost::none_t(); } return LevelSpecifier( *optionalLevelMin, *optionalLevelMax ); } } } return boost::none_t(); }
void ConvertTypeInstance(Context& context, AST::Node<AST::TypeInstance>& typeInstanceNode) { for (const auto& function: *(typeInstanceNode->functionDecls)) { PushScopeElement pushScopeElement(context.scopeStack(), ScopeElement::Function(*function)); ConvertFunctionDef(context, function); } if (typeInstanceNode->isEnum()) { size_t enumValue = 0; // Generate enum constructors. for (const auto& constructorName: *(typeInstanceNode->constructors)) { const auto canonicalMethodName = CanonicalizeMethodName(constructorName); CreateEnumConstructorMethod(context, typeInstanceNode, typeInstanceNode->getFunction(canonicalMethodName), enumValue++); } } // Generate default constructor for applicable types. if (typeInstanceNode->isException()) { CreateExceptionConstructor(context, typeInstanceNode, typeInstanceNode->getFunction(context.getCString("create"))); } else if (typeInstanceNode->isDatatype() || typeInstanceNode->isStruct() || typeInstanceNode->isUnion()) { (void) DefaultMethods(context).createDefaultMethod(typeInstanceNode.get(), typeInstanceNode->getFunction(context.getCString("create")), typeInstanceNode.location()); } // Generate default implicitCopy if relevant. if (typeInstanceNode->isEnum() || typeInstanceNode->isStruct() || typeInstanceNode->isDatatype() || typeInstanceNode->isVariant() || typeInstanceNode->isUnion()) { const auto existingFunction = typeInstanceNode->findFunction(context.getCString("implicitcopy")); if (existingFunction != nullptr) { CreateDefaultMethodOrRemove(context, *typeInstanceNode, *existingFunction, typeInstanceNode.location()); } } // Generate default compare if relevant. if (typeInstanceNode->isEnum() || typeInstanceNode->isStruct() || typeInstanceNode->isDatatype() || typeInstanceNode->isVariant()) { const auto existingFunction = typeInstanceNode->findFunction(context.getCString("compare")); if (existingFunction != nullptr) { CreateDefaultMethodOrRemove(context, *typeInstanceNode, *existingFunction, typeInstanceNode.location()); } } // Simplify all predicates to avoid confusing CodeGen. for (auto& function: typeInstanceNode->functions()) { PushScopeElement pushFunction(context.scopeStack(), ScopeElement::Function(*function)); function->setConstPredicate(reducePredicate(context, function->constPredicate().copy())); function->setRequiresPredicate(reducePredicate(context, function->requiresPredicate().copy())); // Simplify function type noexcept predicate. const auto oldFunctionType = function->type(); const bool isVarArg = oldFunctionType.attributes().isVarArg(); const bool isMethod = oldFunctionType.attributes().isMethod(); const bool isTemplated = oldFunctionType.attributes().isTemplated(); auto noExceptPredicate = reducePredicate(context, oldFunctionType.attributes().noExceptPredicate().copy()); const auto returnType = oldFunctionType.returnType(); const auto& argTypes = oldFunctionType.parameterTypes(); AST::FunctionAttributes attributes(isVarArg, isMethod, isTemplated, std::move(noExceptPredicate)); function->setType(AST::FunctionType(std::move(attributes), returnType, argTypes.copy())); } }