[serialization] Add support for oneofs.

Since SILGen support is so poor, the test just uses -parse.

Swift SVN r6136
This commit is contained in:
Jordan Rose
2013-07-10 23:26:00 +00:00
parent 1564fa7f10
commit ca6f08164f
5 changed files with 178 additions and 3 deletions

View File

@@ -896,6 +896,71 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
break;
}
case decls_block::ONEOF_DECL: {
IdentifierID nameID;
DeclID contextID;
bool isImplicit;
ArrayRef<uint64_t> inheritedIDs;
decls_block::OneOfLayout::readRecord(scratch, nameID, contextID,
isImplicit, inheritedIDs);
MutableArrayRef<TypeLoc> inherited;
DeclContext *DC;
{
BCOffsetRAII restoreOffset(DeclTypeCursor);
inherited = getTypes(inheritedIDs);
DC = getDeclContext(contextID);
}
auto genericParams = maybeReadGenericParams(DC);
auto oneOf = new (ctx) OneOfDecl(SourceLoc(), getIdentifier(nameID),
SourceLoc(), inherited,
genericParams, DC);
declOrOffset = oneOf;
if (isImplicit)
oneOf->setImplicit();
if (genericParams)
for (auto &genericParam : *oneOf->getGenericParams())
genericParam.getAsTypeParam()->setDeclContext(oneOf);
SmallVector<ProtocolConformance *, 16> conformanceBuf;
while (ProtocolConformance *conformance = maybeReadConformance())
conformanceBuf.push_back(conformance);
oneOf->setConformances(ctx.AllocateCopy(conformanceBuf));
auto members = readMembers();
assert(members.hasValue() && "could not read oneof members");
oneOf->setMembers(members.getValue(), SourceRange());
break;
}
case decls_block::ONEOF_ELEMENT_DECL: {
IdentifierID nameID;
DeclID contextID;
TypeID argTypeID, ctorTypeID;
bool isImplicit;
decls_block::OneOfElementLayout::readRecord(scratch, nameID, contextID,
argTypeID, ctorTypeID,
isImplicit);
auto argTy = getType(argTypeID);
auto elem = new (ctx) OneOfElementDecl(SourceLoc(), getIdentifier(nameID),
TypeLoc::withoutLoc(argTy),
getDeclContext(contextID));
declOrOffset = elem;
elem->setType(getType(ctorTypeID));
if (isImplicit)
elem->setImplicit();
break;
}
case decls_block::XREF: {
uint8_t kind;
TypeID expectedTypeID;

View File

@@ -237,6 +237,8 @@ namespace decls_block {
POSTFIX_OPERATOR_DECL,
INFIX_OPERATOR_DECL,
CLASS_DECL,
ONEOF_DECL,
ONEOF_ELEMENT_DECL,
PAREN_PATTERN = 200,
TUPLE_PATTERN,
@@ -406,6 +408,7 @@ namespace decls_block {
using StructLayout = NominalLayout<STRUCT_DECL>;
using ProtocolLayout = NominalLayout<PROTOCOL_DECL>;
using ClassLayout = NominalLayout<CLASS_DECL>;
using OneOfLayout = NominalLayout<ONEOF_DECL>;
using ConstructorLayout = BCRecordLayout<
CONSTRUCTOR_DECL,
@@ -466,6 +469,15 @@ namespace decls_block {
BCFixed<8> // precedence
>;
using OneOfElementLayout = BCRecordLayout<
ONEOF_ELEMENT_DECL,
IdentifierIDField, // name
DeclIDField, // context decl
TypeIDField, // argument type
TypeIDField, // constructor type
BCFixed<1> // implicit?
>;
using ParenPatternLayout = BCRecordLayout<
PAREN_PATTERN

View File

@@ -424,6 +424,8 @@ void Serializer::writeBlockInfoBlock() {
RECORD(decls_block, POSTFIX_OPERATOR_DECL);
RECORD(decls_block, INFIX_OPERATOR_DECL);
RECORD(decls_block, CLASS_DECL);
RECORD(decls_block, ONEOF_DECL);
RECORD(decls_block, ONEOF_ELEMENT_DECL);
RECORD(decls_block, PAREN_PATTERN);
RECORD(decls_block, TUPLE_PATTERN);
@@ -888,8 +890,31 @@ bool Serializer::writeDecl(const Decl *D) {
return true;
}
case DeclKind::OneOf:
return false;
case DeclKind::OneOf: {
auto oneOf = cast<OneOfDecl>(D);
// FIXME: Handle attributes.
if (!oneOf->getAttrs().empty())
return false;
const Decl *DC = getDeclForContext(oneOf->getDeclContext());
SmallVector<TypeID, 4> inherited;
for (auto parent : oneOf->getInherited())
inherited.push_back(addTypeRef(parent.getType()));
unsigned abbrCode = DeclTypeAbbrCodes[OneOfLayout::Code];
OneOfLayout::emitRecord(Out, ScratchRecord, abbrCode,
addIdentifierRef(oneOf->getName()),
addDeclRef(DC),
oneOf->isImplicit(),
inherited);
writeGenericParams(oneOf->getGenericParams());
writeConformances(oneOf->getConformances());
writeMembers(oneOf);
return true;
}
case DeclKind::Class: {
auto theClass = cast<ClassDecl>(D);
@@ -1006,7 +1031,25 @@ bool Serializer::writeDecl(const Decl *D) {
return true;
}
case DeclKind::OneOfElement:
case DeclKind::OneOfElement: {
auto elem = cast<OneOfElementDecl>(D);
// FIXME: Handle attributes.
if (!elem->getAttrs().empty())
return false;
const Decl *DC = getDeclForContext(elem->getDeclContext());
unsigned abbrCode = DeclTypeAbbrCodes[OneOfElementLayout::Code];
OneOfElementLayout::emitRecord(Out, ScratchRecord, abbrCode,
addIdentifierRef(elem->getName()),
addDeclRef(DC),
addTypeRef(elem->getArgumentType()),
addTypeRef(elem->getType()),
elem->isImplicit());
return true;
}
case DeclKind::Subscript:
return false;
@@ -1370,6 +1413,8 @@ void Serializer::writeAllDeclsAndTypes() {
registerDeclTypeAbbr<PostfixOperatorLayout>();
registerDeclTypeAbbr<InfixOperatorLayout>();
registerDeclTypeAbbr<ClassLayout>();
registerDeclTypeAbbr<OneOfLayout>();
registerDeclTypeAbbr<OneOfElementLayout>();
registerDeclTypeAbbr<ParenPatternLayout>();
registerDeclTypeAbbr<TuplePatternLayout>();

View File

@@ -0,0 +1,30 @@
oneof Basic {
Untyped,
HasType : Int
constructor() {
this = .Untyped
}
func doSomething() {}
}
oneof Generic<A> {
Left : A,
Right : A
}
protocol Computable {
func compute()
}
oneof Lazy<T> : Computable {
Thunk : () -> T,
Value : T
func compute() {
// if (this ~= .Thunk(var fn)) {
// this = .Value(fn())
// }
}
}

View File

@@ -0,0 +1,23 @@
// RUN: rm -rf %t
// RUN: mkdir %t
// RUN: %swift -emit-module -o %t/def_oneof.swiftmodule %S/Inputs/def_oneof.swift
// RUN: llvm-bcanalyzer %t/def_oneof.swiftmodule | FileCheck %s
// RUN: %swift -parse -I=%t %s -o /dev/null
// CHECK-NOT: FALL_BACK_TO_TRANSLATION_UNIT
import def_oneof
var a : Basic
a = .Untyped
a.doSomething()
a = .HasType(4)
a.doSomething()
var g = Generic.Left(false)
g = .Right(true)
var lazy = Lazy.Thunk({ 42 })
var comp : Computable = lazy
comp.compute()
lazy.compute()