diff --git a/ast/expressions.go b/ast/expressions.go index c8034ec51..3c1b0125d 100644 --- a/ast/expressions.go +++ b/ast/expressions.go @@ -281,6 +281,25 @@ type ( PositionalArgs []BLangExpression // TODO: Add support for NamedArgs } + + BLangMappingKey struct { + BLangNodeBase + Expr BLangExpression + ComputedKey bool + } + + BLangMappingKeyValueField struct { + BLangNodeBase + Key *BLangMappingKey + ValueExpr BLangExpression + Readonly bool + } + + BLangMappingConstructorExpr struct { + BLangExpressionBase + Fields []model.MappingField + AtomicType semtypes.MappingAtomicType + } ) var ( @@ -293,7 +312,7 @@ var ( _ model.LiteralNode = &BLangConstRef{} _ model.LiteralNode = &BLangLiteral{} _ BLangExpression = &BLangLiteral{} - _ model.RecordVarNameFieldNode = &BLangConstRef{} + _ model.MappingVarNameFieldNode = &BLangConstRef{} _ model.DynamicArgNode = &BLangDynamicArgExpr{} _ model.ElvisExpressionNode = &BLangElvisExpr{} _ model.MarkdownDocumentationTextAttributeNode = &BLangMarkdownDocumentationLine{} @@ -316,6 +335,12 @@ var ( _ BLangExpression = &BLangTypeConversionExpr{} _ BLangExpression = &BLangErrorConstructorExpr{} _ BLangNode = &BLangErrorConstructorExpr{} + _ model.MappingConstructor = &BLangMappingConstructorExpr{} + _ model.MappingKeyValueFieldNode = &BLangMappingKeyValueField{} + _ BLangExpression = &BLangMappingConstructorExpr{} + _ BLangNode = &BLangMappingConstructorExpr{} + _ model.Node = &BLangMappingKey{} + _ BLangNode = &BLangMappingKey{} ) var ( @@ -348,6 +373,9 @@ var ( _ BLangNode = &BLangIndexBasedAccess{} _ BLangNode = &BLangListConstructorExpr{} _ BLangNode = &BLangTypeConversionExpr{} + _ BLangNode = &BLangMappingConstructorExpr{} + _ BLangNode = &BLangMappingKeyValueField{} + _ BLangNode = &BLangMappingKey{} ) var ( @@ -954,6 +982,41 @@ func (this *BLangErrorConstructorExpr) SetTypeCheckedType(ty BType) { panic("not implemented") } +func (this *BLangMappingKey) GetKind() model.NodeKind { + panic("BLangMappingKey has no NodeKind") +} + +func (this *BLangMappingKeyValueField) GetKind() model.NodeKind { + return model.NodeKind_RECORD_LITERAL_KEY_VALUE +} + +func (this *BLangMappingKeyValueField) GetKey() model.ExpressionNode { + if this.Key == nil { + return nil + } + return this.Key.Expr +} + +func (this *BLangMappingKeyValueField) GetValue() model.ExpressionNode { + return this.ValueExpr +} + +func (this *BLangMappingKeyValueField) IsKeyValueField() bool { + return true +} + +func (this *BLangMappingConstructorExpr) GetKind() model.NodeKind { + return model.NodeKind_RECORD_LITERAL_EXPR +} + +func (this *BLangMappingConstructorExpr) GetFields() []model.MappingField { + return this.Fields +} + +func (this *BLangMappingConstructorExpr) SetTypeCheckedType(ty BType) { + this.ExpectedType = ty +} + func createBLangUnaryExpr(location Location, operator model.OperatorKind, expr BLangExpression) *BLangUnaryExpr { exprNode := &BLangUnaryExpr{} exprNode.pos = location diff --git a/ast/node_builder.go b/ast/node_builder.go index 9d1228c7b..bddb68c6b 100644 --- a/ast/node_builder.go +++ b/ast/node_builder.go @@ -1795,7 +1795,53 @@ func (n *NodeBuilder) TransformMethodCallExpression(methodCallExpressionNode *tr } func (n *NodeBuilder) TransformMappingConstructorExpression(mappingConstructorExpressionNode *tree.MappingConstructorExpressionNode) BLangNode { - panic("TransformMappingConstructorExpression unimplemented") + mappingConstructor := &BLangMappingConstructorExpr{ + Fields: make([]model.MappingField, 0), + } + fields := mappingConstructorExpressionNode.FieldNodes() + for i := 0; i < fields.Size(); i += 2 { + field := fields.Get(i) + switch field.Kind() { + case common.SPREAD_FIELD: + panic("mapping constructor spread field not implemented") + case common.COMPUTED_NAME_FIELD: + computedNameField := field.(*tree.ComputedNameFieldNode) + keyExpr := n.createExpression(computedNameField.FieldNameExpr()) + key := &BLangMappingKey{ + Expr: keyExpr, + ComputedKey: true, + } + key.SetPosition(getPosition(computedNameField.FieldNameExpr())) + keyValueField := &BLangMappingKeyValueField{ + Key: key, + ValueExpr: n.createExpression(computedNameField.ValueExpr()), + } + keyValueField.SetPosition(getPosition(computedNameField)) + mappingConstructor.Fields = append(mappingConstructor.Fields, keyValueField) + case common.SPECIFIC_FIELD: + specificField := field.(*tree.SpecificFieldNode) + if specificField.ValueExpr() == nil { + panic("mapping constructor var-name field not implemented") + } + keyExpr := n.createExpression(specificField.FieldName()) + key := &BLangMappingKey{ + Expr: keyExpr, + ComputedKey: false, + } + key.SetPosition(getPosition(specificField.FieldName())) + keyValueField := &BLangMappingKeyValueField{ + Key: key, + ValueExpr: n.createExpression(specificField.ValueExpr()), + Readonly: specificField.ReadonlyKeyword() != nil, + } + keyValueField.SetPosition(getPosition(specificField)) + mappingConstructor.Fields = append(mappingConstructor.Fields, keyValueField) + default: + panic(fmt.Sprintf("unexpected mapping field kind: %v", field.Kind())) + } + } + mappingConstructor.SetPosition(getPosition(mappingConstructorExpressionNode)) + return mappingConstructor } func (n *NodeBuilder) TransformIndexedExpression(indexedExpressionNode *tree.IndexedExpressionNode) BLangNode { @@ -2097,7 +2143,23 @@ func (n *NodeBuilder) TransformRemoteMethodCallAction(remoteMethodCallActionNode } func (n *NodeBuilder) TransformMapTypeDescriptor(mapTypeDescriptorNode *tree.MapTypeDescriptorNode) BLangNode { - panic("TransformMapTypeDescriptor unimplemented") + refType := &BLangBuiltInRefTypeNode{ + TypeKind: model.TypeKind_MAP, + } + refType.SetPosition(getPosition(mapTypeDescriptorNode)) + + mapTypeParamsNode := mapTypeDescriptorNode.MapTypeParamsNode() + if mapTypeParamsNode == nil || mapTypeParamsNode.TypeNode() == nil { + panic("map type requires type parameter") + } + constraint := n.createTypeNode(mapTypeParamsNode.TypeNode()) + + constrainedType := &BLangConstrainedType{ + Type: model.TypeData{TypeDescriptor: refType}, + Constraint: model.TypeData{TypeDescriptor: constraint}, + } + constrainedType.SetPosition(refType.GetPosition()) + return constrainedType } func (n *NodeBuilder) TransformNilLiteral(nilLiteralNode *tree.NilLiteralNode) BLangNode { diff --git a/ast/pretty_printer.go b/ast/pretty_printer.go index 3ec9f60ca..cf03d1ba4 100644 --- a/ast/pretty_printer.go +++ b/ast/pretty_printer.go @@ -104,6 +104,8 @@ func (p *PrettyPrinter) PrintInner(node BLangNode) { p.printUnionTypeNode(t) case *BLangErrorTypeNode: p.printErrorTypeNode(t) + case *BLangConstrainedType: + p.printConstrainedType(t) case *BLangTypeDefinition: p.printTypeDefinition(t) case *BLangUserDefinedType: @@ -112,6 +114,8 @@ func (p *PrettyPrinter) PrintInner(node BLangNode) { p.printFiniteTypeNode(t) case *BLangListConstructorExpr: p.printListConstructorExpr(t) + case *BLangMappingConstructorExpr: + p.printMappingConstructor(t) case *BLangTypeConversionExpr: p.printTypeConversionExpr(t) default: @@ -647,6 +651,34 @@ func (p *PrettyPrinter) printListConstructorExpr(node *BLangListConstructorExpr) p.endNode() } +func (p *PrettyPrinter) printMappingConstructor(node *BLangMappingConstructorExpr) { + p.startNode() + p.printString("mapping-constructor-expr") + p.indentLevel++ + for _, f := range node.Fields { + if kv, ok := f.(*BLangMappingKeyValueField); ok { + p.printMappingKeyValueField(kv) + } + } + p.indentLevel-- + p.endNode() +} + +// Mapping key-value field printer: prints as (key-value (key) (value)) +func (p *PrettyPrinter) printMappingKeyValueField(kv *BLangMappingKeyValueField) { + p.startNode() + p.printString("key-value") + p.indentLevel++ + if kv.Key != nil && kv.Key.Expr != nil { + p.PrintInner(kv.Key.Expr.(BLangNode)) + } + if kv.ValueExpr != nil { + p.PrintInner(kv.ValueExpr.(BLangNode)) + } + p.indentLevel-- + p.endNode() +} + // Wildcard binding pattern printer func (p *PrettyPrinter) printWildCardBindingPattern(node *BLangWildCardBindingPattern) { p.startNode() @@ -689,6 +721,20 @@ func (p *PrettyPrinter) printErrorTypeNode(node *BLangErrorTypeNode) { p.endNode() } +func (p *PrettyPrinter) printConstrainedType(node *BLangConstrainedType) { + p.startNode() + p.printString("constrained-type") + p.indentLevel++ + if node.Type.TypeDescriptor != nil { + p.PrintInner(node.Type.TypeDescriptor.(BLangNode)) + } + if node.Constraint.TypeDescriptor != nil { + p.PrintInner(node.Constraint.TypeDescriptor.(BLangNode)) + } + p.indentLevel-- + p.endNode() +} + // Type definition printer func (p *PrettyPrinter) printTypeDefinition(node *BLangTypeDefinition) { p.startNode() diff --git a/ast/types.go b/ast/types.go index 06db5d6da..c5b5888f7 100644 --- a/ast/types.go +++ b/ast/types.go @@ -131,6 +131,13 @@ type ( BLangTypeBase detailType model.TypeData } + + BLangConstrainedType struct { + BLangTypeBase + Type model.TypeData + Constraint model.TypeData + Definition semtypes.Definition + } ) var ( @@ -145,6 +152,7 @@ var ( _ BNodeWithSymbol = &BLangUserDefinedType{} _ model.UnionTypeNode = &BLangUnionTypeNode{} _ model.ErrorTypeNode = &BLangErrorTypeNode{} + _ model.ConstrainedTypeNode = &BLangConstrainedType{} ) var ( @@ -159,7 +167,9 @@ var ( _ BLangNode = &BLangArrayType{} _ BLangNode = &BLangUserDefinedType{} _ BLangNode = &BLangValueType{} + _ BLangNode = &BLangConstrainedType{} _ model.TypeDescriptor = &BLangValueType{} + _ model.TypeDescriptor = &BLangConstrainedType{} ) func (this *BLangArrayType) GetKind() model.NodeKind { @@ -430,3 +440,25 @@ func (this *BLangErrorTypeNode) GetKind() model.NodeKind { func (this *BLangErrorTypeNode) IsDistinct() bool { return this.FlagSet.Contains(model.Flag_DISTINCT) } + +func (this *BLangConstrainedType) GetKind() model.NodeKind { + return model.NodeKind_CONSTRAINED_TYPE +} + +func (this *BLangConstrainedType) GetType() model.TypeData { + return this.Type +} + +func (this *BLangConstrainedType) GetConstraint() model.TypeData { + return this.Constraint +} + +func (this *BLangConstrainedType) GetTypeKind() model.TypeKind { + if this.Type.TypeDescriptor == nil { + panic("base type is nil") + } + if builtIn, ok := this.Type.TypeDescriptor.(model.BuiltInReferenceTypeNode); ok { + return builtIn.GetTypeKind() + } + panic("BLangConstrainedType.Type does not implement BuiltInReferenceTypeNode") +} diff --git a/ast/walk.go b/ast/walk.go index 9e40ee17d..aea16c6f3 100644 --- a/ast/walk.go +++ b/ast/walk.go @@ -406,6 +406,17 @@ func Walk(v Visitor, node BLangNode) { for _, expr := range node.Exprs { Walk(v, expr.(BLangNode)) } + case *BLangMappingConstructorExpr: + for _, f := range node.Fields { + if kv, ok := f.(*BLangMappingKeyValueField); ok { + if kv.Key != nil && kv.Key.Expr != nil { + Walk(v, kv.Key.Expr.(BLangNode)) + } + if kv.ValueExpr != nil { + Walk(v, kv.ValueExpr.(BLangNode)) + } + } + } case *BLangErrorConstructorExpr: if node.ErrorTypeRef != nil { Walk(v, node.ErrorTypeRef) @@ -545,6 +556,10 @@ func Walk(v Visitor, node BLangNode) { case *BLangErrorTypeNode: WalkTypeData(v, &node.detailType) + case *BLangConstrainedType: + WalkTypeData(v, &node.Type) + WalkTypeData(v, &node.Constraint) + // Section 9: Binding Patterns case *BLangCaptureBindingPattern: Walk(v, &node.Identifier) diff --git a/bir/bir_gen.go b/bir/bir_gen.go index 925d19a3f..ed9dd9f28 100644 --- a/bir/bir_gen.go +++ b/bir/bir_gen.go @@ -524,11 +524,42 @@ func handleExpression(ctx *stmtContext, curBB *BIRBasicBlock, expr ast.BLangExpr return listConstructorExpression(ctx, curBB, expr) case *ast.BLangTypeConversionExpr: return typeConversionExpression(ctx, curBB, expr) + case *ast.BLangMappingConstructorExpr: + return mappingConstructorExpression(ctx, curBB, expr) default: panic("unexpected expression type") } } +func mappingConstructorExpression(ctx *stmtContext, curBB *BIRBasicBlock, expr *ast.BLangMappingConstructorExpr) expressionEffect { + var values []MappingConstructorEntry + for _, field := range expr.Fields { + switch f := field.(type) { + case *ast.BLangMappingKeyValueField: + keyEffect := handleExpression(ctx, curBB, f.Key.Expr) + curBB = keyEffect.block + valueEffect := handleExpression(ctx, curBB, f.ValueExpr) + curBB = valueEffect.block + values = append(values, &MappingConstructorKeyValueEntry{ + keyOp: keyEffect.result, + valueOp: valueEffect.result, + }) + default: + ctx.birCx.CompilerContext.Unimplemented("non-key-value record field not implemented", expr.GetPosition()) + } + } + resultOperand := ctx.addTempVar(expr.GetDeterminedType()) + newMap := &NewMap{} + newMap.Type = expr.GetDeterminedType() + newMap.Values = values + newMap.LhsOp = resultOperand + curBB.Instructions = append(curBB.Instructions, newMap) + return expressionEffect{ + result: resultOperand, + block: curBB, + } +} + func typeConversionExpression(ctx *stmtContext, curBB *BIRBasicBlock, expr *ast.BLangTypeConversionExpr) expressionEffect { exprEffect := handleExpression(ctx, curBB, expr.Expression) curBB = exprEffect.block diff --git a/bir/non_terminator.go b/bir/non_terminator.go index 06e93763b..b4d510c65 100644 --- a/bir/non_terminator.go +++ b/bir/non_terminator.go @@ -30,6 +30,11 @@ type BIRAssignInstruction interface { GetLhsOperand() *BIROperand } +type MappingConstructorEntry interface { + IsKeyValuePair() bool + ValueOp() *BIROperand +} + type ( Move struct { BIRInstructionBase @@ -69,6 +74,14 @@ type ( Filler values.BalValue } + // JBallerina call this NewStruct but prints as NewMap + NewMap struct { + BIRInstructionBase + // Do we need the mapping atomic type as well? + Type semtypes.SemType + Values []MappingConstructorEntry + } + TypeCast struct { BIRInstructionBase RhsOp *BIROperand @@ -78,14 +91,23 @@ type ( } ) +type ( + MappingConstructorKeyValueEntry struct { + keyOp *BIROperand + valueOp *BIROperand + } +) + var ( - _ BIRAssignInstruction = &Move{} - _ BIRAssignInstruction = &BinaryOp{} - _ BIRAssignInstruction = &UnaryOp{} - _ BIRAssignInstruction = &ConstantLoad{} - _ BIRInstruction = &FieldAccess{} - _ BIRInstruction = &NewArray{} - _ BIRInstruction = &TypeCast{} + _ BIRAssignInstruction = &Move{} + _ BIRAssignInstruction = &BinaryOp{} + _ BIRAssignInstruction = &UnaryOp{} + _ BIRAssignInstruction = &ConstantLoad{} + _ BIRInstruction = &FieldAccess{} + _ BIRInstruction = &NewArray{} + _ BIRInstruction = &TypeCast{} + _ BIRInstruction = &NewMap{} + _ MappingConstructorEntry = &MappingConstructorKeyValueEntry{} ) func (m *Move) GetLhsOperand() *BIROperand { @@ -183,3 +205,19 @@ func (t *TypeCast) GetLhsOperand() *BIROperand { func (t *TypeCast) GetKind() InstructionKind { return INSTRUCTION_KIND_TYPE_CAST } + +func (n *NewMap) GetKind() InstructionKind { + return INSTRUCTION_KIND_NEW_STRUCTURE +} + +func (m *MappingConstructorKeyValueEntry) IsKeyValuePair() bool { + return true +} + +func (m *MappingConstructorKeyValueEntry) ValueOp() *BIROperand { + return m.valueOp +} + +func (m *MappingConstructorKeyValueEntry) KeyOp() *BIROperand { + return m.keyOp +} diff --git a/bir/pretty_print.go b/bir/pretty_print.go index 794cb2eca..e27328898 100644 --- a/bir/pretty_print.go +++ b/bir/pretty_print.go @@ -137,6 +137,8 @@ func (p *PrettyPrinter) PrintInstruction(instruction BIRInstruction) string { return p.PrintFieldAccess(instruction.(*FieldAccess)) case *NewArray: return p.PrintNewArray(instruction.(*NewArray)) + case *NewMap: + return p.PrintNewMap(instruction.(*NewMap)) case *TypeCast: return p.PrintTypeCast(instruction.(*TypeCast)) default: @@ -159,6 +161,24 @@ func (p *PrettyPrinter) PrintNewArray(array *NewArray) string { return fmt.Sprintf("%s = newArray %s[%s]{%s}", p.PrintOperand(*array.LhsOp), p.PrintSemType(array.Type), p.PrintOperand(*array.SizeOp), values.String()) } +func (p *PrettyPrinter) PrintNewMap(m *NewMap) string { + values := strings.Builder{} + for i, entry := range m.Values { + if i > 0 { + values.WriteString(", ") + } + if entry.IsKeyValuePair() { + kv := entry.(*MappingConstructorKeyValueEntry) + values.WriteString(p.PrintOperand(*kv.KeyOp())) + values.WriteString("=") + values.WriteString(p.PrintOperand(*kv.ValueOp())) + } else { + values.WriteString(p.PrintOperand(*entry.ValueOp())) + } + } + return fmt.Sprintf("%s = newMap %s{%s}", p.PrintOperand(*m.LhsOp), p.PrintSemType(m.Type), values.String()) +} + func (p *PrettyPrinter) PrintFieldAccess(access *FieldAccess) string { switch access.Kind { case INSTRUCTION_KIND_ARRAY_STORE: diff --git a/corpus/ast/subset4/04-map/02-v.txt b/corpus/ast/subset4/04-map/02-v.txt new file mode 100644 index 000000000..16f04416c --- /dev/null +++ b/corpus/ast/subset4/04-map/02-v.txt @@ -0,0 +1,15 @@ +(compilation-unit regular-source +(package-id $anon . 0.0.0) + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (expression-stmt + (invocation io println ( + (mapping-constructor-expr + (key-value + (simple-var-ref x) + (literal 1)) + (key-value + (simple-var-ref y) + (literal 2))))))))) \ No newline at end of file diff --git a/corpus/ast/subset4/04-map/04-v.txt b/corpus/ast/subset4/04-map/04-v.txt new file mode 100644 index 000000000..dff7af619 --- /dev/null +++ b/corpus/ast/subset4/04-map/04-v.txt @@ -0,0 +1,21 @@ +(compilation-unit regular-source +(package-id $anon . 0.0.0) + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr + (key-value + (simple-var-ref foo) + (literal true)) + (key-value + (simple-var-ref bar) + (literal )))))) + (expression-stmt + (invocation io println ( + (simple-var-ref m))))))) \ No newline at end of file diff --git a/corpus/ast/subset4/04-map/05-v.txt b/corpus/ast/subset4/04-map/05-v.txt new file mode 100644 index 000000000..2016fe7d6 --- /dev/null +++ b/corpus/ast/subset4/04-map/05-v.txt @@ -0,0 +1,30 @@ +(compilation-unit regular-source +(package-id $anon . 0.0.0) + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr + (key-value + (simple-var-ref list) + (list-constructor-expr + (literal 1) + (literal 2) + (literal 3))) + (key-value + (simple-var-ref mapping) + (mapping-constructor-expr + (key-value + (simple-var-ref x) + (literal 1)) + (key-value + (simple-var-ref y) + (literal 2)))))))) + (expression-stmt + (invocation io println ( + (simple-var-ref m))))))) \ No newline at end of file diff --git a/corpus/ast/subset4/04-map/06-v.txt b/corpus/ast/subset4/04-map/06-v.txt new file mode 100644 index 000000000..1ea4ae1fc --- /dev/null +++ b/corpus/ast/subset4/04-map/06-v.txt @@ -0,0 +1,19 @@ +(compilation-unit regular-source +(package-id $anon . 0.0.0) + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr)))) + (var-def + (variable x (type + (value-type any)) (expr + (simple-var-ref m)))) + (expression-stmt + (invocation io println ( + (simple-var-ref x))))))) \ No newline at end of file diff --git a/corpus/ast/subset4/04-map/07-v.txt b/corpus/ast/subset4/04-map/07-v.txt new file mode 100644 index 000000000..b07b30329 --- /dev/null +++ b/corpus/ast/subset4/04-map/07-v.txt @@ -0,0 +1,27 @@ +(compilation-unit regular-source +(package-id $anon . 0.0.0) + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (expression-stmt + (invocation io println ( + (invocation wrap ( + (literal 1)))))) + (expression-stmt + (invocation io println ( + (invocation wrap ( + (invocation wrap ( + (literal )))))))))) + (function wrap ( + (variable x (type + (value-type any)))) ( + (constrained-type + (builtin-ref-type map) + (value-type any))) + (block-function-body + (return + (mapping-constructor-expr + (key-value + (simple-var-ref value) + (simple-var-ref x))))))) \ No newline at end of file diff --git a/corpus/ast/subset4/04-map/08-v.txt b/corpus/ast/subset4/04-map/08-v.txt new file mode 100644 index 000000000..c491adf4c --- /dev/null +++ b/corpus/ast/subset4/04-map/08-v.txt @@ -0,0 +1,38 @@ +(compilation-unit regular-source +(package-id $anon . 0.0.0) + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr + (key-value + (simple-var-ref foo) + (literal 17)) + (key-value + (simple-var-ref bar) + (literal 42)))))) + (var-def + (variable v (type + (value-type any)) (expr + (index-based-access + (simple-var-ref m) + (literal foo))))) + (expression-stmt + (invocation io println ( + (simple-var-ref v)))) + (expression-stmt + (invocation io println ( + (index-based-access + (simple-var-ref m) + (literal bar))))) + (expression-stmt + (invocation io println ( + (list-constructor-expr + (index-based-access + (simple-var-ref m) + (literal baz))))))))) \ No newline at end of file diff --git a/corpus/ast/subset4/04-map/11-v.txt b/corpus/ast/subset4/04-map/11-v.txt new file mode 100644 index 000000000..09eb39d68 --- /dev/null +++ b/corpus/ast/subset4/04-map/11-v.txt @@ -0,0 +1,26 @@ +(compilation-unit regular-source +(package-id $anon . 0.0.0) + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable s (type + (value-type string)) (expr + (literal hello)))) + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr)))) + (assignment + (index-based-access + (simple-var-ref m) + (simple-var-ref s)) + (literal 42)) + (expression-stmt + (invocation io println ( + (index-based-access + (simple-var-ref m) + (simple-var-ref s)))))))) \ No newline at end of file diff --git a/corpus/ast/subset4/04-map/12-v.txt b/corpus/ast/subset4/04-map/12-v.txt new file mode 100644 index 000000000..600fe19d1 --- /dev/null +++ b/corpus/ast/subset4/04-map/12-v.txt @@ -0,0 +1,53 @@ +(compilation-unit regular-source +(package-id $anon . 0.0.0) + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr)))) + (expression-stmt + (invocation put ( + (simple-var-ref m) + (literal five) + (literal 5)))) + (expression-stmt + (invocation io println ( + (invocation get ( + (simple-var-ref m) + (literal five)))))))) + (function put ( + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any)))) + (variable k (type + (value-type string))) + (variable v (type + (value-type int)))) ( + (value-type null)) + (block-function-body + (assignment + (index-based-access + (simple-var-ref m) + (simple-var-ref k)) + (simple-var-ref v)))) + (function get ( + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any)))) + (variable k (type + (value-type string)))) ( + (value-type int)) + (block-function-body + (return + (type-conversion-expr + (index-based-access + (simple-var-ref m) + (simple-var-ref k)) + (value-type int)))))) \ No newline at end of file diff --git a/corpus/ast/subset4/04-map/simple-v.txt b/corpus/ast/subset4/04-map/simple-v.txt new file mode 100644 index 000000000..9d947ae90 --- /dev/null +++ b/corpus/ast/subset4/04-map/simple-v.txt @@ -0,0 +1,35 @@ +(compilation-unit regular-source +(package-id $anon . 0.0.0) + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable foo (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr + (key-value + (literal a) + (literal 1)) + (key-value + (literal b) + (literal b)))))) + (expression-stmt + (invocation io println ( + (simple-var-ref foo)))) + (var-def + (variable a (type + (value-type any)) (expr + (index-based-access + (simple-var-ref foo) + (literal a))))) + (expression-stmt + (invocation io println ( + (simple-var-ref a)))) + (expression-stmt + (invocation io println ( + (index-based-access + (simple-var-ref foo) + (literal b)))))))) \ No newline at end of file diff --git a/corpus/ast/subset4/04-map/union1-v.txt b/corpus/ast/subset4/04-map/union1-v.txt new file mode 100644 index 000000000..c8743e58f --- /dev/null +++ b/corpus/ast/subset4/04-map/union1-v.txt @@ -0,0 +1,35 @@ +(compilation-unit regular-source +(package-id $anon . 0.0.0) + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable foo (type + (union-type + (constrained-type + (builtin-ref-type map) + (value-type int)) + (constrained-type + (builtin-ref-type map) + (value-type string)))) (expr + (mapping-constructor-expr + (key-value + (literal a) + (literal 1)) + (key-value + (literal b) + (literal 2)))))) + (var-def + (variable a (type + (union-type + (value-type int) + (union-type + (value-type string) + (value-type null)))) (expr + (index-based-access + (simple-var-ref foo) + (literal a))))) + (expression-stmt + (invocation io println ( + (simple-var-ref a))))))) \ No newline at end of file diff --git a/corpus/ast/subset4/04-map/union3-v.txt b/corpus/ast/subset4/04-map/union3-v.txt new file mode 100644 index 000000000..968cb0b23 --- /dev/null +++ b/corpus/ast/subset4/04-map/union3-v.txt @@ -0,0 +1,37 @@ +(compilation-unit regular-source +(package-id $anon . 0.0.0) + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable foo (type + (union-type + (constrained-type + (builtin-ref-type map) + (union-type + (value-type int) + (value-type string))) + (constrained-type + (builtin-ref-type map) + (value-type string)))) (expr + (mapping-constructor-expr + (key-value + (literal a) + (literal 1)) + (key-value + (literal b) + (literal b)))))) + (var-def + (variable a (type + (union-type + (value-type int) + (union-type + (value-type string) + (value-type null)))) (expr + (index-based-access + (simple-var-ref foo) + (literal a))))) + (expression-stmt + (invocation io println ( + (simple-var-ref a))))))) \ No newline at end of file diff --git a/corpus/bal/subset4/04-map/01-e.bal b/corpus/bal/subset4/04-map/01-e.bal new file mode 100644 index 000000000..8916947c5 --- /dev/null +++ b/corpus/bal/subset4/04-map/01-e.bal @@ -0,0 +1,24 @@ +// Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// @productions map-type-descriptor mapping-constructor-expr any function-call-expr local-var-decl-stmt int-literal +public function main() { + map m = {}; + int i = 2; + ignore(m[i]); // @error +} + +function ignore(any x) { } diff --git a/corpus/bal/subset4/04-map/02-v.bal b/corpus/bal/subset4/04-map/02-v.bal new file mode 100644 index 000000000..48d3962a3 --- /dev/null +++ b/corpus/bal/subset4/04-map/02-v.bal @@ -0,0 +1,22 @@ +// Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// @productions mapping-constructor-expr int-literal +import ballerina/io; + +public function main() { + io:println({x: 1, y: 2}); // @output {"x":1,"y":2} +} diff --git a/corpus/bal/subset4/04-map/03-e.bal b/corpus/bal/subset4/04-map/03-e.bal new file mode 100644 index 000000000..bb15a9712 --- /dev/null +++ b/corpus/bal/subset4/04-map/03-e.bal @@ -0,0 +1,21 @@ +// Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// @productions map-type-descriptor list-constructor-expr any local-var-decl-stmt +public function main() { + map m = []; // @error + _ = m; +} diff --git a/corpus/bal/subset4/04-map/04-v.bal b/corpus/bal/subset4/04-map/04-v.bal new file mode 100644 index 000000000..f42504c0e --- /dev/null +++ b/corpus/bal/subset4/04-map/04-v.bal @@ -0,0 +1,23 @@ +// Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// @productions map-type-descriptor mapping-constructor-expr boolean-literal local-var-decl-stmt +import ballerina/io; + +public function main() { + map m = { foo: true, bar: ()}; + io:println(m); // @output {"foo":true,"bar":null} +} \ No newline at end of file diff --git a/corpus/bal/subset4/04-map/05-v.bal b/corpus/bal/subset4/04-map/05-v.bal new file mode 100644 index 000000000..0700359fb --- /dev/null +++ b/corpus/bal/subset4/04-map/05-v.bal @@ -0,0 +1,23 @@ +// Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// @productions map-type-descriptor mapping-constructor-expr list-constructor-expr local-var-decl-stmt int-literal +import ballerina/io; + +public function main() { + map m = { list: [1,2,3], mapping: {x: 1, y: 2}}; + io:println(m); // @output {"list":[1,2,3],"mapping":{"x":1,"y":2}} +} diff --git a/corpus/bal/subset4/04-map/06-v.bal b/corpus/bal/subset4/04-map/06-v.bal new file mode 100644 index 000000000..e9c788b1b --- /dev/null +++ b/corpus/bal/subset4/04-map/06-v.bal @@ -0,0 +1,24 @@ +// Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// @productions map-type-descriptor mapping-constructor-expr local-var-decl-stmt +import ballerina/io; + +public function main() { + map m = { }; + any x = m; + io:println(x); // @output {} +} diff --git a/corpus/bal/subset4/04-map/07-v.bal b/corpus/bal/subset4/04-map/07-v.bal new file mode 100644 index 000000000..a07884781 --- /dev/null +++ b/corpus/bal/subset4/04-map/07-v.bal @@ -0,0 +1,27 @@ +// Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// @productions mapping-constructor-expr return-stmt any function-call-expr int-literal +import ballerina/io; + +public function main() { + io:println(wrap(1)); // @output {"value":1} + io:println(wrap(wrap(()))); // @output {"value":{"value":null}} +} + +function wrap(any x) returns map { + return {value: x}; +} diff --git a/corpus/bal/subset4/04-map/08-v.bal b/corpus/bal/subset4/04-map/08-v.bal new file mode 100644 index 000000000..c94fc7f26 --- /dev/null +++ b/corpus/bal/subset4/04-map/08-v.bal @@ -0,0 +1,26 @@ +// Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// @productions map-type-descriptor mapping-constructor-expr string-literal list-constructor-expr local-var-decl-stmt int-literal +import ballerina/io; + +public function main() { + map m = { foo: 17, bar: 42 }; + any v = m["foo"]; + io:println(v); // @output 17 + io:println(m["bar"]); // @output 42 + io:println([m["baz"]]); // @output [null] +} diff --git a/corpus/bal/subset4/04-map/11-v.bal b/corpus/bal/subset4/04-map/11-v.bal new file mode 100644 index 000000000..754ad5fff --- /dev/null +++ b/corpus/bal/subset4/04-map/11-v.bal @@ -0,0 +1,25 @@ +// Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// @productions map-type-descriptor mapping-constructor-expr string-literal assign-stmt local-var-decl-stmt int-literal +import ballerina/io; + +public function main() { + string s = "hello"; + map m = {}; + m[s] = 42; + io:println(m[s]); // @output 42 +} diff --git a/corpus/bal/subset4/04-map/12-v.bal b/corpus/bal/subset4/04-map/12-v.bal new file mode 100644 index 000000000..ca75ba8e8 --- /dev/null +++ b/corpus/bal/subset4/04-map/12-v.bal @@ -0,0 +1,33 @@ +// Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// @productions map-type-descriptor mapping-constructor-expr string string-literal type-cast-expr return-stmt any function-call-expr assign-stmt local-var-decl-stmt int-literal +import ballerina/io; + +public function main() { + map m = {}; + put(m, "five", 5); + io:println(get(m, "five")); // @output 5 +} + +function put(map m, string k, int v) { + m[k] = v; +} + + +function get(map m, string k) returns int{ + return m[k]; +} diff --git a/corpus/bal/subset4/04-map/simple-e.bal b/corpus/bal/subset4/04-map/simple-e.bal new file mode 100644 index 000000000..8ba713564 --- /dev/null +++ b/corpus/bal/subset4/04-map/simple-e.bal @@ -0,0 +1,21 @@ +// Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import ballerina/io; + +public function main() { + map foo = {"a": 1}; + int a = foo["a"]; // @error +} diff --git a/corpus/bal/subset4/04-map/simple-v.bal b/corpus/bal/subset4/04-map/simple-v.bal new file mode 100644 index 000000000..695f45510 --- /dev/null +++ b/corpus/bal/subset4/04-map/simple-v.bal @@ -0,0 +1,24 @@ +// Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import ballerina/io; + +public function main() { + map foo = {"a": 1, "b": "b"}; + io:println(foo); // @output {"a":1,"b":"b"} + any a = foo["a"]; + io:println(a); // @output 1 + io:println(foo["b"]); // @output "b" +} diff --git a/corpus/bal/subset4/04-map/union1-v.bal b/corpus/bal/subset4/04-map/union1-v.bal new file mode 100644 index 000000000..7c1ba65fe --- /dev/null +++ b/corpus/bal/subset4/04-map/union1-v.bal @@ -0,0 +1,23 @@ +// Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import ballerina/io; + +public function main() { + map|map foo = {"a": 1, "b": 2}; + int|string? a = foo["a"]; + io:println(a); // @output 1 +} + diff --git a/corpus/bal/subset4/04-map/union2-e.bal b/corpus/bal/subset4/04-map/union2-e.bal new file mode 100644 index 000000000..e840ab92f --- /dev/null +++ b/corpus/bal/subset4/04-map/union2-e.bal @@ -0,0 +1,22 @@ +// Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import ballerina/io; + +public function main() { + map|map foo = {"a": 1, "b": "b"}; // @error + io:println(foo); +} + diff --git a/corpus/bal/subset4/04-map/union3-v.bal b/corpus/bal/subset4/04-map/union3-v.bal new file mode 100644 index 000000000..9f580583c --- /dev/null +++ b/corpus/bal/subset4/04-map/union3-v.bal @@ -0,0 +1,23 @@ +// Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import ballerina/io; + +public function main() { + map|map foo = {"a": 1, "b": "b"}; + int|string? a = foo["a"]; + io:println(a); // @output 1 +} + diff --git a/corpus/bir/subset4/04-map/02-v.txt b/corpus/bir/subset4/04-map/02-v.txt new file mode 100644 index 000000000..23c20dfe8 --- /dev/null +++ b/corpus/bir/subset4/04-map/02-v.txt @@ -0,0 +1,15 @@ +module $anon.. v 0.0.0; +import ballerina.io v 0.0.0; +main{ + bb0 { + %1 = ConstantLoad x + %2 = ConstantLoad 1 + %3 = ConstantLoad y + %4 = ConstantLoad 2 + %5 = newMap ((), (MAPPING)){%1=%2, %3=%4} + %6 = println(%5) -> bb1; + } + bb1 { + return; + } +} diff --git a/corpus/bir/subset4/04-map/04-v.txt b/corpus/bir/subset4/04-map/04-v.txt new file mode 100644 index 000000000..2ba451253 --- /dev/null +++ b/corpus/bir/subset4/04-map/04-v.txt @@ -0,0 +1,16 @@ +module $anon.. v 0.0.0; +import ballerina.io v 0.0.0; +main{ + bb0 { + %1 = ConstantLoad foo + %2 = ConstantLoad true + %3 = ConstantLoad bar + %4 = ConstantLoad + %5 = newMap ((), (MAPPING)){%1=%2, %3=%4} + m = %5; + %7 = println(m) -> bb1; + } + bb1 { + return; + } +} diff --git a/corpus/bir/subset4/04-map/05-v.txt b/corpus/bir/subset4/04-map/05-v.txt new file mode 100644 index 000000000..04ebee9db --- /dev/null +++ b/corpus/bir/subset4/04-map/05-v.txt @@ -0,0 +1,24 @@ +module $anon.. v 0.0.0; +import ballerina.io v 0.0.0; +main{ + bb0 { + %1 = ConstantLoad list + %2 = ConstantLoad 1 + %3 = ConstantLoad 2 + %4 = ConstantLoad 3 + %5 = ConstantLoad 3 + %6 = newArray ((LIST), ())[%5]{%2, %3, %4} + %7 = ConstantLoad mapping + %8 = ConstantLoad x + %9 = ConstantLoad 1 + %10 = ConstantLoad y + %11 = ConstantLoad 2 + %12 = newMap ((MAPPING), ()){%8=%9, %10=%11} + %13 = newMap ((), (MAPPING)){%1=%6, %7=%12} + m = %13; + %15 = println(m) -> bb1; + } + bb1 { + return; + } +} diff --git a/corpus/bir/subset4/04-map/06-v.txt b/corpus/bir/subset4/04-map/06-v.txt new file mode 100644 index 000000000..8abdc26b4 --- /dev/null +++ b/corpus/bir/subset4/04-map/06-v.txt @@ -0,0 +1,13 @@ +module $anon.. v 0.0.0; +import ballerina.io v 0.0.0; +main{ + bb0 { + %1 = newMap ((), (MAPPING)){} + m = %1; + x = m; + %4 = println(x) -> bb1; + } + bb1 { + return; + } +} diff --git a/corpus/bir/subset4/04-map/07-v.txt b/corpus/bir/subset4/04-map/07-v.txt new file mode 100644 index 000000000..2c9ec4421 --- /dev/null +++ b/corpus/bir/subset4/04-map/07-v.txt @@ -0,0 +1,32 @@ +module $anon.. v 0.0.0; +import ballerina.io v 0.0.0; +main{ + bb0 { + %1 = ConstantLoad 1 + %2 = wrap(%1) -> bb1; + } + bb1 { + %3 = println(%2) -> bb2; + } + bb2 { + %4 = ConstantLoad + %5 = wrap(%4) -> bb3; + } + bb3 { + %6 = wrap(%5) -> bb4; + } + bb4 { + %7 = println(%6) -> bb5; + } + bb5 { + return; + } +} +wrap{ + bb0 { + %2 = ConstantLoad value + %3 = newMap ((), (MAPPING)){%2=x} + %0 = %3; + return; + } +} diff --git a/corpus/bir/subset4/04-map/08-v.txt b/corpus/bir/subset4/04-map/08-v.txt new file mode 100644 index 000000000..9c7a83dda --- /dev/null +++ b/corpus/bir/subset4/04-map/08-v.txt @@ -0,0 +1,31 @@ +module $anon.. v 0.0.0; +import ballerina.io v 0.0.0; +main{ + bb0 { + %1 = ConstantLoad foo + %2 = ConstantLoad 17 + %3 = ConstantLoad bar + %4 = ConstantLoad 42 + %5 = newMap ((), (MAPPING)){%1=%2, %3=%4} + m = %5; + %8 = ConstantLoad foo + %7 = m[%8]; + v = %7; + %10 = println(v) -> bb1; + } + bb1 { + %12 = ConstantLoad bar + %11 = m[%12]; + %13 = println(%11) -> bb2; + } + bb2 { + %15 = ConstantLoad baz + %14 = m[%15]; + %16 = ConstantLoad 1 + %17 = newArray ((), (LIST))[%16]{%14} + %18 = println(%17) -> bb3; + } + bb3 { + return; + } +} diff --git a/corpus/bir/subset4/04-map/11-v.txt b/corpus/bir/subset4/04-map/11-v.txt new file mode 100644 index 000000000..4c12d3810 --- /dev/null +++ b/corpus/bir/subset4/04-map/11-v.txt @@ -0,0 +1,17 @@ +module $anon.. v 0.0.0; +import ballerina.io v 0.0.0; +main{ + bb0 { + %1 = ConstantLoad hello + s = %1; + %3 = newMap ((), (MAPPING)){} + m = %3; + %5 = ConstantLoad 42 + m[s] = %5; + %6 = m[s]; + %7 = println(%6) -> bb1; + } + bb1 { + return; + } +} diff --git a/corpus/bir/subset4/04-map/12-v.txt b/corpus/bir/subset4/04-map/12-v.txt new file mode 100644 index 000000000..27077a783 --- /dev/null +++ b/corpus/bir/subset4/04-map/12-v.txt @@ -0,0 +1,35 @@ +module $anon.. v 0.0.0; +import ballerina.io v 0.0.0; +main{ + bb0 { + %1 = newMap ((), (MAPPING)){} + m = %1; + %3 = ConstantLoad five + %4 = ConstantLoad 5 + %5 = put(m,%3,%4) -> bb1; + } + bb1 { + %6 = ConstantLoad five + %7 = get(m,%6) -> bb2; + } + bb2 { + %8 = println(%7) -> bb3; + } + bb3 { + return; + } +} +put{ + bb0 { + m[k] = v; + return; + } +} +get{ + bb0 { + %3 = m[k]; + %4 = <((INT), ())>(%3) + %0 = %4; + return; + } +} diff --git a/corpus/bir/subset4/04-map/simple-v.txt b/corpus/bir/subset4/04-map/simple-v.txt new file mode 100644 index 000000000..b481fd59c --- /dev/null +++ b/corpus/bir/subset4/04-map/simple-v.txt @@ -0,0 +1,27 @@ +module $anon.. v 0.0.0; +import ballerina.io v 0.0.0; +main{ + bb0 { + %1 = ConstantLoad a + %2 = ConstantLoad 1 + %3 = ConstantLoad b + %4 = ConstantLoad b + %5 = newMap ((), (MAPPING)){%1=%2, %3=%4} + foo = %5; + %7 = println(foo) -> bb1; + } + bb1 { + %9 = ConstantLoad a + %8 = foo[%9]; + a = %8; + %11 = println(a) -> bb2; + } + bb2 { + %13 = ConstantLoad b + %12 = foo[%13]; + %14 = println(%12) -> bb3; + } + bb3 { + return; + } +} diff --git a/corpus/bir/subset4/04-map/union1-v.txt b/corpus/bir/subset4/04-map/union1-v.txt new file mode 100644 index 000000000..25c5f238e --- /dev/null +++ b/corpus/bir/subset4/04-map/union1-v.txt @@ -0,0 +1,19 @@ +module $anon.. v 0.0.0; +import ballerina.io v 0.0.0; +main{ + bb0 { + %1 = ConstantLoad a + %2 = ConstantLoad 1 + %3 = ConstantLoad b + %4 = ConstantLoad 2 + %5 = newMap ((), (MAPPING)){%1=%2, %3=%4} + foo = %5; + %8 = ConstantLoad a + %7 = foo[%8]; + a = %7; + %10 = println(a) -> bb1; + } + bb1 { + return; + } +} diff --git a/corpus/bir/subset4/04-map/union3-v.txt b/corpus/bir/subset4/04-map/union3-v.txt new file mode 100644 index 000000000..4ae819a1b --- /dev/null +++ b/corpus/bir/subset4/04-map/union3-v.txt @@ -0,0 +1,19 @@ +module $anon.. v 0.0.0; +import ballerina.io v 0.0.0; +main{ + bb0 { + %1 = ConstantLoad a + %2 = ConstantLoad 1 + %3 = ConstantLoad b + %4 = ConstantLoad b + %5 = newMap ((), (MAPPING)){%1=%2, %3=%4} + foo = %5; + %8 = ConstantLoad a + %7 = foo[%8]; + a = %7; + %10 = println(a) -> bb1; + } + bb1 { + return; + } +} diff --git a/corpus/cfg/subset4/04-map/02-v.txt b/corpus/cfg/subset4/04-map/02-v.txt new file mode 100644 index 000000000..c6736ed6a --- /dev/null +++ b/corpus/cfg/subset4/04-map/02-v.txt @@ -0,0 +1,13 @@ +(main + (bb0 () () + (expression-stmt + (invocation io println ( + (mapping-constructor-expr + (key-value + (simple-var-ref x) + (literal 1)) + (key-value + (simple-var-ref y) + (literal 2)))))) + ) +) \ No newline at end of file diff --git a/corpus/cfg/subset4/04-map/04-v.txt b/corpus/cfg/subset4/04-map/04-v.txt new file mode 100644 index 000000000..13a0ce642 --- /dev/null +++ b/corpus/cfg/subset4/04-map/04-v.txt @@ -0,0 +1,19 @@ +(main + (bb0 () () + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr + (key-value + (simple-var-ref foo) + (literal true)) + (key-value + (simple-var-ref bar) + (literal )))))) + (expression-stmt + (invocation io println ( + (simple-var-ref m)))) + ) +) \ No newline at end of file diff --git a/corpus/cfg/subset4/04-map/05-v.txt b/corpus/cfg/subset4/04-map/05-v.txt new file mode 100644 index 000000000..45807b7a6 --- /dev/null +++ b/corpus/cfg/subset4/04-map/05-v.txt @@ -0,0 +1,28 @@ +(main + (bb0 () () + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr + (key-value + (simple-var-ref list) + (list-constructor-expr + (literal 1) + (literal 2) + (literal 3))) + (key-value + (simple-var-ref mapping) + (mapping-constructor-expr + (key-value + (simple-var-ref x) + (literal 1)) + (key-value + (simple-var-ref y) + (literal 2)))))))) + (expression-stmt + (invocation io println ( + (simple-var-ref m)))) + ) +) \ No newline at end of file diff --git a/corpus/cfg/subset4/04-map/06-v.txt b/corpus/cfg/subset4/04-map/06-v.txt new file mode 100644 index 000000000..ab149e363 --- /dev/null +++ b/corpus/cfg/subset4/04-map/06-v.txt @@ -0,0 +1,17 @@ +(main + (bb0 () () + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr)))) + (var-def + (variable x (type + (value-type any)) (expr + (simple-var-ref m)))) + (expression-stmt + (invocation io println ( + (simple-var-ref x)))) + ) +) \ No newline at end of file diff --git a/corpus/cfg/subset4/04-map/07-v.txt b/corpus/cfg/subset4/04-map/07-v.txt new file mode 100644 index 000000000..1f6cc7abc --- /dev/null +++ b/corpus/cfg/subset4/04-map/07-v.txt @@ -0,0 +1,22 @@ +(main + (bb0 () () + (expression-stmt + (invocation io println ( + (invocation wrap ( + (literal 1)))))) + (expression-stmt + (invocation io println ( + (invocation wrap ( + (invocation wrap ( + (literal )))))))) + ) +) +(wrap + (bb0 () () + (return + (mapping-constructor-expr + (key-value + (simple-var-ref value) + (simple-var-ref x)))) + ) +) \ No newline at end of file diff --git a/corpus/cfg/subset4/04-map/08-v.txt b/corpus/cfg/subset4/04-map/08-v.txt new file mode 100644 index 000000000..24c7bb96a --- /dev/null +++ b/corpus/cfg/subset4/04-map/08-v.txt @@ -0,0 +1,36 @@ +(main + (bb0 () () + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr + (key-value + (simple-var-ref foo) + (literal 17)) + (key-value + (simple-var-ref bar) + (literal 42)))))) + (var-def + (variable v (type + (value-type any)) (expr + (index-based-access + (simple-var-ref m) + (literal foo))))) + (expression-stmt + (invocation io println ( + (simple-var-ref v)))) + (expression-stmt + (invocation io println ( + (index-based-access + (simple-var-ref m) + (literal bar))))) + (expression-stmt + (invocation io println ( + (list-constructor-expr + (index-based-access + (simple-var-ref m) + (literal baz)))))) + ) +) \ No newline at end of file diff --git a/corpus/cfg/subset4/04-map/11-v.txt b/corpus/cfg/subset4/04-map/11-v.txt new file mode 100644 index 000000000..7af9236bc --- /dev/null +++ b/corpus/cfg/subset4/04-map/11-v.txt @@ -0,0 +1,24 @@ +(main + (bb0 () () + (var-def + (variable s (type + (value-type string)) (expr + (literal hello)))) + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr)))) + (assignment + (index-based-access + (simple-var-ref m) + (simple-var-ref s)) + (literal 42)) + (expression-stmt + (invocation io println ( + (index-based-access + (simple-var-ref m) + (simple-var-ref s))))) + ) +) \ No newline at end of file diff --git a/corpus/cfg/subset4/04-map/12-v.txt b/corpus/cfg/subset4/04-map/12-v.txt new file mode 100644 index 000000000..adafdb3f1 --- /dev/null +++ b/corpus/cfg/subset4/04-map/12-v.txt @@ -0,0 +1,39 @@ +(get + (bb0 () () + (return + (type-conversion-expr + (index-based-access + (simple-var-ref m) + (simple-var-ref k)) + (value-type int))) + ) +) +(main + (bb0 () () + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr)))) + (expression-stmt + (invocation put ( + (simple-var-ref m) + (literal five) + (literal 5)))) + (expression-stmt + (invocation io println ( + (invocation get ( + (simple-var-ref m) + (literal five)))))) + ) +) +(put + (bb0 () () + (assignment + (index-based-access + (simple-var-ref m) + (simple-var-ref k)) + (simple-var-ref v)) + ) +) \ No newline at end of file diff --git a/corpus/cfg/subset4/04-map/simple-v.txt b/corpus/cfg/subset4/04-map/simple-v.txt new file mode 100644 index 000000000..1048127ab --- /dev/null +++ b/corpus/cfg/subset4/04-map/simple-v.txt @@ -0,0 +1,33 @@ +(main + (bb0 () () + (var-def + (variable foo (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr + (key-value + (literal a) + (literal 1)) + (key-value + (literal b) + (literal b)))))) + (expression-stmt + (invocation io println ( + (simple-var-ref foo)))) + (var-def + (variable a (type + (value-type any)) (expr + (index-based-access + (simple-var-ref foo) + (literal a))))) + (expression-stmt + (invocation io println ( + (simple-var-ref a)))) + (expression-stmt + (invocation io println ( + (index-based-access + (simple-var-ref foo) + (literal b))))) + ) +) \ No newline at end of file diff --git a/corpus/cfg/subset4/04-map/union1-v.txt b/corpus/cfg/subset4/04-map/union1-v.txt new file mode 100644 index 000000000..2c29f2b46 --- /dev/null +++ b/corpus/cfg/subset4/04-map/union1-v.txt @@ -0,0 +1,33 @@ +(main + (bb0 () () + (var-def + (variable foo (type + (union-type + (constrained-type + (builtin-ref-type map) + (value-type int)) + (constrained-type + (builtin-ref-type map) + (value-type string)))) (expr + (mapping-constructor-expr + (key-value + (literal a) + (literal 1)) + (key-value + (literal b) + (literal 2)))))) + (var-def + (variable a (type + (union-type + (value-type int) + (union-type + (value-type string) + (value-type null)))) (expr + (index-based-access + (simple-var-ref foo) + (literal a))))) + (expression-stmt + (invocation io println ( + (simple-var-ref a)))) + ) +) \ No newline at end of file diff --git a/corpus/cfg/subset4/04-map/union3-v.txt b/corpus/cfg/subset4/04-map/union3-v.txt new file mode 100644 index 000000000..21b8a17e2 --- /dev/null +++ b/corpus/cfg/subset4/04-map/union3-v.txt @@ -0,0 +1,35 @@ +(main + (bb0 () () + (var-def + (variable foo (type + (union-type + (constrained-type + (builtin-ref-type map) + (union-type + (value-type int) + (value-type string))) + (constrained-type + (builtin-ref-type map) + (value-type string)))) (expr + (mapping-constructor-expr + (key-value + (literal a) + (literal 1)) + (key-value + (literal b) + (literal b)))))) + (var-def + (variable a (type + (union-type + (value-type int) + (union-type + (value-type string) + (value-type null)))) (expr + (index-based-access + (simple-var-ref foo) + (literal a))))) + (expression-stmt + (invocation io println ( + (simple-var-ref a)))) + ) +) \ No newline at end of file diff --git a/corpus/desugared/subset4/04-map/02-v.txt b/corpus/desugared/subset4/04-map/02-v.txt new file mode 100644 index 000000000..163ffce7a --- /dev/null +++ b/corpus/desugared/subset4/04-map/02-v.txt @@ -0,0 +1,14 @@ +(package + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (expression-stmt + (invocation io println ( + (mapping-constructor-expr + (key-value + (literal x) + (literal 1)) + (key-value + (literal y) + (literal 2))))))))) \ No newline at end of file diff --git a/corpus/desugared/subset4/04-map/04-v.txt b/corpus/desugared/subset4/04-map/04-v.txt new file mode 100644 index 000000000..0a74ffd3d --- /dev/null +++ b/corpus/desugared/subset4/04-map/04-v.txt @@ -0,0 +1,20 @@ +(package + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr + (key-value + (literal foo) + (literal true)) + (key-value + (literal bar) + (literal )))))) + (expression-stmt + (invocation io println ( + (simple-var-ref m))))))) \ No newline at end of file diff --git a/corpus/desugared/subset4/04-map/05-v.txt b/corpus/desugared/subset4/04-map/05-v.txt new file mode 100644 index 000000000..5c4386cd7 --- /dev/null +++ b/corpus/desugared/subset4/04-map/05-v.txt @@ -0,0 +1,29 @@ +(package + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr + (key-value + (literal list) + (list-constructor-expr + (literal 1) + (literal 2) + (literal 3))) + (key-value + (literal mapping) + (mapping-constructor-expr + (key-value + (literal x) + (literal 1)) + (key-value + (literal y) + (literal 2)))))))) + (expression-stmt + (invocation io println ( + (simple-var-ref m))))))) \ No newline at end of file diff --git a/corpus/desugared/subset4/04-map/06-v.txt b/corpus/desugared/subset4/04-map/06-v.txt new file mode 100644 index 000000000..2200d4a06 --- /dev/null +++ b/corpus/desugared/subset4/04-map/06-v.txt @@ -0,0 +1,18 @@ +(package + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr)))) + (var-def + (variable x (type + (value-type any)) (expr + (simple-var-ref m)))) + (expression-stmt + (invocation io println ( + (simple-var-ref x))))))) \ No newline at end of file diff --git a/corpus/desugared/subset4/04-map/07-v.txt b/corpus/desugared/subset4/04-map/07-v.txt new file mode 100644 index 000000000..ea01eb973 --- /dev/null +++ b/corpus/desugared/subset4/04-map/07-v.txt @@ -0,0 +1,26 @@ +(package + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (expression-stmt + (invocation io println ( + (invocation wrap ( + (literal 1)))))) + (expression-stmt + (invocation io println ( + (invocation wrap ( + (invocation wrap ( + (literal )))))))))) + (function wrap ( + (variable x (type + (value-type any)))) ( + (constrained-type + (builtin-ref-type map) + (value-type any))) + (block-function-body + (return + (mapping-constructor-expr + (key-value + (literal value) + (simple-var-ref x))))))) \ No newline at end of file diff --git a/corpus/desugared/subset4/04-map/08-v.txt b/corpus/desugared/subset4/04-map/08-v.txt new file mode 100644 index 000000000..7e1d4feb5 --- /dev/null +++ b/corpus/desugared/subset4/04-map/08-v.txt @@ -0,0 +1,37 @@ +(package + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr + (key-value + (literal foo) + (literal 17)) + (key-value + (literal bar) + (literal 42)))))) + (var-def + (variable v (type + (value-type any)) (expr + (index-based-access + (simple-var-ref m) + (literal foo))))) + (expression-stmt + (invocation io println ( + (simple-var-ref v)))) + (expression-stmt + (invocation io println ( + (index-based-access + (simple-var-ref m) + (literal bar))))) + (expression-stmt + (invocation io println ( + (list-constructor-expr + (index-based-access + (simple-var-ref m) + (literal baz))))))))) \ No newline at end of file diff --git a/corpus/desugared/subset4/04-map/11-v.txt b/corpus/desugared/subset4/04-map/11-v.txt new file mode 100644 index 000000000..2aa78bfc7 --- /dev/null +++ b/corpus/desugared/subset4/04-map/11-v.txt @@ -0,0 +1,25 @@ +(package + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable s (type + (value-type string)) (expr + (literal hello)))) + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr)))) + (assignment + (index-based-access + (simple-var-ref m) + (simple-var-ref s)) + (literal 42)) + (expression-stmt + (invocation io println ( + (index-based-access + (simple-var-ref m) + (simple-var-ref s)))))))) \ No newline at end of file diff --git a/corpus/desugared/subset4/04-map/12-v.txt b/corpus/desugared/subset4/04-map/12-v.txt new file mode 100644 index 000000000..ca17d0119 --- /dev/null +++ b/corpus/desugared/subset4/04-map/12-v.txt @@ -0,0 +1,52 @@ +(package + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr)))) + (expression-stmt + (invocation put ( + (simple-var-ref m) + (literal five) + (literal 5)))) + (expression-stmt + (invocation io println ( + (invocation get ( + (simple-var-ref m) + (literal five)))))))) + (function put ( + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any)))) + (variable k (type + (value-type string))) + (variable v (type + (value-type int)))) ( + (value-type null)) + (block-function-body + (assignment + (index-based-access + (simple-var-ref m) + (simple-var-ref k)) + (simple-var-ref v)))) + (function get ( + (variable m (type + (constrained-type + (builtin-ref-type map) + (value-type any)))) + (variable k (type + (value-type string)))) ( + (value-type int)) + (block-function-body + (return + (type-conversion-expr + (index-based-access + (simple-var-ref m) + (simple-var-ref k)) + (value-type int)))))) \ No newline at end of file diff --git a/corpus/desugared/subset4/04-map/simple-v.txt b/corpus/desugared/subset4/04-map/simple-v.txt new file mode 100644 index 000000000..1b1908f35 --- /dev/null +++ b/corpus/desugared/subset4/04-map/simple-v.txt @@ -0,0 +1,34 @@ +(package + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable foo (type + (constrained-type + (builtin-ref-type map) + (value-type any))) (expr + (mapping-constructor-expr + (key-value + (literal a) + (literal 1)) + (key-value + (literal b) + (literal b)))))) + (expression-stmt + (invocation io println ( + (simple-var-ref foo)))) + (var-def + (variable a (type + (value-type any)) (expr + (index-based-access + (simple-var-ref foo) + (literal a))))) + (expression-stmt + (invocation io println ( + (simple-var-ref a)))) + (expression-stmt + (invocation io println ( + (index-based-access + (simple-var-ref foo) + (literal b)))))))) \ No newline at end of file diff --git a/corpus/desugared/subset4/04-map/union1-v.txt b/corpus/desugared/subset4/04-map/union1-v.txt new file mode 100644 index 000000000..60d093ea7 --- /dev/null +++ b/corpus/desugared/subset4/04-map/union1-v.txt @@ -0,0 +1,34 @@ +(package + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable foo (type + (union-type + (constrained-type + (builtin-ref-type map) + (value-type int)) + (constrained-type + (builtin-ref-type map) + (value-type string)))) (expr + (mapping-constructor-expr + (key-value + (literal a) + (literal 1)) + (key-value + (literal b) + (literal 2)))))) + (var-def + (variable a (type + (union-type + (value-type int) + (union-type + (value-type string) + (value-type null)))) (expr + (index-based-access + (simple-var-ref foo) + (literal a))))) + (expression-stmt + (invocation io println ( + (simple-var-ref a))))))) \ No newline at end of file diff --git a/corpus/desugared/subset4/04-map/union3-v.txt b/corpus/desugared/subset4/04-map/union3-v.txt new file mode 100644 index 000000000..ccac09e07 --- /dev/null +++ b/corpus/desugared/subset4/04-map/union3-v.txt @@ -0,0 +1,36 @@ +(package + (import-package ballerina io (as io)) + (function main () ( + (value-type null)) + (block-function-body + (var-def + (variable foo (type + (union-type + (constrained-type + (builtin-ref-type map) + (union-type + (value-type int) + (value-type string))) + (constrained-type + (builtin-ref-type map) + (value-type string)))) (expr + (mapping-constructor-expr + (key-value + (literal a) + (literal 1)) + (key-value + (literal b) + (literal b)))))) + (var-def + (variable a (type + (union-type + (value-type int) + (union-type + (value-type string) + (value-type null)))) (expr + (index-based-access + (simple-var-ref foo) + (literal a))))) + (expression-stmt + (invocation io println ( + (simple-var-ref a))))))) \ No newline at end of file diff --git a/corpus/integration_test.go b/corpus/integration_test.go index d25dd3f30..57371a960 100644 --- a/corpus/integration_test.go +++ b/corpus/integration_test.go @@ -59,7 +59,24 @@ var ( errorRegex = regexp.MustCompile(`//\s*@error`) // Skip tests that cause unrecoverable Go runtime errors - skipTestsMap = makeSkipTestsMap([]string{}) + skipTestsMap = makeSkipTestsMap([]string{ + "subset4/04-map/01-e.bal", + "subset4/04-map/02-v.bal", + "subset4/04-map/03-e.bal", + "subset4/04-map/04-v.bal", + "subset4/04-map/05-v.bal", + "subset4/04-map/06-v.bal", + "subset4/04-map/07-v.bal", + "subset4/04-map/08-v.bal", + "subset4/04-map/09-v.bal", + "subset4/04-map/11-v.bal", + "subset4/04-map/12-v.bal", + "subset4/04-map/simple-e.bal", + "subset4/04-map/simple-v.bal", + "subset4/04-map/union1-v.bal", + "subset4/04-map/union2-e.bal", + "subset4/04-map/union3-v.bal", + }) printlnOutputs = make(map[string]string) printlnMu sync.Mutex diff --git a/desugar/expression.go b/desugar/expression.go index e2a15741a..49b581b4c 100644 --- a/desugar/expression.go +++ b/desugar/expression.go @@ -20,6 +20,7 @@ package desugar import ( "ballerina-lang-go/ast" "ballerina-lang-go/model" + "ballerina-lang-go/semtypes" "fmt" ) @@ -39,6 +40,8 @@ func walkExpression(cx *FunctionContext, node model.ExpressionNode) desugaredNod return walkInvocation(cx, expr) case *ast.BLangListConstructorExpr: return walkListConstructorExpr(cx, expr) + case *ast.BLangMappingConstructorExpr: + return walkMappingConstructorExpr(cx, expr) case *ast.BLangErrorConstructorExpr: return walkErrorConstructorExpr(cx, expr) case *ast.BLangCheckedExpr: @@ -338,3 +341,33 @@ func walkArrowFunction(cx *FunctionContext, expr *ast.BLangArrowFunction) desuga replacementNode: expr, } } + +func walkMappingConstructorExpr(cx *FunctionContext, expr *ast.BLangMappingConstructorExpr) desugaredNode[model.ExpressionNode] { + var initStmts []model.StatementNode + + for _, field := range expr.Fields { + kv := field.(*ast.BLangMappingKeyValueField) + + if !kv.Key.ComputedKey { + if varRef, ok := kv.Key.Expr.(*ast.BLangSimpleVarRef); ok { + name := varRef.VariableName.Value + lit := &ast.BLangLiteral{ + Value: name, + OriginalValue: name, + } + s := semtypes.STRING + lit.SetDeterminedType(&s) + kv.Key.Expr = lit + } + } + + result := walkExpression(cx, kv.ValueExpr) + initStmts = append(initStmts, result.initStmts...) + kv.ValueExpr = result.replacementNode.(ast.BLangExpression) + } + + return desugaredNode[model.ExpressionNode]{ + initStmts: initStmts, + replacementNode: expr, + } +} diff --git a/model/tree.go b/model/tree.go index 311e97b15..a82501e31 100644 --- a/model/tree.go +++ b/model/tree.go @@ -740,6 +740,12 @@ type ErrorTypeNode interface { GetDetailType() TypeData } +type ConstrainedTypeNode interface { + TypeDescriptor + GetType() TypeData + GetConstraint() TypeData +} + type UserDefinedTypeNode interface { ReferenceTypeNode GetPackageAlias() IdentifierNode @@ -809,16 +815,27 @@ type ElvisExpressionNode interface { GetRightExpression() ExpressionNode } -type RecordField interface { +type MappingField interface { Node IsKeyValueField() bool } -type RecordVarNameFieldNode interface { - RecordField +type MappingVarNameFieldNode interface { + MappingField SimpleVariableReferenceNode } +type MappingConstructor interface { + ExpressionNode + GetFields() []MappingField +} + +type MappingKeyValueFieldNode interface { + MappingField + GetKey() ExpressionNode + GetValue() ExpressionNode +} + type MarkdownDocumentationTextAttributeNode interface { ExpressionNode GetText() string diff --git a/parser/tree/node_gen.go b/parser/tree/node_gen.go index 027ee7060..bc3a49afc 100644 --- a/parser/tree/node_gen.go +++ b/parser/tree/node_gen.go @@ -1211,6 +1211,10 @@ func (n MappingConstructorExpressionNode) Fields() NodeList[MappingFieldNode] { return nodeListFrom[MappingFieldNode](into[NonTerminalNode](n.ChildInBucket(1))) } +func (n MappingConstructorExpressionNode) FieldNodes() NodeList[Node] { + return nodeListFrom[Node](into[NonTerminalNode](n.ChildInBucket(1))) +} + func (n MappingConstructorExpressionNode) CloseBrace() Token { val, ok := n.ChildInBucket(2).(Token) if !ok { diff --git a/semantics/semantic_analyzer.go b/semantics/semantic_analyzer.go index 0b1261acb..d43b1c15d 100644 --- a/semantics/semantic_analyzer.go +++ b/semantics/semantic_analyzer.go @@ -24,6 +24,7 @@ import ( "ballerina-lang-go/tools/diagnostics" "fmt" "reflect" + "sort" ) type analyzer interface { @@ -502,6 +503,9 @@ func analyzeExpression[A analyzer](a A, expr ast.BLangExpression, expectedType s case *ast.BLangListConstructorExpr: analyzeListConstructorExpr(a, expr, expectedType) + case *ast.BLangMappingConstructorExpr: + analyzeMappingConstructorExpr(a, expr, expectedType) + case *ast.BLangErrorConstructorExpr: analyzeErrorConstructorExpr(a, expr, expectedType) @@ -613,6 +617,7 @@ func selectListInherentType[A analyzer](a A, expr *ast.BLangListConstructorExpr, // Filter alternatives by length compatibility var validAlts []semtypes.ListAlternative + // FIXME: is this needed? for _, expr := range expr.Exprs { analyzeExpression(a, expr, nil) } @@ -659,6 +664,97 @@ func selectListInherentType[A analyzer](a A, expr *ast.BLangListConstructorExpr, return selectedSemType, *lat } +func analyzeMappingConstructorExpr[A analyzer](a A, expr *ast.BLangMappingConstructorExpr, expectedType semtypes.SemType) { + if expectedType != nil { + resultType, mappingAtomicType := selectMappingInherentType(a, expr, expectedType) + for _, f := range expr.Fields { + kv := f.(*ast.BLangMappingKeyValueField) + var keyName string + switch keyExpr := kv.Key.Expr.(type) { + case *ast.BLangLiteral: + keyName = keyExpr.GetOriginalValue() + case ast.BNodeWithSymbol: + keyName = a.ctx().SymbolName(keyExpr.Symbol()) + } + requiredType := mappingAtomicType.FieldInnerVal(keyName) + analyzeExpression(a, kv.ValueExpr, requiredType) + } + expr.AtomicType = mappingAtomicType + setExpectedType(expr, resultType) + } else { + for _, f := range expr.Fields { + kv := f.(*ast.BLangMappingKeyValueField) + analyzeExpression(a, kv.ValueExpr, nil) + } + } + validateResolvedType(a, expr, expectedType) +} + +func selectMappingInherentType[A analyzer](a A, expr *ast.BLangMappingConstructorExpr, expectedType semtypes.SemType) (semtypes.SemType, semtypes.MappingAtomicType) { + expectedMappingType := semtypes.Intersect(expectedType, &semtypes.MAPPING) + tc := a.tyCtx() + if semtypes.IsEmpty(tc, expectedMappingType) { + a.semanticErr("mapping type not found in expected type") + return nil, semtypes.MappingAtomicType{} + } + mat := semtypes.ToMappingAtomicType(tc, expectedMappingType) + if mat != nil { + return expectedMappingType, *mat + } + alts := semtypes.MappingAlternatives(tc, expectedType) + var validAlts []semtypes.MappingAlternative + + fieldNames := make([]string, len(expr.Fields)) + for i, f := range expr.Fields { + kv := f.(*ast.BLangMappingKeyValueField) + analyzeExpression(a, kv.ValueExpr, nil) + fieldNames[i] = kv.Key.Expr.(*ast.BLangLiteral).Value.(string) + } + sort.Strings(fieldNames) + + for _, alt := range alts { + if semtypes.MappingAlternativeAllowsFields(alt, fieldNames) { + if alt.Pos != nil { + isValid := true + mat := alt.Pos + for _, f := range expr.Fields { + kv := f.(*ast.BLangMappingKeyValueField) + keyName := kv.Key.Expr.(*ast.BLangLiteral).Value.(string) + exprTy := kv.ValueExpr.GetDeterminedType() + ty := mat.FieldInnerVal(keyName) + if !semtypes.IsSubtype(tc, exprTy, ty) { + isValid = false + break + } + } + if isValid { + validAlts = append(validAlts, alt) + } + } else { + validAlts = append(validAlts, alt) + } + } + } + if len(validAlts) == 0 { + a.semanticErr("no applicable inherent type for mapping constructor") + return nil, semtypes.MappingAtomicType{} + } + if len(validAlts) > 1 { + a.semanticErr("ambiguous inherent type for mapping constructor") + return nil, semtypes.MappingAtomicType{} + } + + // Extract atomic type from selected alternative + selectedSemType := validAlts[0].SemType + mat = semtypes.ToMappingAtomicType(tc, selectedSemType) + if mat == nil { + a.semanticErr("applicable type for mapping constructor is not atomic") + return nil, semtypes.MappingAtomicType{} + } + + return selectedSemType, *mat +} + func analyzeErrorConstructorExpr[A analyzer](a A, expr *ast.BLangErrorConstructorExpr, expectedType semtypes.SemType) { argCount := len(expr.PositionalArgs) if argCount < 1 || argCount > 2 { diff --git a/semantics/symbol_resolver.go b/semantics/symbol_resolver.go index 6a60a53e7..27c714d32 100644 --- a/semantics/symbol_resolver.go +++ b/semantics/symbol_resolver.go @@ -290,6 +290,8 @@ func (bs *blockSymbolResolver) Visit(node ast.BLangNode) ast.Visitor { func visitInnerSymbolResolver[T symbolResolver](resolver T, node ast.BLangNode) ast.Visitor { switch n := node.(type) { + case *ast.BLangMappingConstructorExpr: + return resolveMappingConstructor(resolver, n) case model.InvocationNode: if n.GetExpression() != nil { createDeferredMethodSymbol(resolver, n) @@ -306,6 +308,22 @@ func visitInnerSymbolResolver[T symbolResolver](resolver T, node ast.BLangNode) return resolver } +func resolveMappingConstructor[T symbolResolver](resolver T, n *ast.BLangMappingConstructorExpr) ast.Visitor { + blockResolver := newBlockSymbolResolverWithBlockScope(resolver, n) + for _, field := range n.Fields { + if kv, ok := field.(*ast.BLangMappingKeyValueField); ok { + if !kv.Key.ComputedKey { + if varRef, ok := kv.Key.Expr.(*ast.BLangSimpleVarRef); ok { + name := varRef.VariableName.Value + symbol := model.NewValueSymbol(name, false, false, false) + addSymbolAndSetOnNode(blockResolver, name, &symbol, varRef) + } + } + } + } + return blockResolver +} + // since we don't have type information we can't determine if this is an actual method call or need to be converted // to a function call. func createDeferredMethodSymbol[T symbolResolver](resolver T, n model.InvocationNode) { diff --git a/semantics/type_resolver.go b/semantics/type_resolver.go index 9bdfd7d2d..56cbb01c7 100644 --- a/semantics/type_resolver.go +++ b/semantics/type_resolver.go @@ -437,6 +437,8 @@ func (t *TypeResolver) resolveExpression(expr ast.BLangExpression) semtypes.SemT return t.resolveIndexBasedAccess(e) case *ast.BLangListConstructorExpr: return t.resolveListConstructorExpr(e) + case *ast.BLangMappingConstructorExpr: + return t.resolveMappingConstructorExpr(e) case *ast.BLangErrorConstructorExpr: return t.resolveErrorConstructorExpr(e) case *ast.BLangGroupExpr: @@ -454,6 +456,36 @@ func (t *TypeResolver) resolveExpression(expr ast.BLangExpression) semtypes.SemT } } +func (t *TypeResolver) resolveMappingConstructorExpr(e *ast.BLangMappingConstructorExpr) semtypes.SemType { + fields := make([]semtypes.Field, len(e.Fields)) + for i, f := range e.Fields { + kv := f.(*ast.BLangMappingKeyValueField) + valueTy := t.resolveExpression(kv.ValueExpr) + var broadTy semtypes.SemType + if semtypes.SingleShape(valueTy).IsEmpty() { + broadTy = valueTy + } else { + basicTy := semtypes.WidenToBasicTypes(valueTy) + broadTy = &basicTy + } + var keyName string + switch keyExpr := kv.Key.Expr.(type) { + case *ast.BLangLiteral: + keyName = keyExpr.GetOriginalValue() + case ast.BNodeWithSymbol: + t.ctx.SetSymbolType(keyExpr.Symbol(), valueTy) + keyName = t.ctx.SymbolName(keyExpr.Symbol()) + } + fields[i] = semtypes.FieldFrom(keyName, broadTy, false, false) + } + md := semtypes.NewMappingDefinition() + mapTy := md.DefineMappingTypeWrapped(t.ctx.GetTypeEnv(), fields, &semtypes.NEVER) + setExpectedType(e, mapTy) + mat := semtypes.ToMappingAtomicType(t.tyCtx, mapTy) + e.AtomicType = *mat + return mapTy +} + func (t *TypeResolver) resolveTypeConversionExpr(e *ast.BLangTypeConversionExpr) semtypes.SemType { expectedType := t.resolveBType(e.TypeDescriptor.(ast.BType), 0) _ = t.resolveExpression(e.Expression) @@ -776,6 +808,7 @@ func (t *TypeResolver) NilLiftingExprResultTy(lhsTy, rhsTy semtypes.SemType, exp t.ctx.InternalError(fmt.Sprintf("unsupported binary operator: %s", string(expr.GetOperatorKind())), expr.GetPosition()) return nil, false } + func createIteratorType(env semtypes.Env, t, c semtypes.SemType) semtypes.SemType { od := semtypes.NewObjectDefinition() @@ -824,8 +857,15 @@ func (t *TypeResolver) resolveIndexBasedAccess(expr *ast.BLangIndexBasedAccess) var resultTy semtypes.SemType if semtypes.IsSubtypeSimple(containerExprTy, semtypes.LIST) { - // List indexing resultTy = semtypes.ListMemberTypeInnerVal(t.tyCtx, containerExprTy, keyExprTy) + } else if semtypes.IsSubtypeSimple(containerExprTy, semtypes.MAPPING) { + memberTy := semtypes.MappingMemberTypeInner(t.tyCtx, containerExprTy, keyExprTy) + maybeMissing := semtypes.ContainsUndef(memberTy) + // TODO: need to handle filling get but when do we have a filling get? + if maybeMissing { + memberTy = semtypes.Union(semtypes.Diff(memberTy, &semtypes.UNDEF), &semtypes.NIL) + } + resultTy = memberTy } else if semtypes.IsSubtypeSimple(containerExprTy, semtypes.STRING) { // String indexing returns a string resultTy = &semtypes.STRING @@ -1045,6 +1085,30 @@ func (tr *TypeResolver) resolveBTypeInner(btype ast.BType, depth int) semtypes.S result = semtypes.Union(result, ty) } return result + case *ast.BLangConstrainedType: + defn := ty.Definition + if defn == nil { + switch ty.GetTypeKind() { + case model.TypeKind_MAP: + d := semtypes.NewMappingDefinition() + ty.Definition = &d + rest := tr.resolveTypeDataPair(&ty.Constraint, depth+1) + return d.DefineMappingTypeWrapped(tr.ctx.GetTypeEnv(), nil, rest) + default: + tr.ctx.Unimplemented("unsupported base type kind", nil) + return nil + } + } else { + return defn.GetSemType(tr.ctx.GetTypeEnv()) + } + case *ast.BLangBuiltInRefTypeNode: + switch ty.TypeKind { + case model.TypeKind_MAP: + return &semtypes.MAPPING + default: + tr.ctx.InternalError("Unexpected builtin type kind", ty.GetPosition()) + } + return nil default: // TODO: here we need to implement type resolution logic for each type tr.ctx.Unimplemented("unsupported type", nil) diff --git a/semtypes/core.go b/semtypes/core.go index acadfc506..d3bfba00e 100644 --- a/semtypes/core.go +++ b/semtypes/core.go @@ -542,7 +542,7 @@ func ListAtomicTypeAllMemberTypesInnerVal(atomicType *ListAtomicType) ListMember return ListMemberTypesFrom(ranges, types) } -func mappingAtomicType(cx Context, t SemType) *MappingAtomicType { +func ToMappingAtomicType(cx Context, t SemType) *MappingAtomicType { mappingAtomicInner := MAPPING_ATOMIC_INNER if b, ok := t.(*BasicTypeBitSet); ok { if b.bitset == MAPPING.bitset { @@ -1038,3 +1038,15 @@ func comparableNillableList(cx Context, t1, t2 SemType) bool { memo.comparable = true return true } + +func ContainsUndef(t SemType) bool { + switch t := t.(type) { + case *BasicTypeBitSet: + bitSet := t.bitset + return (bitSet & (1 << BT_UNDEF.Code)) != 0 + case ComplexSemType: + return *getComplexSubtypeData(t, BT_UNDEF).(*bool) + default: + panic("unexpected semtype") + } +} diff --git a/semtypes/field_pair.go b/semtypes/field_pair.go index 8b60ba6c5..f754fd56d 100644 --- a/semtypes/field_pair.go +++ b/semtypes/field_pair.go @@ -155,14 +155,15 @@ func (i *mappingPairIterator) toIterator() iter.Seq[FieldPair] { } } -func NewFieldPairs(m1 MappingAtomicType, m2 MappingAtomicType) iter.Seq[FieldPair] { +func NewFieldPairs(m1 *MappingAtomicType, m2 *MappingAtomicType) iter.Seq[FieldPair] { i := &mappingPairIterator{ - names1: m1.Names, - names2: m2.Names, - types1: m1.Types, - types2: m2.Types, - len1: len(m1.Names), - len2: len(m2.Names), + names1: m1.Names, + names2: m2.Names, + types1: m1.Types, + types2: m2.Types, + len1: len(m1.Names), + len2: len(m2.Names), + shouldCalculate: true, } return i.toIterator() } diff --git a/semtypes/mapping_alternative.go b/semtypes/mapping_alternative.go index 4ee91704f..93a4de250 100644 --- a/semtypes/mapping_alternative.go +++ b/semtypes/mapping_alternative.go @@ -16,51 +16,87 @@ package semtypes +import "slices" + type MappingAlternative struct { - semType SemType - pos []MappingAtomicType + SemType SemType + Pos *MappingAtomicType neg []MappingAtomicType } -func newMappingAlternativeFromSemType(semType SemType, pos []MappingAtomicType, neg []MappingAtomicType) MappingAlternative { - this := MappingAlternative{} - this.semType = semType - this.pos = pos - this.neg = neg - return this -} - -func (this *MappingAlternative) MappingAlternatives(cx Context, t SemType) []MappingAlternative { - // migrated from MappingAlternative.java:39:5 +func MappingAlternatives(cx Context, t SemType) []MappingAlternative { if b, ok := t.(*BasicTypeBitSet); ok { if (b.bitset & MAPPING.bitset) == 0 { return nil - } else { - return []MappingAlternative{this.From(cx, &MAPPING, []Atom{}, []Atom{})} } - } else { - paths := []BddPath{} - BddPaths(getComplexSubtypeData(t.(ComplexSemType), BT_MAPPING).(Bdd), &paths, BddPathFrom()) - alts := []MappingAlternative{} - for _, bddPath := range paths { - semType := CreateBasicSemType(BT_MAPPING, bddPath.bdd) - if !IsNever(semType) { - alts = append(alts, this.From(cx, semType, bddPath.pos, bddPath.neg)) + return []MappingAlternative{{SemType: &MAPPING, Pos: nil, neg: nil}} + } + + paths := []BddPath{} + BddPaths(getComplexSubtypeData(t.(ComplexSemType), BT_MAPPING).(Bdd), &paths, BddPathFrom()) + alts := []MappingAlternative{} + for _, bddPath := range paths { + posAtoms := make([]*MappingAtomicType, len(bddPath.pos)) + for i := 0; i < len(bddPath.pos); i++ { + posAtoms[i] = cx.mappingAtomType(bddPath.pos[i]) + } + intersectionSemType, intersectionAtomType, ok := intersectMappingAtoms(cx.Env(), posAtoms) + if ok { + negAtoms := make([]MappingAtomicType, len(bddPath.neg)) + for i := 0; i < len(bddPath.neg); i++ { + negAtoms[i] = *cx.mappingAtomType(bddPath.neg[i]) } + alts = append(alts, MappingAlternative{SemType: intersectionSemType, Pos: intersectionAtomType, neg: negAtoms}) } - return alts } + return alts } -func (this *MappingAlternative) From(cx Context, semType SemType, pos []Atom, neg []Atom) MappingAlternative { - // migrated from MappingAlternative.java:63:5 - p := make([]MappingAtomicType, len(pos)) - n := make([]MappingAtomicType, len(neg)) - for i := 0; i < len(pos); i++ { - p[i] = *cx.mappingAtomType(pos[i]) +func intersectMappingAtoms(env Env, atoms []*MappingAtomicType) (SemType, *MappingAtomicType, bool) { + if len(atoms) == 0 { + return nil, nil, false + } + atom := atoms[0] + for i := 1; i < len(atoms); i++ { + result := intersectMapping(env, atom, atoms[i]) + if result == nil { + return nil, nil, false + } + atom = result + } + typeAtom := env.mappingAtom(atom) + ty := CreateBasicSemType(BT_MAPPING, BddAtom(&typeAtom)) + return ty, atom, true +} + +func MappingAlternativeAllowsFields(alt MappingAlternative, fieldNames []string) bool { + pos := alt.Pos + if pos != nil { + if CellInnerVal(pos.Rest) == &UNDEF { + if !slices.Equal(pos.Names, fieldNames) { + return false + } + } + i := 0 + len := len(fieldNames) + for _, name := range pos.Names { + for { + if i >= len { + return false + } + if fieldNames[i] == name { + i += 1 + break + } + if fieldNames[i] > name { + return false + } + i += 1 + } + } } - for i := 0; i < len(neg); i++ { - n[i] = *cx.mappingAtomType(neg[i]) + if len(alt.neg) != 0 { + panic("unexpected negative atom in mapping alternative") } - return newMappingAlternativeFromSemType(semType, p, n) + return true } diff --git a/semtypes/mapping_atomic_type.go b/semtypes/mapping_atomic_type.go index cf035355e..03b9f0028 100644 --- a/semtypes/mapping_atomic_type.go +++ b/semtypes/mapping_atomic_type.go @@ -49,3 +49,12 @@ func (this *MappingAtomicType) AtomKind() Kind { // migrated from MappingAtomicType.java:74:5 return Kind_MAPPING_ATOM } + +func (this *MappingAtomicType) FieldInnerVal(name string) SemType { + for i, n := range this.Names { + if n == name { + return CellInnerVal(this.Types[i]) + } + } + return CellInnerVal(this.Rest) +} diff --git a/semtypes/mapping_ops.go b/semtypes/mapping_ops.go index 18f3cf908..c92b90a96 100644 --- a/semtypes/mapping_ops.go +++ b/semtypes/mapping_ops.go @@ -32,21 +32,21 @@ func mappingSubtypeIsEmpty(cx Context, t SubtypeData) bool { func mappingFormulaIsEmpty(cx Context, posList *Conjunction, negList *Conjunction) bool { // migrated from MappingOps.java:57:5 - var combined MappingAtomicType + var combined *MappingAtomicType if posList == nil { - combined = MAPPING_ATOMIC_INNER + combined = &MAPPING_ATOMIC_INNER } else { - combined = *cx.mappingAtomType(posList.Atom) + combined = cx.mappingAtomType(posList.Atom) p := posList.Next for true { if p == nil { break } else { - m := intersectMapping(cx.Env(), combined, *cx.mappingAtomType(p.Atom)) + m := intersectMapping(cx.Env(), combined, cx.mappingAtomType(p.Atom)) if m == nil { return true } else { - combined = *m + combined = m } p = p.Next } @@ -63,12 +63,12 @@ func mappingFormulaIsEmpty(cx Context, posList *Conjunction, negList *Conjunctio return (!mappingInhabited(cx, combined, negList)) } -func mappingInhabitedFast(cx Context, pos MappingAtomicType, negList *Conjunction) bool { +func mappingInhabitedFast(cx Context, pos *MappingAtomicType, negList *Conjunction) bool { // migrated from MappingOps.java:98:5 if negList == nil { return true } else { - neg := *cx.mappingAtomType(negList.Atom) + neg := cx.mappingAtomType(negList.Atom) pairing := NewFieldPairs(pos, neg) if !IsEmpty(cx, Diff(pos.Rest, neg.Rest)) { return mappingInhabitedFast(cx, pos, negList.Next) @@ -87,13 +87,13 @@ func mappingInhabitedFast(cx Context, pos MappingAtomicType, negList *Conjunctio } } -func mappingInhabited(cx Context, pos MappingAtomicType, negList *Conjunction) bool { +func mappingInhabited(cx Context, pos *MappingAtomicType, negList *Conjunction) bool { // migrated from MappingOps.java:127:5 if negList == nil { return true } else { neg := cx.mappingAtomType(negList.Atom) - pairing := NewFieldPairs(pos, *neg) + pairing := NewFieldPairs(pos, neg) if !IsEmpty(cx, Diff(pos.Rest, neg.Rest)) { return mappingInhabited(cx, pos, negList.Next) } @@ -106,13 +106,13 @@ func mappingInhabited(cx Context, pos MappingAtomicType, negList *Conjunction) b if !IsEmpty(cx, d) { var mt MappingAtomicType if fieldPair.Index1 == nil { - mt = insertField(pos, fieldPair.Name, *d) + mt = insertField(*pos, fieldPair.Name, *d) } else { posTypes := pos.Types posTypes[*fieldPair.Index1] = *d mt = MappingAtomicTypeFrom(pos.Names, posTypes, pos.Rest) } - if mappingInhabited(cx, mt, negList.Next) { + if mappingInhabited(cx, &mt, negList.Next) { return true } } @@ -141,7 +141,7 @@ func insertField(m MappingAtomicType, name string, t CellSemType) MappingAtomicT return MappingAtomicTypeFrom(names, types, m.Rest) } -func intersectMapping(env Env, m1 MappingAtomicType, m2 MappingAtomicType) *MappingAtomicType { +func intersectMapping(env Env, m1 *MappingAtomicType, m2 *MappingAtomicType) *MappingAtomicType { // migrated from MappingOps.java:186:5 var names []string var types []CellSemType