mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 08:11:04 +01:00
Canonicalize struct types. (#2855)
This adds canonicalization of struct types based on their type fields. It obsoletes the current CanImplicitAsStruct because the type ids should now be identical when they're structurally identical; there's only a reason to implicit CanImplicitAsStruct to detect _compatible_ conversions.
The type fields themselves aren't canonicalized because it would need to be done during the first parse, and could yield name conflicts being associated with the wrong location. i.e.:
```
var x: {a: i32, a: i32};
var y: {a: i32, b: i32, a: i32};
```
This should yield two separate name conflict diagnostics pointing at the type fields for each respective line, but if struct type fields were canonicalized then both would point at the first `a: i32` field definition. This isn't expected to be an issue for types because I'm trying to print those, but we may also end up with a "first defined at" situation in some cases (still, less confusing because the type should match). Regardless, I think individual fields gets much more awkward.
This commit is contained in:
+3
-5
@@ -7,17 +7,15 @@
|
||||
// CHECK:STDOUT: source_filename = "empty.carbon"
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: %StructLiteralType = type {}
|
||||
// CHECK:STDOUT: %StructLiteralType.0 = type {}
|
||||
// CHECK:STDOUT: %StructLiteralType.1 = type {}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: define i32 @Run() {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %StructLiteralValue = alloca %StructLiteralType, align 8
|
||||
// CHECK:STDOUT: %var = alloca %StructLiteralType, align 8
|
||||
// CHECK:STDOUT: %StructLiteralValue1 = alloca %StructLiteralType.0, align 8
|
||||
// CHECK:STDOUT: %StructLiteralValue1 = alloca %StructLiteralType, align 8
|
||||
// CHECK:STDOUT: store ptr %StructLiteralValue1, ptr %var, align 8
|
||||
// CHECK:STDOUT: %StructLiteralValue2 = alloca %StructLiteralType.1, align 8
|
||||
// CHECK:STDOUT: %var3 = alloca %StructLiteralType.1, align 8
|
||||
// CHECK:STDOUT: %StructLiteralValue2 = alloca %StructLiteralType, align 8
|
||||
// CHECK:STDOUT: %var3 = alloca %StructLiteralType, align 8
|
||||
// CHECK:STDOUT: store ptr %var, ptr %var3, align 8
|
||||
// CHECK:STDOUT: ret i32 0
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
+3
-4
@@ -7,15 +7,14 @@
|
||||
// CHECK:STDOUT: source_filename = "member_access.carbon"
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: %StructLiteralType = type { double, i32 }
|
||||
// CHECK:STDOUT: %StructLiteralType.0 = type { double, i32 }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: define i32 @Run() {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %var = alloca %StructLiteralType, align 8
|
||||
// CHECK:STDOUT: %StructLiteralValue = alloca %StructLiteralType.0, align 8
|
||||
// CHECK:STDOUT: %a = getelementptr inbounds %StructLiteralType.0, ptr %StructLiteralValue, i32 0, i32 0
|
||||
// CHECK:STDOUT: %StructLiteralValue = alloca %StructLiteralType, align 8
|
||||
// CHECK:STDOUT: %a = getelementptr inbounds %StructLiteralType, ptr %StructLiteralValue, i32 0, i32 0
|
||||
// CHECK:STDOUT: store double 0.000000e+00, ptr %a, align 8
|
||||
// CHECK:STDOUT: %b = getelementptr inbounds %StructLiteralType.0, ptr %StructLiteralValue, i32 0, i32 1
|
||||
// CHECK:STDOUT: %b = getelementptr inbounds %StructLiteralType, ptr %StructLiteralValue, i32 0, i32 1
|
||||
// CHECK:STDOUT: store i32 1, ptr %b, align 4
|
||||
// CHECK:STDOUT: store ptr %StructLiteralValue, ptr %var, align 8
|
||||
// CHECK:STDOUT: %var1 = alloca i32, align 4
|
||||
|
||||
+3
-5
@@ -7,17 +7,15 @@
|
||||
// CHECK:STDOUT: source_filename = "one_entry.carbon"
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: %StructLiteralType = type { i32 }
|
||||
// CHECK:STDOUT: %StructLiteralType.0 = type { i32 }
|
||||
// CHECK:STDOUT: %StructLiteralType.1 = type { i32 }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: define i32 @Run() {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %var = alloca %StructLiteralType, align 8
|
||||
// CHECK:STDOUT: %StructLiteralValue = alloca %StructLiteralType.0, align 8
|
||||
// CHECK:STDOUT: %a = getelementptr inbounds %StructLiteralType.0, ptr %StructLiteralValue, i32 0, i32 0
|
||||
// CHECK:STDOUT: %StructLiteralValue = alloca %StructLiteralType, align 8
|
||||
// CHECK:STDOUT: %a = getelementptr inbounds %StructLiteralType, ptr %StructLiteralValue, i32 0, i32 0
|
||||
// CHECK:STDOUT: store i32 4, ptr %a, align 4
|
||||
// CHECK:STDOUT: store ptr %StructLiteralValue, ptr %var, align 8
|
||||
// CHECK:STDOUT: %var1 = alloca %StructLiteralType.1, align 8
|
||||
// CHECK:STDOUT: %var1 = alloca %StructLiteralType, align 8
|
||||
// CHECK:STDOUT: store ptr %var, ptr %var1, align 8
|
||||
// CHECK:STDOUT: ret i32 0
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
+4
-6
@@ -7,19 +7,17 @@
|
||||
// CHECK:STDOUT: source_filename = "two_entries.carbon"
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: %StructLiteralType = type { i32, i32 }
|
||||
// CHECK:STDOUT: %StructLiteralType.0 = type { i32, i32 }
|
||||
// CHECK:STDOUT: %StructLiteralType.1 = type { i32, i32 }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: define i32 @Run() {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %var = alloca %StructLiteralType, align 8
|
||||
// CHECK:STDOUT: %StructLiteralValue = alloca %StructLiteralType.0, align 8
|
||||
// CHECK:STDOUT: %a = getelementptr inbounds %StructLiteralType.0, ptr %StructLiteralValue, i32 0, i32 0
|
||||
// CHECK:STDOUT: %StructLiteralValue = alloca %StructLiteralType, align 8
|
||||
// CHECK:STDOUT: %a = getelementptr inbounds %StructLiteralType, ptr %StructLiteralValue, i32 0, i32 0
|
||||
// CHECK:STDOUT: store i32 1, ptr %a, align 4
|
||||
// CHECK:STDOUT: %b = getelementptr inbounds %StructLiteralType.0, ptr %StructLiteralValue, i32 0, i32 1
|
||||
// CHECK:STDOUT: %b = getelementptr inbounds %StructLiteralType, ptr %StructLiteralValue, i32 0, i32 1
|
||||
// CHECK:STDOUT: store i32 2, ptr %b, align 4
|
||||
// CHECK:STDOUT: store ptr %StructLiteralValue, ptr %var, align 8
|
||||
// CHECK:STDOUT: %var1 = alloca %StructLiteralType.1, align 8
|
||||
// CHECK:STDOUT: %var1 = alloca %StructLiteralType, align 8
|
||||
// CHECK:STDOUT: store ptr %var, ptr %var1, align 8
|
||||
// CHECK:STDOUT: ret i32 0
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
@@ -282,19 +282,7 @@ auto SemanticsContext::ImplicitAsImpl(SemanticsNodeId value_id,
|
||||
}
|
||||
}
|
||||
|
||||
if (value_type_id != SemanticsTypeId::TypeType &&
|
||||
as_type_id != SemanticsTypeId::TypeType) {
|
||||
auto value_type = semantics_->GetNode(semantics_->GetType(value_type_id));
|
||||
auto as_type = semantics_->GetNode(semantics_->GetType(as_type_id));
|
||||
if (CanImplicitAsStruct(value_type, as_type)) {
|
||||
// Under the current implementation, struct types are only allowed to
|
||||
// ImplicitAs when they're equivalent. What's really missing is type
|
||||
// consolidation such that this would fall under the above `value_type_id
|
||||
// == as_type_id` case. In the future, this will need to handle actual
|
||||
// conversions.
|
||||
return ImplicitAsKind::Identical;
|
||||
}
|
||||
}
|
||||
// TODO: Handle ImplicitAs for compatible structs and tuples.
|
||||
|
||||
if (output_value_id != nullptr) {
|
||||
*output_value_id = SemanticsNodeId::BuiltinInvalidType;
|
||||
@@ -302,30 +290,6 @@ auto SemanticsContext::ImplicitAsImpl(SemanticsNodeId value_id,
|
||||
return ImplicitAsKind::Incompatible;
|
||||
}
|
||||
|
||||
auto SemanticsContext::CanImplicitAsStruct(SemanticsNode value_type,
|
||||
SemanticsNode as_type) -> bool {
|
||||
if (value_type.kind() != SemanticsNodeKind::StructType ||
|
||||
as_type.kind() != SemanticsNodeKind::StructType) {
|
||||
return false;
|
||||
}
|
||||
auto value_type_refs = semantics_->GetNodeBlock(value_type.GetAsStructType());
|
||||
auto as_type_refs = semantics_->GetNodeBlock(as_type.GetAsStructType());
|
||||
if (value_type_refs.size() != as_type_refs.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < static_cast<int>(value_type_refs.size()); ++i) {
|
||||
auto value_type_field = semantics_->GetNode(value_type_refs[i]);
|
||||
auto as_type_field = semantics_->GetNode(as_type_refs[i]);
|
||||
if (value_type_field.type_id() != as_type_field.type_id() ||
|
||||
value_type_field.GetAsStructTypeField() !=
|
||||
as_type_field.GetAsStructTypeField()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
auto SemanticsContext::ParamOrArgStart() -> void {
|
||||
params_or_args_stack_.Push();
|
||||
}
|
||||
@@ -380,6 +344,38 @@ auto SemanticsContext::CanonicalizeType(SemanticsNodeId node_id)
|
||||
return type_id;
|
||||
}
|
||||
|
||||
auto SemanticsContext::CanonicalizeStructType(ParseTree::Node parse_node,
|
||||
SemanticsNodeBlockId refs_id)
|
||||
-> SemanticsTypeId {
|
||||
// Construct the field structure for lookup.
|
||||
auto refs = semantics_->GetNodeBlock(refs_id);
|
||||
llvm::FoldingSetNodeID canonical_id;
|
||||
for (const auto& ref_id : refs) {
|
||||
auto ref = semantics_->GetNode(ref_id);
|
||||
canonical_id.AddInteger(ref.GetAsStructTypeField().index);
|
||||
canonical_id.AddInteger(ref.type_id().index);
|
||||
}
|
||||
|
||||
// If a struct with matching fields was already created, reuse it.
|
||||
void* insert_pos;
|
||||
auto* node =
|
||||
canonical_struct_types_.FindNodeOrInsertPos(canonical_id, insert_pos);
|
||||
if (node != nullptr) {
|
||||
return node->type_id();
|
||||
}
|
||||
|
||||
// The struct doesn't already exist, so create and store it as canonical.
|
||||
auto node_id = AddNode(SemanticsNode::StructType::Make(
|
||||
parse_node, SemanticsTypeId::TypeType, refs_id));
|
||||
auto type_id = semantics_->AddType(node_id);
|
||||
CARBON_CHECK(canonical_types_.insert({node_id, type_id}).second);
|
||||
canonical_struct_types_nodes_.push_back(
|
||||
std::make_unique<StructTypeNode>(canonical_id, type_id));
|
||||
canonical_struct_types_.InsertNode(canonical_struct_types_nodes_.back().get(),
|
||||
insert_pos);
|
||||
return type_id;
|
||||
}
|
||||
|
||||
auto SemanticsContext::PrintForStackDump(llvm::raw_ostream& output) const
|
||||
-> void {
|
||||
node_stack_.PrintForStackDump(output);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "toolchain/parser/parse_tree.h"
|
||||
#include "toolchain/semantics/semantics_ir.h"
|
||||
@@ -97,6 +98,16 @@ class SemanticsContext {
|
||||
// TODO: This should eventually return a type ID.
|
||||
auto CanonicalizeType(SemanticsNodeId node_id) -> SemanticsTypeId;
|
||||
|
||||
// Handles canonicalization of struct types. This may create a new struct type
|
||||
// when it has a new structure, or reference an existing struct type when it
|
||||
// duplicates a prior type.
|
||||
//
|
||||
// Individual struct type fields aren't canonicalized because they may have
|
||||
// name conflicts or other diagnostics during creation, which can use the
|
||||
// parse node.
|
||||
auto CanonicalizeStructType(ParseTree::Node parse_node,
|
||||
SemanticsNodeBlockId refs_id) -> SemanticsTypeId;
|
||||
|
||||
// Converts an expression for use as a type.
|
||||
// TODO: This should eventually return a type ID.
|
||||
auto ExpressionAsType(ParseTree::Node parse_node, SemanticsNodeId value_id)
|
||||
@@ -161,6 +172,19 @@ class SemanticsContext {
|
||||
Compatible,
|
||||
};
|
||||
|
||||
// A FoldingSet node for a struct type.
|
||||
class StructTypeNode : public llvm::FastFoldingSetNode {
|
||||
public:
|
||||
explicit StructTypeNode(const llvm::FoldingSetNodeID& node_id,
|
||||
SemanticsTypeId type_id)
|
||||
: llvm::FastFoldingSetNode(node_id), type_id_(type_id) {}
|
||||
|
||||
auto type_id() -> SemanticsTypeId { return type_id_; }
|
||||
|
||||
private:
|
||||
SemanticsTypeId type_id_;
|
||||
};
|
||||
|
||||
// An entry in scope_stack_.
|
||||
struct ScopeStackEntry {
|
||||
// Names which are registered with name_lookup_, and will need to be
|
||||
@@ -185,11 +209,6 @@ class SemanticsContext {
|
||||
auto ImplicitAsImpl(SemanticsNodeId value_id, SemanticsTypeId as_type_id,
|
||||
SemanticsNodeId* output_value_id) -> ImplicitAsKind;
|
||||
|
||||
// Returns true if the ImplicitAs can use struct conversion.
|
||||
// TODO: This currently only supports struct types that precisely match.
|
||||
auto CanImplicitAsStruct(SemanticsNode value_type, SemanticsNode as_type)
|
||||
-> bool;
|
||||
|
||||
auto current_scope() -> ScopeStackEntry& { return scope_stack_.back(); }
|
||||
|
||||
// Tokens for getting data on literals.
|
||||
@@ -244,6 +263,15 @@ class SemanticsContext {
|
||||
// Tracks types which have been used, so that they aren't repeatedly added to
|
||||
// SemanticsIR.
|
||||
llvm::DenseMap<SemanticsNodeId, SemanticsTypeId> canonical_types_;
|
||||
|
||||
// Tracks struct type literals which have been defined, so that they aren't
|
||||
// repeatedly redefined.
|
||||
llvm::FoldingSet<StructTypeNode> canonical_struct_types_;
|
||||
|
||||
// Storage for the nodes in canonical_struct_types_. This stores in pointers
|
||||
// so that canonical_struct_types_ can have stable pointers.
|
||||
llvm::SmallVector<std::unique_ptr<StructTypeNode>>
|
||||
canonical_struct_types_nodes_;
|
||||
};
|
||||
|
||||
// Parse node handlers. Returns false for unrecoverable errors.
|
||||
|
||||
@@ -74,13 +74,7 @@ auto SemanticsHandleStructLiteral(SemanticsContext& context,
|
||||
ParseNodeKind::StructLiteralOrStructTypeLiteralStart);
|
||||
auto type_block_id = context.args_type_info_stack().Pop();
|
||||
|
||||
// Construct a type for the literal.
|
||||
// TODO: This should try to canonicalize the struct form before adding the
|
||||
// node.
|
||||
auto refs = context.semantics().GetNodeBlock(refs_id);
|
||||
auto type_id =
|
||||
context.CanonicalizeType(context.AddNode(SemanticsNode::StructType::Make(
|
||||
parse_node, SemanticsTypeId::TypeType, type_block_id)));
|
||||
auto type_id = context.CanonicalizeStructType(parse_node, type_block_id);
|
||||
|
||||
auto value_id = context.AddNode(
|
||||
SemanticsNode::StructValue::Make(parse_node, type_id, refs_id));
|
||||
@@ -114,9 +108,8 @@ auto SemanticsHandleStructTypeLiteral(SemanticsContext& context,
|
||||
CARBON_CHECK(refs_id != SemanticsNodeBlockId::Empty)
|
||||
<< "{} is handled by StructLiteral.";
|
||||
|
||||
auto type_id = context.AddNode(SemanticsNode::StructType::Make(
|
||||
parse_node, SemanticsTypeId::TypeType, refs_id));
|
||||
context.node_stack().Push(parse_node, type_id);
|
||||
auto type_id = context.CanonicalizeStructType(parse_node, refs_id);
|
||||
context.node_stack().Push(parse_node, context.semantics().GetType(type_id));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+15
-21
@@ -5,7 +5,7 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: callables: [
|
||||
// CHECK:STDOUT: {param_refs: block2, return_type: type1},
|
||||
// CHECK:STDOUT: {param_refs: block2, return_type: type0},
|
||||
// CHECK:STDOUT: {param_refs: block0},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
@@ -19,26 +19,22 @@
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: types: [
|
||||
// CHECK:STDOUT: node+0,
|
||||
// CHECK:STDOUT: node+4,
|
||||
// CHECK:STDOUT: nodeEmptyTupleType,
|
||||
// CHECK:STDOUT: node+10,
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: nodes: [
|
||||
// CHECK:STDOUT: {kind: StructType, arg0: block0, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block0, type: type0},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type0},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+2, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructType, arg0: block0, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block0, type: type1},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block0, type: type0},
|
||||
// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str1, arg1: callable0},
|
||||
// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+2, type: type0},
|
||||
// CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+6, arg1: block4},
|
||||
// CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+5, arg1: block4},
|
||||
// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str2, arg1: callable1},
|
||||
// CHECK:STDOUT: {kind: StructType, arg0: block0, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block0, type: type3},
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+11, type: type3},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block6, arg1: callable0, type: type1},
|
||||
// CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+9, arg1: block5},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block0, type: type0},
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+9, type: type0},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block6, arg1: callable0, type: type0},
|
||||
// CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+8, arg1: block5},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: node_blocks: [
|
||||
// CHECK:STDOUT: [
|
||||
@@ -55,22 +51,20 @@
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+4,
|
||||
// CHECK:STDOUT: node+5,
|
||||
// CHECK:STDOUT: node+6,
|
||||
// CHECK:STDOUT: node+7,
|
||||
// CHECK:STDOUT: node+8,
|
||||
// CHECK:STDOUT: node+9,
|
||||
// CHECK:STDOUT: node+14,
|
||||
// CHECK:STDOUT: node+12,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+7,
|
||||
// CHECK:STDOUT: node+6,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+9,
|
||||
// CHECK:STDOUT: node+10,
|
||||
// CHECK:STDOUT: node+11,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+10,
|
||||
// CHECK:STDOUT: node+11,
|
||||
// CHECK:STDOUT: node+12,
|
||||
// CHECK:STDOUT: node+13,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+12,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
|
||||
+3
-6
@@ -19,7 +19,6 @@
|
||||
// CHECK:STDOUT: types: [
|
||||
// CHECK:STDOUT: nodeIntegerType,
|
||||
// CHECK:STDOUT: node+1,
|
||||
// CHECK:STDOUT: node+6,
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: nodes: [
|
||||
// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: type0},
|
||||
@@ -28,9 +27,8 @@
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: type0},
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+3, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructType, arg0: block4, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block5, type: type2},
|
||||
// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+7, type: type2},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block5, type: type1},
|
||||
// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+6, type: type1},
|
||||
// CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+2, arg1: block3},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: node_blocks: [
|
||||
@@ -40,7 +38,7 @@
|
||||
// CHECK:STDOUT: node+0,
|
||||
// CHECK:STDOUT: node+1,
|
||||
// CHECK:STDOUT: node+2,
|
||||
// CHECK:STDOUT: node+9,
|
||||
// CHECK:STDOUT: node+8,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+0,
|
||||
@@ -50,7 +48,6 @@
|
||||
// CHECK:STDOUT: node+5,
|
||||
// CHECK:STDOUT: node+6,
|
||||
// CHECK:STDOUT: node+7,
|
||||
// CHECK:STDOUT: node+8,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+4,
|
||||
|
||||
+6
-12
@@ -16,22 +16,18 @@
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: types: [
|
||||
// CHECK:STDOUT: node+0,
|
||||
// CHECK:STDOUT: node+4,
|
||||
// CHECK:STDOUT: node+7,
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: nodes: [
|
||||
// CHECK:STDOUT: {kind: StructType, arg0: block0, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block0, type: type0},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type0},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+2, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructType, arg0: block0, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block0, type: type1},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: node+5, type: type1},
|
||||
// CHECK:STDOUT: {kind: StructType, arg0: block0, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block0, type: type2},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type2},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+9, type: type2},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+9, arg1: node+2, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block0, type: type0},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: node+4, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block0, type: type0},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type0},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+7, type: type0},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+7, arg1: node+2, type: type0},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: node_blocks: [
|
||||
// CHECK:STDOUT: [
|
||||
@@ -47,8 +43,6 @@
|
||||
// CHECK:STDOUT: node+7,
|
||||
// CHECK:STDOUT: node+8,
|
||||
// CHECK:STDOUT: node+9,
|
||||
// CHECK:STDOUT: node+10,
|
||||
// CHECK:STDOUT: node+11,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
// CHECK:STDOUT: types: [
|
||||
// CHECK:STDOUT: nodeFloatingPointType,
|
||||
// CHECK:STDOUT: node+1,
|
||||
// CHECK:STDOUT: node+7,
|
||||
// CHECK:STDOUT: nodeIntegerType,
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: nodes: [
|
||||
@@ -31,12 +30,11 @@
|
||||
// CHECK:STDOUT: {kind: RealLiteral, arg0: real0, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: type0},
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+4, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructType, arg0: block3, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block4, type: type2},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: node+8, type: type2},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type3},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+10, type: type3},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+10, arg1: nodeInvalidType, type: typeInvalidType},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block4, type: type1},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: node+7, type: type1},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type2},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+9, type: type2},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+9, arg1: nodeInvalidType, type: typeInvalidType},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: node_blocks: [
|
||||
// CHECK:STDOUT: [
|
||||
@@ -53,7 +51,6 @@
|
||||
// CHECK:STDOUT: node+9,
|
||||
// CHECK:STDOUT: node+10,
|
||||
// CHECK:STDOUT: node+11,
|
||||
// CHECK:STDOUT: node+12,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+0,
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
// CHECK:STDOUT: types: [
|
||||
// CHECK:STDOUT: nodeIntegerType,
|
||||
// CHECK:STDOUT: node+1,
|
||||
// CHECK:STDOUT: node+7,
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: nodes: [
|
||||
// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: type0},
|
||||
@@ -30,12 +29,11 @@
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: type0},
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+4, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructType, arg0: block3, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block4, type: type2},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: node+8, type: type2},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block4, type: type1},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: node+7, type: type1},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type0},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+10, type: type0},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+10, arg1: nodeInvalidType, type: typeInvalidType},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+9, type: type0},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+9, arg1: nodeInvalidType, type: typeInvalidType},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: node_blocks: [
|
||||
// CHECK:STDOUT: [
|
||||
@@ -52,7 +50,6 @@
|
||||
// CHECK:STDOUT: node+9,
|
||||
// CHECK:STDOUT: node+10,
|
||||
// CHECK:STDOUT: node+11,
|
||||
// CHECK:STDOUT: node+12,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+0,
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type1},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+2, type: type1},
|
||||
// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructType, arg0: block3, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: nodeInvalidType, type: typeInvalidType},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: node_blocks: [
|
||||
@@ -37,7 +36,6 @@
|
||||
// CHECK:STDOUT: node+3,
|
||||
// CHECK:STDOUT: node+4,
|
||||
// CHECK:STDOUT: node+5,
|
||||
// CHECK:STDOUT: node+6,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+0,
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
// CHECK:STDOUT: nodeFloatingPointType,
|
||||
// CHECK:STDOUT: nodeIntegerType,
|
||||
// CHECK:STDOUT: node+2,
|
||||
// CHECK:STDOUT: node+11,
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: nodes: [
|
||||
// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: type0},
|
||||
@@ -37,16 +36,15 @@
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1},
|
||||
// CHECK:STDOUT: {kind: StructTypeField, arg0: str1, type: type1},
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+8, type: type1},
|
||||
// CHECK:STDOUT: {kind: StructType, arg0: block3, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block4, type: type3},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+3, arg1: node+12, type: type3},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block4, type: type2},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+3, arg1: node+11, type: type2},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type1},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str3, arg1: node+14, type: type1},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str3, arg1: node+13, type: type1},
|
||||
// CHECK:STDOUT: {kind: StructMemberAccess, arg0: node+3, arg1: member1, type: type1},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+14, arg1: node+16, type: type1},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+13, arg1: node+15, type: type1},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type1},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str4, arg1: node+18, type: type1},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+18, arg1: node+14, type: type1},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str4, arg1: node+17, type: type1},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+17, arg1: node+13, type: type1},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: node_blocks: [
|
||||
// CHECK:STDOUT: [
|
||||
@@ -70,7 +68,6 @@
|
||||
// CHECK:STDOUT: node+17,
|
||||
// CHECK:STDOUT: node+18,
|
||||
// CHECK:STDOUT: node+19,
|
||||
// CHECK:STDOUT: node+20,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+0,
|
||||
|
||||
+6
-12
@@ -19,8 +19,6 @@
|
||||
// CHECK:STDOUT: types: [
|
||||
// CHECK:STDOUT: nodeIntegerType,
|
||||
// CHECK:STDOUT: node+1,
|
||||
// CHECK:STDOUT: node+7,
|
||||
// CHECK:STDOUT: node+11,
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: nodes: [
|
||||
// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: type0},
|
||||
@@ -30,14 +28,12 @@
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: type0},
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+4, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructType, arg0: block3, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block4, type: type2},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: node+8, type: type2},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block4, type: type1},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: node+7, type: type1},
|
||||
// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructType, arg0: block5, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type3},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+12, type: type3},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+12, arg1: node+2, type: type1},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type1},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+10, type: type1},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+10, arg1: node+2, type: type1},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: node_blocks: [
|
||||
// CHECK:STDOUT: [
|
||||
@@ -55,8 +51,6 @@
|
||||
// CHECK:STDOUT: node+10,
|
||||
// CHECK:STDOUT: node+11,
|
||||
// CHECK:STDOUT: node+12,
|
||||
// CHECK:STDOUT: node+13,
|
||||
// CHECK:STDOUT: node+14,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+0,
|
||||
@@ -68,7 +62,7 @@
|
||||
// CHECK:STDOUT: node+6,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+10,
|
||||
// CHECK:STDOUT: node+9,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
|
||||
+6
-12
@@ -21,8 +21,6 @@
|
||||
// CHECK:STDOUT: types: [
|
||||
// CHECK:STDOUT: nodeIntegerType,
|
||||
// CHECK:STDOUT: node+2,
|
||||
// CHECK:STDOUT: node+11,
|
||||
// CHECK:STDOUT: node+16,
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: nodes: [
|
||||
// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: type0},
|
||||
@@ -36,15 +34,13 @@
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructTypeField, arg0: str1, type: type0},
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+8, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructType, arg0: block3, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block4, type: type2},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+3, arg1: node+12, type: type2},
|
||||
// CHECK:STDOUT: {kind: StructValue, arg0: block4, type: type1},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+3, arg1: node+11, type: type1},
|
||||
// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructTypeField, arg0: str1, type: type0},
|
||||
// CHECK:STDOUT: {kind: StructType, arg0: block5, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type3},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str3, arg1: node+17, type: type3},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+17, arg1: node+3, type: type1},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type1},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str3, arg1: node+15, type: type1},
|
||||
// CHECK:STDOUT: {kind: Assign, arg0: node+15, arg1: node+3, type: type1},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: node_blocks: [
|
||||
// CHECK:STDOUT: [
|
||||
@@ -66,8 +62,6 @@
|
||||
// CHECK:STDOUT: node+15,
|
||||
// CHECK:STDOUT: node+16,
|
||||
// CHECK:STDOUT: node+17,
|
||||
// CHECK:STDOUT: node+18,
|
||||
// CHECK:STDOUT: node+19,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+0,
|
||||
@@ -82,8 +76,8 @@
|
||||
// CHECK:STDOUT: node+10,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+13,
|
||||
// CHECK:STDOUT: node+14,
|
||||
// CHECK:STDOUT: node+15,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user