Skip to content

Commit

Permalink
Added labeled branch targets for for loops
Browse files Browse the repository at this point in the history
  • Loading branch information
ritchiecarroll committed Oct 13, 2024
1 parent 707974b commit 1c09ddf
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 66 deletions.
19 changes: 15 additions & 4 deletions src/Tests/Behavioral/ForVariants/ForVariants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ private static void Main() {

fmt.Println("i =", i);
fmt.Println();
@out:
ref var iɅ1 = ref heap(new nint(), out var ᏑiɅ1);
for (iɅ1 = 0; iɅ1 < 5; iɅ1++)
{
Expand All @@ -44,22 +45,32 @@ private static void Main() {
for (iɅ2 = 12; iɅ2 < 15; iɅ2++)
{
f(ᏑiɅ2);
goto @out_break;
}

//c
if (iɅ1 > 13)
{
goto @out_continue;
}

fmt.Println();
}

@out_continue:;
}
@out_break:;
//d
fmt.Println();
fmt.Println("i =", i);
fmt.Println();
while (true)
{
i++;
f(Ꮡi); /* visitIfStmt: if i > 12 {
break
} */
f(Ꮡi);
if (i > 12)
{
break;
}

}

Expand Down
7 changes: 7 additions & 0 deletions src/Tests/Behavioral/ForVariants/ForVariants.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,20 @@ func main() {
fmt.Println("i =", i)
fmt.Println()

out:
for i := 0; i < 5; i++ {
// a
f(&i) // b

for i := 12; i < 15; i++ {
f(&i)
break out
} //c

if i > 13 {
continue out
}

fmt.Println()
} //d

Expand Down
26 changes: 8 additions & 18 deletions src/go2cs2/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,12 @@ type Visitor struct {
tempVarCount map[string]int

// BlockStmt variables
blocks Stack[*strings.Builder]
blockInnerPrefixInjection Stack[string]
blockInnerSuffixInjection Stack[string]
blockOuterPrefixInjection Stack[string]
blockOuterSuffixInjection Stack[string]
firstStatementIsReturn bool
identEscapesHeap map[*ast.Ident]bool
identNames map[*ast.Ident]string // Local identifiers to adjusted names map
isReassigned map[*ast.Ident]bool // Local identifiers to reassignment status map
scopeStack []map[string]*types.Var // Stack of local variable scopes
blocks Stack[*strings.Builder]
firstStatementIsReturn bool
identEscapesHeap map[*ast.Ident]bool
identNames map[*ast.Ident]string // Local identifiers to adjusted names map
isReassigned map[*ast.Ident]bool // Local identifiers to reassignment status map
scopeStack []map[string]*types.Var // Stack of local variable scopes
}

const RootNamespace = "go"
Expand Down Expand Up @@ -280,14 +276,8 @@ Examples:
options: options,
globalIdentNames: globalIdentNames,
globalScope: globalScope,

// BlockStmt variable initializations
blocks: Stack[*strings.Builder]{},
blockInnerPrefixInjection: Stack[string]{},
blockInnerSuffixInjection: Stack[string]{},
blockOuterPrefixInjection: Stack[string]{},
blockOuterSuffixInjection: Stack[string]{},
identEscapesHeap: map[*ast.Ident]bool{},
blocks: Stack[*strings.Builder]{},
identEscapesHeap: map[*ast.Ident]bool{},
}

visitor.visitFile(fileEntry.file)
Expand Down
40 changes: 12 additions & 28 deletions src/go2cs2/visitBlockStmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,28 @@ import (
"strings"
)

func (v *Visitor) visitBlockStmt(blockStmt *ast.BlockStmt, format FormattingContext) {
func (v *Visitor) visitBlockStmt(blockStmt *ast.BlockStmt, context BlockStmtContext) {
v.pushBlock()

if v.blockOuterPrefixInjection.Len() > 0 {
v.targetFile.WriteString(v.blockOuterPrefixInjection.Pop())
if len(context.outerPrefix) > 0 {
v.targetFile.WriteString(context.outerPrefix)
}

if format.useNewLine {
if context.format.useNewLine {
v.targetFile.WriteString(v.newline)
v.targetFile.WriteString(v.indent(v.indentLevel))
v.targetFile.WriteString("{")
} else {
v.targetFile.WriteString(" {")
}

if v.blockInnerPrefixInjection.Len() > 0 {
v.targetFile.WriteString(v.blockInnerPrefixInjection.Pop())
if len(context.innerPrefix) > 0 {
v.targetFile.WriteString(context.innerPrefix)
}

v.firstStatementIsReturn = false

if format.useIndent {
if context.format.useIndent {
v.indentLevel++
}

Expand Down Expand Up @@ -67,7 +67,7 @@ func (v *Visitor) visitBlockStmt(blockStmt *ast.BlockStmt, format FormattingCont
lastStmt = stmt
}

if format.useIndent {
if context.format.useIndent {
v.indentLevel--
}

Expand All @@ -79,15 +79,15 @@ func (v *Visitor) visitBlockStmt(blockStmt *ast.BlockStmt, format FormattingCont
v.firstStatementIsReturn = ok
}

if v.blockInnerSuffixInjection.Len() > 0 {
v.targetFile.WriteString(v.blockInnerSuffixInjection.Pop())
if len(context.innerSuffix) > 0 {
v.targetFile.WriteString(context.innerSuffix)
}

v.targetFile.WriteString(v.newline)
v.writeOutputLn("}")

if v.blockOuterSuffixInjection.Len() > 0 {
v.targetFile.WriteString(v.blockOuterSuffixInjection.Pop())
if len(context.outerSuffix) > 0 {
v.targetFile.WriteString(context.outerSuffix)
}

// if (!m_firstTopLevelDeclaration && IndentLevel > 2)
Expand Down Expand Up @@ -117,19 +117,3 @@ func (v *Visitor) popBlockAppend(appendToPrevious bool) string {

return block
}

func (v *Visitor) pushInnerBlockPrefix(prefix string) {
v.blockInnerPrefixInjection.Push(prefix)
}

func (v *Visitor) pushInnerBlockSuffix(suffix string) {
v.blockInnerSuffixInjection.Push(suffix)
}

func (v *Visitor) pushOuterBlockPrefix(prefix string) {
v.blockOuterPrefixInjection.Push(prefix)
}

func (v *Visitor) pushOuterBlockSuffix(suffix string) {
v.blockOuterSuffixInjection.Push(suffix)
}
21 changes: 19 additions & 2 deletions src/go2cs2/visitBranchStmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,24 @@ import (
)

func (v *Visitor) visitBranchStmt(branchStmt *ast.BranchStmt) {
if branchStmt.Tok != token.FALLTHROUGH {
v.writeOutputLn("/* visitBranchStmt: " + v.getPrintedNode(branchStmt) + " */")
// FALLTHROUGH is handled in visitSwitchStmt.go
switch branchStmt.Tok {
case token.BREAK:
v.targetFile.WriteString(v.newline)
if branchStmt.Label == nil {
v.writeOutput("break;")
} else {
v.writeOutput("goto " + getSanitizedIdentifier(branchStmt.Label.Name) + "_break;")
}
case token.CONTINUE:
v.targetFile.WriteString(v.newline)
if branchStmt.Label == nil {
v.writeOutput("continue;")
} else {
v.writeOutput("goto " + getSanitizedIdentifier(branchStmt.Label.Name) + "_continue;")
}
case token.GOTO:
v.targetFile.WriteString(v.newline)
v.writeOutput("goto " + getSanitizedIdentifier(branchStmt.Label.Name) + ";")
}
}
14 changes: 11 additions & 3 deletions src/go2cs2/visitForStmt.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package main

import (
"fmt"
"go/ast"
"strings"
)

const ForVarInitMarker = ">>MARKER:FOR_VAR_INIT<<"

func (v *Visitor) visitForStmt(forStmt *ast.ForStmt) {
func (v *Visitor) visitForStmt(forStmt *ast.ForStmt, target LabeledStmtContext) {
v.targetFile.WriteString(v.newline)

// Handle while-style for loops
Expand All @@ -21,7 +22,7 @@ func (v *Visitor) visitForStmt(forStmt *ast.ForStmt) {
}

v.targetFile.WriteString(") ")
v.visitBlockStmt(forStmt.Body, DefaultFormattingContext())
v.visitBlockStmt(forStmt.Body, DefaultBlockStmtContext())
return
}

Expand Down Expand Up @@ -86,5 +87,12 @@ func (v *Visitor) visitForStmt(forStmt *ast.ForStmt) {

v.targetFile.WriteString(") ")

v.visitBlockStmt(forStmt.Body, DefaultFormattingContext())
blockContext := DefaultBlockStmtContext()

if len(target.label) > 0 {
blockContext.innerSuffix = fmt.Sprintf("%s%s%s_continue:;", v.newline, v.newline, target.label)
blockContext.outerSuffix = fmt.Sprintf("%s_break:;", target.label)
}

v.visitBlockStmt(forStmt.Body, blockContext)
}
9 changes: 5 additions & 4 deletions src/go2cs2/visitFuncDecl.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@ func (v *Visitor) visitFuncDecl(funcDecl *ast.FuncDecl) {

functionParametersMarker := fmt.Sprintf(FunctionParametersMarker, goFunctionName)
functionExecContextMarker := fmt.Sprintf(FunctionExecContextMarker, goFunctionName)
v.pushInnerBlockPrefix(fmt.Sprintf(FunctionBlockPrefixMarker, goFunctionName))

blockContext := DefaultBlockStmtContext()
blockContext.innerPrefix = fmt.Sprintf(FunctionBlockPrefixMarker, goFunctionName)

v.writeOutput(fmt.Sprintf("%s static %s %s(%s)%s", getAccess(goFunctionName), generateResultSignature(signature), csFunctionName, functionParametersMarker, functionExecContextMarker))

if funcDecl.Body != nil {
format := DefaultFormattingContext()
format.useNewLine = false
v.visitBlockStmt(funcDecl.Body, format)
blockContext.format.useNewLine = false
v.visitBlockStmt(funcDecl.Body, blockContext)
}

signatureOnly := funcDecl.Body == nil
Expand Down
31 changes: 29 additions & 2 deletions src/go2cs2/visitIfStmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,33 @@ import (
"go/ast"
)

func (v *Visitor) visitIfStmt(ifStmt *ast.IfStmt) {
v.writeOutputLn("/* visitIfStmt: " + v.getPrintedNode(ifStmt) + " */")
func (v *Visitor) visitIfStmt(ifStmt *ast.IfStmt, source ParentBlockContext) {
v.targetFile.WriteString(v.newline)

if ifStmt.Init != nil {
// Any declared variable will be scoped to if statement, so create a sub-block for it
v.targetFile.WriteString(v.newline)
v.writeOutput("{")
v.indentLevel++

v.visitStmt(ifStmt.Init, []StmtContext{source})
}

v.writeOutput("if (")
v.targetFile.WriteString(v.convExpr(ifStmt.Cond, nil))
v.targetFile.WriteString(") ")

v.visitBlockStmt(ifStmt.Body, DefaultBlockStmtContext())

if ifStmt.Else != nil {
v.writeOutput(" else ")
switch elseStmt := ifStmt.Else.(type) {
case *ast.IfStmt:
v.visitIfStmt(elseStmt, source)
case *ast.BlockStmt:
v.visitBlockStmt(elseStmt, DefaultBlockStmtContext())
default:
panic("Unexpected Else type: " + v.getPrintedNode(elseStmt))
}
}
}
10 changes: 9 additions & 1 deletion src/go2cs2/visitLabeledStmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,13 @@ import (
)

func (v *Visitor) visitLabeledStmt(labeledStmt *ast.LabeledStmt) {
v.writeOutputLn("/* " + v.getPrintedNode(labeledStmt) + " */")
v.targetFile.WriteString(v.newline)

labelName := getSanitizedIdentifier(labeledStmt.Label.Name)

v.targetFile.WriteString(labelName + ":")

target := LabeledStmtContext{label: labelName}

v.visitStmt(labeledStmt.Stmt, []StmtContext{target})
}
46 changes: 42 additions & 4 deletions src/go2cs2/visitStmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,42 @@ func (c FormattingContext) getDefault() StmtContext {
return DefaultFormattingContext()
}

type BlockStmtContext struct {
format FormattingContext
innerPrefix string
innerSuffix string
outerPrefix string
outerSuffix string
}

func DefaultBlockStmtContext() BlockStmtContext {
return BlockStmtContext{
format: DefaultFormattingContext(),
innerPrefix: "",
innerSuffix: "",
outerPrefix: "",
outerSuffix: "",
}
}

func (c BlockStmtContext) getDefault() StmtContext {
return DefaultBlockStmtContext()
}

type LabeledStmtContext struct {
label string
}

func DefaultLabeledStmtContext() LabeledStmtContext {
return LabeledStmtContext{
label: "",
}
}

func (c LabeledStmtContext) getDefault() StmtContext {
return DefaultLabeledStmtContext()
}

func getStmtContext[TContext StmtContext](contexts []StmtContext) TContext {
var zeroValue TContext

Expand All @@ -69,8 +105,8 @@ func (v *Visitor) visitStmt(stmt ast.Stmt, contexts []StmtContext) {
format := getStmtContext[FormattingContext](contexts)
v.visitAssignStmt(stmtType, source, format)
case *ast.BlockStmt:
format := getStmtContext[FormattingContext](contexts)
v.visitBlockStmt(stmtType, format)
context := getStmtContext[BlockStmtContext](contexts)
v.visitBlockStmt(stmtType, context)
case *ast.BranchStmt:
v.visitBranchStmt(stmtType)
case *ast.CommClause:
Expand All @@ -85,11 +121,13 @@ func (v *Visitor) visitStmt(stmt ast.Stmt, contexts []StmtContext) {
case *ast.ExprStmt:
v.visitExprStmt(stmtType)
case *ast.ForStmt:
v.visitForStmt(stmtType)
target := getStmtContext[LabeledStmtContext](contexts)
v.visitForStmt(stmtType, target)
case *ast.GoStmt:
v.visitGoStmt(stmtType)
case *ast.IfStmt:
v.visitIfStmt(stmtType)
source := getStmtContext[ParentBlockContext](contexts)
v.visitIfStmt(stmtType, source)
case *ast.IncDecStmt:
format := getStmtContext[FormattingContext](contexts)
v.visitIncDecStmt(stmtType, format)
Expand Down

0 comments on commit 1c09ddf

Please sign in to comment.