From a54afdc6ffe792fd969790b6c5064e1875c9ad65 Mon Sep 17 00:00:00 2001 From: Vilsol Date: Tue, 15 Mar 2022 01:44:32 +0200 Subject: [PATCH] Support unary for loop logic, Go 1.18rc1 --- .github/workflows/build.yml | 4 +- .github/workflows/release.yml | 4 +- tests/transpiler/statement_test.go | 29 +++++++++ transpiler/statement.go | 99 +++++++++++++++++++++++------- 4 files changed, 111 insertions(+), 25 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8163f87..0719d81 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.18.0-beta2 + go-version: 1.18.0-rc1 stable: false - name: Check out code into the Go module directory @@ -47,7 +47,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.18.0-beta2 + go-version: 1.18.0-rc1 stable: false - name: Check out code into the Go module directory diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f0912a4..e9956bb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,7 +13,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.18.0-beta2 + go-version: 1.18.0-rc1 stable: false - name: Check out code into the Go module directory @@ -47,7 +47,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.18.0-beta2 + go-version: 1.18.0-rc1 stable: false - name: Check out code into the Go module directory diff --git a/tests/transpiler/statement_test.go b/tests/transpiler/statement_test.go index a88c363..1be8566 100644 --- a/tests/transpiler/statement_test.go +++ b/tests/transpiler/statement_test.go @@ -37,6 +37,35 @@ jump 6 always print _main_i op add _main_i _main_i 1 jump 3 lessThan _main_i 10`, + }, + { + name: "ForLoop2", + input: TestMain(`x := false +for !x { +x = true +}`, false, false), + output: `set _main_x false +jump 3 notEqual _main_x true +jump 5 always +set _main_x true +jump 3 notEqual _main_x true`, + }, + { + name: "ForLoop3", + input: TestMain(`s := m.B("switch1") +a := 1 +b := 2 +for s.IsEnabled() && a < b { + print(1) +}`, true, false), + output: `set _main_s switch1 +set _main_a 1 +set _main_b 2 +sensor _main_0 _main_s @enabled +jump 6 equal _main_0 true +jump 8 always +print 1 +jump 3 always`, }, { name: "Reassignment", diff --git a/transpiler/statement.go b/transpiler/statement.go index c08da80..6f9de09 100644 --- a/transpiler/statement.go +++ b/transpiler/statement.go @@ -319,7 +319,21 @@ func forStmtToMLOG(ctx context.Context, statement *ast.ForStmt) ([]MLOGStatement var loopStartJump *MLOGJump var intoLoopJump *MLOGJump + var loopStartOverride *MLOGStatement + if statement.Cond != nil { + loopStartJump = &MLOGJump{ + MLOG: MLOG{ + Comment: "Jump to start of loop", + }, + } + + intoLoopJump = &MLOGJump{ + MLOG: MLOG{ + Comment: "Jump into the loop", + }, + } + if binaryExpr, ok := statement.Cond.(*ast.BinaryExpr); ok { if translatedOp, ok := jumpOperators[binaryExpr.Op]; ok { leftSide, leftExprInstructions, err := exprToResolvable(ctx, binaryExpr.X) @@ -342,32 +356,70 @@ func forStmtToMLOG(ctx context.Context, statement *ast.ForStmt) ([]MLOGStatement return nil, Err(ctx, "unknown error") } - loopStartJump = &MLOGJump{ - MLOG: MLOG{ - Comment: "Jump to start of loop", - }, - Condition: []Resolvable{ - &Value{Value: translatedOp}, - leftSide[0], - rightSide[0], - }, + loopStartJump.Condition = []Resolvable{ + &Value{Value: translatedOp}, + leftSide[0], + rightSide[0], } - intoLoopJump = &MLOGJump{ - MLOG: MLOG{ - Comment: "Jump into the loop", - }, - Condition: []Resolvable{ - &Value{Value: translatedOp}, - leftSide[0], - rightSide[0], - }, + intoLoopJump.Condition = []Resolvable{ + &Value{Value: translatedOp}, + leftSide[0], + rightSide[0], } } else { - return nil, Err(ctx, fmt.Sprintf("jump statement cannot use this operation: %T", binaryExpr.Op)) + expr, exprInstructions, err := exprToResolvable(ctx, binaryExpr.X) + if err != nil { + return nil, err + } + + results = append(results, exprInstructions...) + + if len(expr) != 1 { + return nil, Err(ctx, "unknown error") + } + + loopStartJump.Condition = []Resolvable{ + &Value{Value: "always"}, + } + + intoLoopJump.Condition = []Resolvable{ + &Value{Value: jumpOperators[token.EQL]}, + expr[0], + &Value{Value: "true"}, + } + + loopStartOverride = &exprInstructions[0] + } + } else if unaryExpr, ok := statement.Cond.(*ast.UnaryExpr); ok { + if unaryExpr.Op != token.NOT { + return nil, Err(ctx, fmt.Sprintf("loop unary expresion cannot use this operation: %T", binaryExpr.Op)) + } + + expr, exprInstructions, err := exprToResolvable(ctx, unaryExpr.X) + if err != nil { + return nil, err + } + + results = append(results, exprInstructions...) + + if len(expr) != 1 { + return nil, Err(ctx, "unknown error") + } + + loopStartJump.Condition = []Resolvable{ + &Value{Value: jumpOperators[token.NEQ]}, + expr[0], + &Value{Value: "true"}, + } + + intoLoopJump.Condition = []Resolvable{ + &Value{Value: jumpOperators[token.NEQ]}, + expr[0], + &Value{Value: "true"}, } } else { - return nil, Err(ctx, "for loop can only have binary conditional expressions") + return nil, Err(ctx, "for loop can only have unary or binary conditional expressions") } } else { loopStartJump = &MLOGJump{ @@ -425,7 +477,12 @@ func forStmtToMLOG(ctx context.Context, statement *ast.ForStmt) ([]MLOGStatement blockCtxStruct.Extra = append(blockCtxStruct.Extra, instructions...) } - loopStartJump.JumpTarget = bodyMLOG[0] + if loopStartOverride != nil { + loopStartJump.JumpTarget = *loopStartOverride + } else { + loopStartJump.JumpTarget = bodyMLOG[0] + } + results = append(results, loopStartJump) blockCtxStruct.Extra = append(blockCtxStruct.Extra, loopStartJump)