Generate match statement default cases
This commit is contained in:
parent
4931f97496
commit
5dda7b2186
|
@ -82,6 +82,16 @@ testUnit (test,
|
|||
0,
|
||||
)}
|
||||
|
||||
func TestMatchDefaultPrint (test *testing.T) {
|
||||
dependencies := []string {
|
||||
compileDependency(test, "io"),
|
||||
}
|
||||
testUnit (test,
|
||||
"/test-data/data/match-default-print", dependencies,
|
||||
"", "something else\n",
|
||||
0,
|
||||
)}
|
||||
|
||||
func TestReturnAssign (test *testing.T) {
|
||||
dependencies := []string {
|
||||
compileDependency(test, "io"),
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
'624d4557-5291-4ad7-9283-7c200b9c2942'
|
||||
+ 'io'
|
|
@ -0,0 +1,11 @@
|
|||
[main]: I32 'main' = {
|
||||
x:UInt = 7
|
||||
[matchToInt x]
|
||||
0
|
||||
}
|
||||
|
||||
U: (| Int F64 UInt)
|
||||
[matchToInt u:U] = match u
|
||||
| u:Int io::[println 'Int']
|
||||
| u:F64 io::[println 'F64']
|
||||
* io::[println 'something else']
|
|
@ -340,6 +340,92 @@ U: (| Int F64 UInt)
|
|||
`)
|
||||
}
|
||||
|
||||
func TestMatchDefault (test *testing.T) {
|
||||
testString (test,
|
||||
`%"0zNZN147MN2wzMAQ6NS2dQ==::U" = type { i64, i64 }
|
||||
%"AAAAAAAAAAAAAAAAAAAAAA==::Index" = type i64
|
||||
%"AAAAAAAAAAAAAAAAAAAAAA==::String" = type { ptr, %"AAAAAAAAAAAAAAAAAAAAAA==::Index" }
|
||||
define void @"0zNZN147MN2wzMAQ6NS2dQ==::matchToInt"(%"0zNZN147MN2wzMAQ6NS2dQ==::U" %u) {
|
||||
0:
|
||||
%1 = alloca %"0zNZN147MN2wzMAQ6NS2dQ==::U"
|
||||
store %"0zNZN147MN2wzMAQ6NS2dQ==::U" %u, ptr %1
|
||||
%2 = alloca i64
|
||||
%3 = alloca %"AAAAAAAAAAAAAAAAAAAAAA==::String"
|
||||
%4 = alloca [3 x i8]
|
||||
%5 = alloca double
|
||||
%6 = alloca %"AAAAAAAAAAAAAAAAAAAAAA==::String"
|
||||
%7 = alloca [3 x i8]
|
||||
%8 = alloca %"AAAAAAAAAAAAAAAAAAAAAA==::String"
|
||||
%9 = alloca [3 x i8]
|
||||
%10 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::U", ptr %1, i32 0, i32 0
|
||||
%11 = load i64, ptr %10
|
||||
switch i64 %11, label %31 [
|
||||
i64 7620767046192759206, label %13
|
||||
i64 9186060094042213285, label %22
|
||||
]
|
||||
12:
|
||||
ret void
|
||||
13:
|
||||
%14 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::U", ptr %1, i32 0, i32 1
|
||||
%15 = load i64, ptr %14
|
||||
store i64 %15, ptr %2
|
||||
%16 = getelementptr [3 x i8], ptr %4, i32 0, i32 0
|
||||
store i8 73, ptr %16
|
||||
%17 = getelementptr [3 x i8], ptr %4, i32 0, i32 1
|
||||
store i8 110, ptr %17
|
||||
%18 = getelementptr [3 x i8], ptr %4, i32 0, i32 2
|
||||
store i8 116, ptr %18
|
||||
%19 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %3, i32 0, i32 0
|
||||
store ptr %4, ptr %19
|
||||
%20 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %3, i32 0, i32 1
|
||||
store %"AAAAAAAAAAAAAAAAAAAAAA==::Index" 3, ptr %20
|
||||
%21 = load %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %3
|
||||
call void @"0zNZN147MN2wzMAQ6NS2dQ==::print"(%"AAAAAAAAAAAAAAAAAAAAAA==::String" %21)
|
||||
br label %12
|
||||
22:
|
||||
%23 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::U", ptr %1, i32 0, i32 1
|
||||
%24 = load double, ptr %23
|
||||
store double %24, ptr %5
|
||||
%25 = getelementptr [3 x i8], ptr %7, i32 0, i32 0
|
||||
store i8 70, ptr %25
|
||||
%26 = getelementptr [3 x i8], ptr %7, i32 0, i32 1
|
||||
store i8 54, ptr %26
|
||||
%27 = getelementptr [3 x i8], ptr %7, i32 0, i32 2
|
||||
store i8 52, ptr %27
|
||||
%28 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %6, i32 0, i32 0
|
||||
store ptr %7, ptr %28
|
||||
%29 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %6, i32 0, i32 1
|
||||
store %"AAAAAAAAAAAAAAAAAAAAAA==::Index" 3, ptr %29
|
||||
%30 = load %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %6
|
||||
call void @"0zNZN147MN2wzMAQ6NS2dQ==::print"(%"AAAAAAAAAAAAAAAAAAAAAA==::String" %30)
|
||||
br label %12
|
||||
31:
|
||||
%32 = getelementptr [3 x i8], ptr %9, i32 0, i32 0
|
||||
store i8 105, ptr %32
|
||||
%33 = getelementptr [3 x i8], ptr %9, i32 0, i32 1
|
||||
store i8 100, ptr %33
|
||||
%34 = getelementptr [3 x i8], ptr %9, i32 0, i32 2
|
||||
store i8 107, ptr %34
|
||||
%35 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %8, i32 0, i32 0
|
||||
store ptr %9, ptr %35
|
||||
%36 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %8, i32 0, i32 1
|
||||
store %"AAAAAAAAAAAAAAAAAAAAAA==::Index" 3, ptr %36
|
||||
%37 = load %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %8
|
||||
call void @"0zNZN147MN2wzMAQ6NS2dQ==::print"(%"AAAAAAAAAAAAAAAAAAAAAA==::String" %37)
|
||||
br label %12
|
||||
}
|
||||
declare void @"0zNZN147MN2wzMAQ6NS2dQ==::print"(%"AAAAAAAAAAAAAAAAAAAAAA==::String" %str)
|
||||
`,
|
||||
`
|
||||
U: (| Int F64 UInt)
|
||||
[print str:String]
|
||||
[matchToInt u:U] = match u
|
||||
| u:Int [print 'Int']
|
||||
| u:F64 [print 'F64']
|
||||
* [print 'idk']
|
||||
`)
|
||||
}
|
||||
|
||||
func TestIfElseReturnValueUsed (test *testing.T) {
|
||||
testString (test,
|
||||
`%"AAAAAAAAAAAAAAAAAAAAAA==::Bool" = type i1
|
||||
|
|
|
@ -122,7 +122,6 @@ func (this *generator) generateIfElse (ifelse *entity.IfElse, mode resultMode) (
|
|||
}
|
||||
|
||||
func (this *generator) generateMatch (match *entity.Match, mode resultMode) (llvm.Value, bool, error) {
|
||||
var loc bool
|
||||
value, err := this.generateExpressionLoc(match.Value)
|
||||
if err != nil { return nil, false, err }
|
||||
irUnionType, err := this.generateType(match.Value.Type())
|
||||
|
@ -134,6 +133,31 @@ func (this *generator) generateMatch (match *entity.Match, mode resultMode) (llv
|
|||
|
||||
irCases := make([]*llvm.Case, len(match.Cases))
|
||||
irIncomings := []*llvm.Incoming { }
|
||||
loc := false
|
||||
first := true
|
||||
|
||||
generateCaseExpression := func (expression entity.Expression) error {
|
||||
thisMode := mode
|
||||
if !first && mode != resultModeAny {
|
||||
if loc { thisMode = resultModeLoc
|
||||
} else { thisMode = resultModeVal }
|
||||
}
|
||||
result, thisLoc, err := this.generateExpression(expression, thisMode)
|
||||
if err != nil { return err }
|
||||
if first { loc = thisLoc }
|
||||
if !this.blockManager.Terminated() {
|
||||
if expression != nil {
|
||||
irIncomings = append(irIncomings, &llvm.Incoming {
|
||||
X: result,
|
||||
Predecessor: this.blockManager.Block,
|
||||
})
|
||||
}
|
||||
this.blockManager.NewBr(exitBlock)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// generate type cases
|
||||
for index, cas := range match.Cases {
|
||||
// set up ir case
|
||||
caseBlock := this.blockManager.newBlock()
|
||||
|
@ -151,30 +175,27 @@ func (this *generator) generateMatch (match *entity.Match, mode resultMode) (llv
|
|||
this.blockManager.addDeclaration(cas.Declaration, data)
|
||||
|
||||
// generate case expression
|
||||
thisMode := mode
|
||||
if index != 0 && mode != resultModeAny {
|
||||
if loc { thisMode = resultModeLoc
|
||||
} else { thisMode = resultModeVal }
|
||||
}
|
||||
caseExpression, thisLoc, err := this.generateExpression(cas.Expression, thisMode)
|
||||
err = generateCaseExpression(cas.Expression)
|
||||
if err != nil { return nil, false, err }
|
||||
}
|
||||
|
||||
// generate default case
|
||||
var defaultBlock llvm.Value
|
||||
if match.Default != nil {
|
||||
defaultBlock = this.blockManager.newBlock()
|
||||
err = generateCaseExpression(match.Default.Expression)
|
||||
if err != nil { return nil, false, err }
|
||||
if index == 0 { loc = thisLoc }
|
||||
if !this.blockManager.Terminated() {
|
||||
if caseExpression != nil {
|
||||
irIncomings = append(irIncomings, &llvm.Incoming {
|
||||
X: caseExpression,
|
||||
Predecessor: this.blockManager.Block,
|
||||
})
|
||||
}
|
||||
this.blockManager.NewBr(exitBlock)
|
||||
}
|
||||
}
|
||||
|
||||
// create switch branch
|
||||
this.blockManager.Block = previousBlock
|
||||
hashFieldLoc := this.getUnionTypeFieldLoc(value, irUnionType)
|
||||
hash := this.blockManager.NewLoad(irHashType, hashFieldLoc)
|
||||
this.blockManager.NewSwitch(hash, exitBlock, irCases...)
|
||||
if defaultBlock == nil {
|
||||
this.blockManager.NewSwitch(hash, exitBlock, irCases...)
|
||||
} else {
|
||||
this.blockManager.NewSwitch(hash, defaultBlock, irCases...)
|
||||
}
|
||||
|
||||
// discard/obtain results
|
||||
this.blockManager.Block = exitBlock
|
||||
|
@ -183,10 +204,12 @@ func (this *generator) generateMatch (match *entity.Match, mode resultMode) (llv
|
|||
} else {
|
||||
irType, err := this.generateType(match.Type())
|
||||
if err != nil { return nil, false, err }
|
||||
irIncomings = append(irIncomings, &llvm.Incoming {
|
||||
X: llvm.NewConstZeroInitializer(irType),
|
||||
Predecessor: previousBlock,
|
||||
})
|
||||
if defaultBlock == nil {
|
||||
irIncomings = append(irIncomings, &llvm.Incoming {
|
||||
X: llvm.NewConstZeroInitializer(irType),
|
||||
Predecessor: previousBlock,
|
||||
})
|
||||
}
|
||||
return this.blockManager.NewPhi(irIncomings...), loc, nil
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue