Skip to content

Commit 009fdfa

Browse files
Completed initial switch implementation
1 parent 5b66493 commit 009fdfa

File tree

12 files changed

+445
-81
lines changed

12 files changed

+445
-81
lines changed

src/Tests/Behavioral/ExprSwitch/ExprSwitch.cs

Lines changed: 96 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ public static partial class main_package {
88

99
private static nint x = 1;
1010

11-
private static nint getNext() { x++;
12-
13-
return x;
11+
private static int32 getNext() {
12+
x++;
13+
return int32(x);
1414
}
1515

1616
private static @string getStr(@string test) {
@@ -45,8 +45,8 @@ private static void Main() {
4545
}
4646

4747
break;
48-
case 4:
49-
fmt.Println("four");
48+
case 4 or 5 or 6:
49+
fmt.Println("four, five or siz");
5050
break;
5151
default:
5252
fmt.Println("unknown");
@@ -56,17 +56,16 @@ private static void Main() {
5656
nint x = 5;
5757
fmt.Println(x);
5858
{
59-
nint xꞥ1 = 6;
60-
fmt.Println(xꞥ1);
59+
nint xɅ1 = 6;
60+
fmt.Println(xɅ1);
6161
}
6262

6363
fmt.Println(x);
6464
// You can use commas to separate multiple expressions
6565
// in the same `case` statement. We use the optional
6666
// `default` case in this example as well.
6767
switch (time.Now().Weekday()) {
68-
case time.Saturday:
69-
case time.Sunday:
68+
case time.Saturday or time.Sunday:
7069
fmt.Println("It's the weekend");
7170
break;
7271
case time.Monday:
@@ -82,19 +81,105 @@ private static void Main() {
8281
// to express if/else logic. Here we also show how the
8382
// `case` expressions can be non-constants.
8483
var t = time.Now();
84+
{
85+
switch () {
86+
case when t.Hour() is < 12:
87+
fmt.Println("It's before noon");
88+
break;
89+
default:
90+
fmt.Println("It's after noon");
91+
break;
92+
}
93+
}
8594

8695
// Before noon
8796
// After noon
97+
// Here is a more complex switch
98+
nint hour = 1;
99+
nint hour1 = time.Now().Hour();
100+
{
101+
nint hourɅ1 = time.Now().Hour();
102+
switch () {
103+
case when hourɅ1 is 1 or < 12 or 2:
104+
fmt.Println("Good morning!");
105+
break;
106+
case when (hourɅ1 == 1) || (hourɅ1 < 12) || (hourɅ1 == 2 || hour1 == 4):
107+
fmt.Println("Good morning (opt 2)!");
108+
break;
109+
case when hourɅ1 is < 17:
110+
fmt.Println("Good afternoon!");
111+
break;
112+
case when hourɅ1 is 0:
113+
fmt.Println("Midnight!");
114+
break;
115+
case when hourɅ1 == 0 && hour1 == 1:
116+
fmt.Println("Midnight (opt 2)!");
117+
break;
118+
default:
119+
fmt.Println("Good evening!");
120+
break;
121+
}
122+
}
123+
124+
// missing expression means "true"
125+
fmt.Println(hour);
126+
var c = '\r';
127+
switch (c) {
128+
case ' ' or '\t' or '\n' or '\f' or '\r':
129+
fmt.Println("whitespace");
130+
break;
131+
}
132+
88133
// "i" before should be saved
89134
fmt.Printf("i before = %d\n"u8, i);
90135
// Here is a switch with simple statement and a redeclared identifier plus a fallthrough
91136
{
92-
93-
nint iꞥ1 = 1;
137+
nint iɅ1 = 1;
138+
var exprꞥ1 = getNext();
139+
var matchꞥ1 = false;
140+
if (exprꞥ1 is -1) { matchꞥ1 = true;
141+
fmt.Println("negative");
142+
}
143+
if (exprꞥ1 is 0) { matchꞥ1 = true;
144+
fmt.Println("zero");
145+
}
146+
if (exprꞥ1 is 1 or 2) { matchꞥ1 = true;
147+
fmt.Println("one or two");
148+
fallthrough = true;
149+
}
150+
if (fallthrough || exprꞥ1 is 3) { matchꞥ1 = true;
151+
fmt.Printf("three, but x=%d and i now = %d\n"u8, x, iɅ1);
152+
fallthrough = true;
153+
}
154+
if (fallthrough || !matchꞥ1) { /* default: */
155+
fmt.Println("plus, always a default here because of fallthrough");
156+
}
94157
}
95158

96159
// "i" after should be restored
97160
fmt.Printf("i after = %d\n"u8, i);
161+
{
162+
var next = getNext();
163+
var matchꞥ2 = false;
164+
if (next is <= -1) { matchꞥ2 = true;
165+
fmt.Println("negative");
166+
}
167+
if (next is 0) { matchꞥ2 = true;
168+
fmt.Println("zero");
169+
}
170+
if (next is 1 or 2) { matchꞥ2 = true;
171+
fmt.Println("one or two");
172+
fallthrough = true;
173+
}
174+
if (fallthrough || next >= 3 && next < 100) { matchꞥ2 = true;
175+
fmt.Printf("three or greater < 100: %d\n"u8, x);
176+
fallthrough = true;
177+
}
178+
if (fallthrough || !matchꞥ2) { /* default: */
179+
fmt.Println("plus, always a default here because of fallthrough");
180+
}
181+
}
182+
98183
}
99184

100185
} // end main_package

src/Tests/Behavioral/ExprSwitch/ExprSwitch.go

Lines changed: 64 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,24 @@
33

44
package main
55

6-
import "fmt"
7-
import "time"
6+
import (
7+
"fmt"
8+
"time"
9+
)
810

911
var x = 1
1012

11-
func getNext() int {
12-
x++
13-
return x
13+
func getNext() int32 {
14+
x++
15+
return int32(x)
1416
}
1517

1618
func getStr(test string) string {
17-
return "string" + test
19+
return "string" + test
1820
}
1921

2022
func getStr2(test1 interface{}, test2 string) string {
21-
return test1.(string) + test2
23+
return test1.(string) + test2
2224
}
2325

2426
func getStr3(format string, a ...interface{}) string {
@@ -27,9 +29,9 @@ func getStr3(format string, a ...interface{}) string {
2729

2830
func main() {
2931

30-
fmt.Println(getStr("test"))
31-
fmt.Println(getStr2("hello, ", "world"))
32-
fmt.Println(getStr3("hello, %s", "world"))
32+
fmt.Println(getStr("test"))
33+
fmt.Println(getStr2("hello, ", "world"))
34+
fmt.Println(getStr3("hello, %s", "world"))
3335

3436
// Here's a basic `switch`.
3537
i := 2
@@ -43,21 +45,21 @@ func main() {
4345
{
4446
fmt.Println("three")
4547
}
46-
case 4:
47-
fmt.Println("four")
48+
case 4, 5, 6:
49+
fmt.Println("four, five or siz")
4850
default:
4951
fmt.Println("unknown")
5052
}
5153

52-
x := 5
53-
fmt.Println(x)
54+
x := 5
55+
fmt.Println(x)
5456

55-
{
56-
x := 6
57-
fmt.Println(x)
58-
}
57+
{
58+
x := 6
59+
fmt.Println(x)
60+
}
5961

60-
fmt.Println(x)
62+
fmt.Println(x)
6163

6264
// You can use commas to separate multiple expressions
6365
// in the same `case` statement. We use the optional
@@ -82,6 +84,34 @@ func main() {
8284
fmt.Println("It's after noon")
8385
}
8486

87+
// Here is a more complex switch
88+
hour := 1
89+
hour1 := time.Now().Hour()
90+
91+
switch hour := time.Now().Hour(); { // missing expression means "true"
92+
case hour == 1, hour < 12, hour == 2:
93+
fmt.Println("Good morning!")
94+
case hour == 1, hour < 12, hour == 2 || hour1 == 4:
95+
fmt.Println("Good morning (opt 2)!")
96+
case hour < 17:
97+
fmt.Println("Good afternoon!")
98+
case hour == 0:
99+
fmt.Println("Midnight!")
100+
case hour == 0 && hour1 == 1:
101+
fmt.Println("Midnight (opt 2)!")
102+
default:
103+
fmt.Println("Good evening!")
104+
}
105+
106+
fmt.Println(hour)
107+
108+
c := '\r'
109+
110+
switch c {
111+
case ' ', '\t', '\n', '\f', '\r':
112+
fmt.Println("whitespace")
113+
}
114+
85115
// "i" before should be saved
86116
fmt.Printf("i before = %d\n", i)
87117

@@ -103,4 +133,19 @@ func main() {
103133

104134
// "i" after should be restored
105135
fmt.Printf("i after = %d\n", i)
136+
137+
switch next := getNext(); {
138+
case next <= -1:
139+
fmt.Println("negative")
140+
case next == 0:
141+
fmt.Println("zero")
142+
case next == 1, next == 2:
143+
fmt.Println("one or two")
144+
fallthrough
145+
case next >= 3 && next < 100:
146+
fmt.Printf("three or greater < 100: %d\n", x)
147+
fallthrough
148+
default:
149+
fmt.Println("plus, always a default here because of fallthrough")
150+
}
106151
}

src/Tests/Behavioral/SortArrayType/SortArrayType.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,15 @@ public static (nint E2, @string p) Testing() {
155155
fmt.Println(E2, B2);
156156
p = "Hello"u8;
157157
{
158-
nint E2ꞥ1 = 99;
159-
nint B2ꞥ1 = 199;
160-
fmt.Println(E2ꞥ1, B2ꞥ1);
158+
nint E2Ʌ1 = 99;
159+
nint B2Ʌ1 = 199;
160+
fmt.Println(E2Ʌ1, B2Ʌ1);
161161
}
162162

163163
{
164164
E2 = 100;
165-
nint B2ꞥ2 = 200;
166-
fmt.Println(E2, B2ꞥ2);
165+
nint B2Ʌ2 = 200;
166+
fmt.Println(E2, B2Ʌ2);
167167
}
168168

169169
fmt.Println(E2, B2);

src/go2cs2/convBinaryExpr.go

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,42 @@ import (
55
"go/ast"
66
)
77

8-
func (v *Visitor) convBinaryExpr(binaryExpr *ast.BinaryExpr) string {
8+
func (v *Visitor) convBinaryExpr(binaryExpr *ast.BinaryExpr, context *PatternMatchExprContext) string {
99
leftOperand := v.convExpr(binaryExpr.X, nil)
1010
binaryOp := binaryExpr.Op.String()
1111
rightOperand := v.convExpr(binaryExpr.Y, nil)
1212

13-
if binaryOp == "<<" || binaryOp == ">>" {
14-
rightOperand = fmt.Sprintf("(int)(%s)", rightOperand)
13+
if context == nil {
14+
if binaryOp == "<<" || binaryOp == ">>" {
15+
rightOperand = fmt.Sprintf("(int)(%s)", rightOperand)
16+
}
17+
18+
if binaryOp == "&^" {
19+
binaryOp = " & ~"
20+
} else {
21+
binaryOp = " " + binaryOp + " "
22+
}
23+
24+
return fmt.Sprintf("%s%s%s", leftOperand, binaryOp, rightOperand)
25+
}
26+
27+
// Handle start of pattern match expression with "is" keyword:
28+
if context.declareIsExpr {
29+
if binaryOp == "==" {
30+
binaryOp = ""
31+
} else {
32+
binaryOp = " " + binaryOp
33+
}
34+
35+
return fmt.Sprintf("%s is%s %s", leftOperand, binaryOp, rightOperand)
1536
}
1637

17-
if binaryOp == "&^" {
18-
binaryOp = " & ~"
38+
// Handle remaining pattern match expressions:
39+
if binaryOp == "==" {
40+
binaryOp = ""
1941
} else {
20-
binaryOp = " " + binaryOp + " "
42+
binaryOp = binaryOp + " "
2143
}
2244

23-
return fmt.Sprintf("%s%s%s", leftOperand, binaryOp, rightOperand)
45+
return fmt.Sprintf("%s%s", binaryOp, rightOperand)
2446
}

src/go2cs2/convExpr.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ type BasicLitContext struct {
1616
u8StringOK bool
1717
}
1818

19+
// Handles pattern match expressions, e.g.: "x is 1 or > 3"
20+
type PatternMatchExprContext struct {
21+
declareIsExpr bool
22+
}
23+
1924
func (v *Visitor) convExpr(expr ast.Expr, context ExprContext) string {
2025
switch exprType := expr.(type) {
2126
case *ast.ArrayType:
@@ -27,7 +32,11 @@ func (v *Visitor) convExpr(expr ast.Expr, context ExprContext) string {
2732

2833
return v.convBasicLit(exprType, true)
2934
case *ast.BinaryExpr:
30-
return v.convBinaryExpr(exprType)
35+
if context, ok := context.(*PatternMatchExprContext); ok && context != nil {
36+
return v.convBinaryExpr(exprType, context)
37+
}
38+
39+
return v.convBinaryExpr(exprType, nil)
3140
case *ast.CallExpr:
3241
return v.convCallExpr(exprType)
3342
case *ast.ChanType:

0 commit comments

Comments
 (0)