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);
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
/// 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);
}
Esempio n. 7
0
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());
}
Esempio n. 8
0
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;
}