Journal::Functor* Journal::_create(Id id) { for (FuncDecl* ptr = _FunctionList; ptr; ptr = ptr->next) if (ptr->id == id) return ptr->create(); return 0; }
Journal::Id Journal::_getFunctionId(VoidPtr ptr,VoidMethod method) { for (FuncDecl* itr = _FunctionList; itr; itr = itr->next) if (itr->match(ptr,method)) return itr->id; return 0; }
FuncDecl *DerivedConformance::declareDerivedPropertyGetter(TypeChecker &tc, Decl *parentDecl, NominalTypeDecl *typeDecl, Type propertyInterfaceType, Type propertyContextType, bool isStatic) { auto &C = tc.Context; auto parentDC = cast<DeclContext>(parentDecl); auto selfDecl = ParamDecl::createSelf(SourceLoc(), parentDC, isStatic); ParameterList *params[] = { ParameterList::createWithoutLoc(selfDecl), ParameterList::createEmpty(C) }; FuncDecl *getterDecl = FuncDecl::create(C, SourceLoc(), StaticSpellingKind::None, SourceLoc(), DeclName(), SourceLoc(), SourceLoc(), SourceLoc(), nullptr, Type(), params, TypeLoc::withoutLoc(propertyContextType), parentDC); getterDecl->setImplicit(); getterDecl->setStatic(isStatic); // Compute the type of the getter. GenericParamList *genericParams = getterDecl->getGenericParamsOfContext(); Type type = FunctionType::get(TupleType::getEmpty(C), propertyContextType); Type selfType = getterDecl->computeSelfType(); selfDecl->overwriteType(selfType); if (genericParams) type = PolymorphicFunctionType::get(selfType, type, genericParams); else type = FunctionType::get(selfType, type); getterDecl->setType(type); getterDecl->setBodyResultType(propertyContextType); // Compute the interface type of the getter. Type interfaceType = FunctionType::get(TupleType::getEmpty(C), propertyInterfaceType); Type selfInterfaceType = getterDecl->computeInterfaceSelfType(false); if (auto sig = parentDC->getGenericSignatureOfContext()) interfaceType = GenericFunctionType::get(sig, selfInterfaceType, interfaceType, FunctionType::ExtInfo()); else interfaceType = type; getterDecl->setInterfaceType(interfaceType); getterDecl->setAccessibility(typeDecl->getFormalAccess()); // If the enum was not imported, the derived conformance is either from the // enum itself or an extension, in which case we will emit the declaration // normally. if (parentDecl->hasClangNode()) tc.Context.addExternalDecl(getterDecl); return getterDecl; }
/// Derive the body for an '==' operator for an enum static void deriveBodyEquatable_enum_eq(AbstractFunctionDecl *eqDecl) { auto parentDC = eqDecl->getDeclContext(); ASTContext &C = parentDC->getASTContext(); auto args = eqDecl->getParameterLists().back(); auto aParam = args->get(0); auto bParam = args->get(1); auto boolTy = C.getBoolDecl()->getDeclaredType(); auto enumDecl = cast<EnumDecl>(aParam->getType()->getAnyNominal()); // Generate the conversion from the enums to integer indices. SmallVector<ASTNode, 6> statements; DeclRefExpr *aIndex = convertEnumToIndex(statements, parentDC, enumDecl, aParam, eqDecl, "index_a"); DeclRefExpr *bIndex = convertEnumToIndex(statements, parentDC, enumDecl, bParam, eqDecl, "index_b"); // Generate the compare of the indices. FuncDecl *cmpFunc = C.getEqualIntDecl(); assert(cmpFunc && "should have a == for int as we already checked for it"); auto fnType = cast<FunctionType>(cmpFunc->getInterfaceType() ->getCanonicalType()); Expr *cmpFuncExpr; if (cmpFunc->getDeclContext()->isTypeContext()) { auto contextTy = cmpFunc->getDeclContext()->getSelfInterfaceType(); Expr *base = TypeExpr::createImplicitHack(SourceLoc(), contextTy, C); Expr *ref = new (C) DeclRefExpr(cmpFunc, DeclNameLoc(), /*Implicit*/ true, AccessSemantics::Ordinary, fnType); fnType = cast<FunctionType>(fnType.getResult()); cmpFuncExpr = new (C) DotSyntaxCallExpr(ref, SourceLoc(), base, fnType); cmpFuncExpr->setImplicit(); } else { cmpFuncExpr = new (C) DeclRefExpr(cmpFunc, DeclNameLoc(), /*implicit*/ true, AccessSemantics::Ordinary, fnType); } auto tType = fnType.getInput(); TupleExpr *abTuple = TupleExpr::create(C, SourceLoc(), { aIndex, bIndex }, { }, { }, SourceLoc(), /*HasTrailingClosure*/ false, /*Implicit*/ true, tType); auto *cmpExpr = new (C) BinaryExpr(cmpFuncExpr, abTuple, /*implicit*/ true, boolTy); statements.push_back(new (C) ReturnStmt(SourceLoc(), cmpExpr)); BraceStmt *body = BraceStmt::create(C, SourceLoc(), statements, SourceLoc()); eqDecl->setBody(body); }
FuncDecl *DerivedConformance::declareDerivedPropertyGetter(TypeChecker &tc, Decl *parentDecl, NominalTypeDecl *typeDecl, Type propertyInterfaceType, Type propertyContextType, bool isStatic, bool isFinal) { auto &C = tc.Context; auto parentDC = cast<DeclContext>(parentDecl); auto selfDecl = ParamDecl::createSelf(SourceLoc(), parentDC, isStatic); ParameterList *params[] = { ParameterList::createWithoutLoc(selfDecl), ParameterList::createEmpty(C) }; FuncDecl *getterDecl = FuncDecl::create(C, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None, /*FuncLoc=*/SourceLoc(), DeclName(), /*NameLoc=*/SourceLoc(), /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), /*AccessorKeywordLoc=*/SourceLoc(), nullptr, params, TypeLoc::withoutLoc(propertyInterfaceType), parentDC); getterDecl->setImplicit(); getterDecl->setStatic(isStatic); // If this is supposed to be a final method, mark it as such. assert(isFinal || !parentDC->getAsClassOrClassExtensionContext()); if (isFinal && parentDC->getAsClassOrClassExtensionContext() && !getterDecl->isFinal()) getterDecl->getAttrs().add(new (C) FinalAttr(/*IsImplicit=*/true)); // Compute the interface type of the getter. Type interfaceType = FunctionType::get(TupleType::getEmpty(C), propertyInterfaceType); Type selfInterfaceType = getterDecl->computeInterfaceSelfType(); if (auto sig = parentDC->getGenericSignatureOfContext()) { getterDecl->setGenericEnvironment( parentDC->getGenericEnvironmentOfContext()); interfaceType = GenericFunctionType::get(sig, selfInterfaceType, interfaceType, FunctionType::ExtInfo()); } else interfaceType = FunctionType::get(selfInterfaceType, interfaceType); getterDecl->setInterfaceType(interfaceType); getterDecl->setAccessibility(std::max(typeDecl->getFormalAccess(), Accessibility::Internal)); // If the enum was not imported, the derived conformance is either from the // enum itself or an extension, in which case we will emit the declaration // normally. if (isa<ClangModuleUnit>(parentDC->getModuleScopeContext())) tc.Context.addExternalDecl(getterDecl); return getterDecl; }
/// Emit a collection downcast expression. /// /// \param conditional Whether to emit a conditional downcast; if /// false, this will emit a forced downcast. static RValue emitCollectionDowncastExpr(SILGenFunction &SGF, ManagedValue source, Type sourceType, SILLocation loc, Type destType, SGFContext C, bool conditional) { // Compute substitutions for the intrinsic call. auto fromCollection = cast<BoundGenericStructType>( sourceType->getCanonicalType()); auto toCollection = cast<BoundGenericStructType>( destType->getCanonicalType()); // Get the intrinsic function. auto &ctx = SGF.getASTContext(); FuncDecl *fn = nullptr; if (fromCollection->getDecl() == ctx.getArrayDecl()) { fn = conditional ? SGF.SGM.getArrayConditionalCast(loc) : SGF.SGM.getArrayForceCast(loc); } else if (fromCollection->getDecl() == ctx.getDictionaryDecl()) { fn = (conditional ? SGF.SGM.getDictionaryDownCastConditional(loc) : SGF.SGM.getDictionaryDownCast(loc)); } else if (fromCollection->getDecl() == ctx.getSetDecl()) { fn = (conditional ? SGF.SGM.getSetDownCastConditional(loc) : SGF.SGM.getSetDownCast(loc)); } else { llvm_unreachable("unsupported collection upcast kind"); } // This will have been diagnosed by the accessors above. if (!fn) return SGF.emitUndefRValue(loc, destType); auto fnGenericParams = fn->getGenericSignature()->getGenericParams(); auto fromSubsts = fromCollection->gatherAllSubstitutions( SGF.SGM.SwiftModule, nullptr); auto toSubsts = toCollection->gatherAllSubstitutions( SGF.SGM.SwiftModule, nullptr); assert(fnGenericParams.size() == fromSubsts.size() + toSubsts.size() && "wrong number of generic collection parameters"); (void) fnGenericParams; // Form type parameter substitutions. SmallVector<Substitution, 4> subs; subs.append(fromSubsts.begin(), fromSubsts.end()); subs.append(toSubsts.begin(), toSubsts.end()); return SGF.emitApplyOfLibraryIntrinsic(loc, fn, subs, {source}, C); }
void StmtEmitter::visitDeferStmt(DeferStmt *S) { // Emit the closure for the defer, along with its binding. // If the defer is at the top-level code, insert 'mark_escape_inst' // to the top-level code to check initialization of any captured globals. FuncDecl *deferDecl = S->getTempDecl(); auto declCtxKind = deferDecl->getDeclContext()->getContextKind(); auto &sgm = SGF.SGM; if (declCtxKind == DeclContextKind::TopLevelCodeDecl && sgm.TopLevelSGF && sgm.TopLevelSGF->B.hasValidInsertionPoint()) { sgm.emitMarkFunctionEscapeForTopLevelCodeGlobals( S, deferDecl->getCaptureInfo()); } SGF.visitFuncDecl(deferDecl); // Register a cleanup to invoke the closure on any exit paths. SGF.Cleanups.pushCleanup<DeferCleanup>(S->getDeferLoc(), S->getCallExpr()); }
void Hurricane::build(){ BlogProgram *blog = new BlogProgram(0, 0); root = blog; /* type City; type PrepLevel; type DamageLevel; */ { blog->add(new TypDecl(0, 0, Symbol("City"))); blog->add(new TypDecl(0, 0, Symbol("PrepLevel"))); blog->add(new TypDecl(0, 0, Symbol("DamageLevel"))); } /* distinct City A, B; distinct PrepLevel Low, High; distinct DamageLevel Severe, Mild; */ { DistinctDecl*dis; dis = new DistinctDecl(0, 0, Symbol("City")); dis->add(Symbol("A"), 1); dis->add(Symbol("B"), 1); blog->add(dis); dis = new DistinctDecl(0, 0, Symbol("PrepLevel")); dis->add(Symbol("Low"), 1); dis->add(Symbol("High"), 1); blog->add(dis); dis = new DistinctDecl(0, 0, Symbol("DamageLevel")); dis->add(Symbol("Severe"), 1); dis->add(Symbol("Mild"), 1); blog->add(dis); } /* random City First ~ UniformChoice({c for City c}); */ { SetExpr *se = new TupleSetExpr(0, 0, std::vector<Expr*>({ new FuncApp(0, 0, Symbol("c")) }), std::vector<VarDecl>({ VarDecl(0, 0, Symbol("City"), Symbol("c")) }),NULL); FuncApp *dis = new FuncApp(0, 0, Symbol("UniformChoice")); dis->add(se); FuncDecl *fd = new FuncDecl(0, 0, true, Symbol("City"), Symbol("First"), dis); blog->add(fd); } /* random PrepLevel Prep(City c) ~ if (First == c) then Categorical({High -> 0.5, Low -> 0.5}) else case Damage(First) in {Severe -> ~ Categorical({High -> 0.9, Low -> 0.1}), Mild -> ~ Categorical({High -> 0.1, Low -> 0.9})}; }; */ { Expr *cond, *thn, *els; { // Cond OpExpr *eq = new OpExpr(0, 0, AbsynConstant::EQ, new FuncApp(0, 0, Symbol("First")), new FuncApp(0, 0, Symbol("c"))); cond = eq; } { // Then Clause MapExpr *map = new MapExpr(0, 0); map->addMap(new FuncApp(0, 0, Symbol("High")), new DoubleLiteral(0, 0, 0.5)); map->addMap(new FuncApp(0, 0, Symbol("Low")), new DoubleLiteral(0, 0, 0.5)); FuncApp *cat = new FuncApp(0, 0, Symbol("Categorical")); cat->add(map); thn = cat; } { // Else Clause FuncApp *dam_f = new FuncApp(0, 0, Symbol("Damage")); dam_f->add(new FuncApp(0, 0, Symbol("First"))); MapExpr *map_s = new MapExpr(0, 0); map_s->addMap(new FuncApp(0, 0, Symbol("High")), new DoubleLiteral(0, 0, 0.9)); map_s->addMap(new FuncApp(0, 0, Symbol("Low")), new DoubleLiteral(0, 0, 0.1)); FuncApp *cat_s = new FuncApp(0, 0, Symbol("Categorical")); cat_s->add(map_s); MapExpr *map_m = new MapExpr(0, 0); map_m->addMap(new FuncApp(0, 0, Symbol("High")), new DoubleLiteral(0, 0, 0.1)); map_m->addMap(new FuncApp(0, 0, Symbol("Low")), new DoubleLiteral(0, 0, 0.9)); FuncApp *cat_m = new FuncApp(0, 0, Symbol("Categorical")); cat_m->add(map_m); MapExpr *map_t = new MapExpr(0, 0); map_t->addMap(new FuncApp(0, 0, Symbol("Severe")), cat_s); map_t->addMap(new FuncApp(0, 0, Symbol("Mild")), cat_m); CaseExpr *cas_els = new CaseExpr(0, 0, dam_f, map_t); els = cas_els; } IfExpr *ife = new IfExpr(0, 0, cond, thn, els); FuncDecl *func = new FuncDecl(0, 0, true, Symbol("PrepLevel"), Symbol("Prep"), ife); func->addArg(VarDecl(0, 0, Symbol("City"), Symbol("c"))); blog->add(func); } /* random DamageLevel Damage(City c) ~ case Prep(c) in {High -> ~ Categorical({Severe -> 0.2, Mild -> 0.8}), Low -> ~ Categorical({Severe -> 0.8, Mild -> 0.2})}; }; */ { FuncApp *cat_h = new FuncApp(0, 0, Symbol("Categorical")); MapExpr *map_h = new MapExpr(0, 0); map_h->addMap(new FuncApp(0, 0, Symbol("Severe")), new DoubleLiteral(0, 0, 0.2)); map_h->addMap(new FuncApp(0, 0, Symbol("Mild")), new DoubleLiteral(0, 0, 0.8)); cat_h->add(map_h); FuncApp *cat_l = new FuncApp(0, 0, Symbol("Categorical")); MapExpr *map_l = new MapExpr(0, 0); map_l->addMap(new FuncApp(0, 0, Symbol("Severe")), new DoubleLiteral(0, 0, 0.8)); map_l->addMap(new FuncApp(0, 0, Symbol("Mild")), new DoubleLiteral(0, 0, 0.2)); cat_l->add(map_l); FuncApp *prep = new FuncApp(0, 0, Symbol("Prep")); prep->add(new FuncApp(0, 0, Symbol("c"))); MapExpr *map_t = new MapExpr(0, 0); map_t->addMap(new FuncApp(0, 0, Symbol("High")), cat_h); map_t->addMap(new FuncApp(0, 0, Symbol("Low")), cat_l); CaseExpr *cas = new CaseExpr(0,0,prep,map_t); FuncDecl* func = new FuncDecl(0, 0, true, Symbol("DamageLevel"), Symbol("Damage"), cas); func->addArg(VarDecl(0, 0, Symbol("City"), Symbol("c"))); blog->add(func); } /* obs Damage(First) = Severe; */ { FuncApp *dam = new FuncApp(0, 0, Symbol("Damage")); dam->add(new FuncApp(0, 0, Symbol("First"))); Evidence *obs = new Evidence(0, 0, dam, new FuncApp(0, 0, Symbol("Severe"))); blog->add(obs); } /* query First; query Damage(A); query Damage(B); */ { blog->add(new Query(0, 0, new FuncApp(0, 0, Symbol("First")))); FuncApp *dam_A = new FuncApp(0, 0, Symbol("Damage")); dam_A->add(new FuncApp(0, 0, Symbol("A"))); blog->add(new Query(0, 0, dam_A)); FuncApp *dam_B = new FuncApp(0, 0, Symbol("Damage")); dam_B->add(new FuncApp(0, 0, Symbol("B"))); blog->add(new Query(0, 0, dam_B)); } }
/// Derive a 'hashValue' implementation for an enum. static ValueDecl * deriveHashable_enum_hashValue(TypeChecker &tc, Decl *parentDecl, EnumDecl *enumDecl) { // enum SomeEnum { // case A, B, C // @derived var hashValue: Int { // var index: Int // switch self { // case A: // index = 0 // case B: // index = 1 // case C: // index = 2 // } // return index.hashValue // } // } ASTContext &C = tc.Context; auto parentDC = cast<DeclContext>(parentDecl); Type intType = C.getIntDecl()->getDeclaredType(); // We can't form a Hashable conformance if Int isn't Hashable or // IntegerLiteralConvertible. if (!tc.conformsToProtocol(intType,C.getProtocol(KnownProtocolKind::Hashable), enumDecl, None)) { tc.diagnose(enumDecl->getLoc(), diag::broken_int_hashable_conformance); return nullptr; } ProtocolDecl *intLiteralProto = C.getProtocol(KnownProtocolKind::IntegerLiteralConvertible); if (!tc.conformsToProtocol(intType, intLiteralProto, enumDecl, None)) { tc.diagnose(enumDecl->getLoc(), diag::broken_int_integer_literal_convertible_conformance); return nullptr; } auto selfDecl = ParamDecl::createSelf(SourceLoc(), parentDC); ParameterList *params[] = { ParameterList::createWithoutLoc(selfDecl), ParameterList::createEmpty(C) }; FuncDecl *getterDecl = FuncDecl::create(C, SourceLoc(), StaticSpellingKind::None, SourceLoc(), Identifier(), SourceLoc(), SourceLoc(), SourceLoc(), nullptr, Type(), params, TypeLoc::withoutLoc(intType), parentDC); getterDecl->setImplicit(); getterDecl->setBodySynthesizer(deriveBodyHashable_enum_hashValue); // Compute the type of hashValue(). GenericParamList *genericParams = getterDecl->getGenericParamsOfContext(); Type methodType = FunctionType::get(TupleType::getEmpty(tc.Context), intType); Type selfType = getterDecl->computeSelfType(); selfDecl->overwriteType(selfType); Type type; if (genericParams) type = PolymorphicFunctionType::get(selfType, methodType, genericParams); else type = FunctionType::get(selfType, methodType); getterDecl->setType(type); getterDecl->setBodyResultType(intType); // Compute the interface type of hashValue(). Type interfaceType; Type selfIfaceType = getterDecl->computeInterfaceSelfType(false); if (auto sig = parentDC->getGenericSignatureOfContext()) interfaceType = GenericFunctionType::get(sig, selfIfaceType, methodType, AnyFunctionType::ExtInfo()); else interfaceType = FunctionType::get(selfType, methodType); getterDecl->setInterfaceType(interfaceType); getterDecl->setAccessibility(enumDecl->getFormalAccess()); // If the enum was not imported, the derived conformance is either from the // enum itself or an extension, in which case we will emit the declaration // normally. if (enumDecl->hasClangNode()) tc.Context.addExternalDecl(getterDecl); // Create the property. VarDecl *hashValueDecl = new (C) VarDecl(/*static*/ false, /*let*/ false, SourceLoc(), C.Id_hashValue, intType, parentDC); hashValueDecl->setImplicit(); hashValueDecl->makeComputed(SourceLoc(), getterDecl, nullptr, nullptr, SourceLoc()); hashValueDecl->setAccessibility(enumDecl->getFormalAccess()); Pattern *hashValuePat = new (C) NamedPattern(hashValueDecl, /*implicit*/true); hashValuePat->setType(intType); hashValuePat = new (C) TypedPattern(hashValuePat, TypeLoc::withoutLoc(intType), /*implicit*/ true); hashValuePat->setType(intType); auto patDecl = PatternBindingDecl::create(C, SourceLoc(), StaticSpellingKind::None, SourceLoc(), hashValuePat, nullptr, parentDC); patDecl->setImplicit(); auto dc = cast<IterableDeclContext>(parentDecl); dc->addMember(getterDecl); dc->addMember(hashValueDecl); dc->addMember(patDecl); return hashValueDecl; }