Skip to content

Commit

Permalink
Add support for switch statements
Browse files Browse the repository at this point in the history
- Add long overdue support for switch statments, doesn't currently check if each section has a break and relies on the normal linter to yell at people.
  • Loading branch information
MerlinVR committed Mar 19, 2020
1 parent f72479e commit d72ce7b
Showing 1 changed file with 94 additions and 1 deletion.
95 changes: 94 additions & 1 deletion Assets/UdonSharp/Editor/UdonSharpASTVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1939,7 +1939,100 @@ public override void VisitSwitchStatement(SwitchStatementSyntax node)
{
UpdateSyntaxNode(node);

throw new System.NotImplementedException("UdonSharp does not yet support switch statements");
JumpLabel switchExitLabel = visitorContext.labelTable.GetNewJumpLabel("switchStatementExit");

visitorContext.breakLabelStack.Push(switchExitLabel);

SymbolDefinition switchExpressionSymbol = null;
using (ExpressionCaptureScope switchExpressionScope = new ExpressionCaptureScope(visitorContext, null))
{
Visit(node.Expression);
switchExpressionSymbol = switchExpressionScope.ExecuteGet();
}

JumpLabel[] sectionJumps = new JumpLabel[node.Sections.Count];

JumpLabel defaultJump = null;

JumpLabel nextLabelJump = visitorContext.labelTable.GetNewJumpLabel("nextSwitchLabelJump");

// Iterate all the sections and build the condition jumps first
for (int i = 0; i < node.Sections.Count; ++i)
{
SwitchSectionSyntax switchSection = node.Sections[i];
JumpLabel sectionJump = visitorContext.labelTable.GetNewJumpLabel("switchStatmentSectionJump");
sectionJumps[i] = sectionJump;

for (int j = 0; j < switchSection.Labels.Count; ++j)
{
SwitchLabelSyntax switchLabel = switchSection.Labels[j];
SymbolDefinition switchLabelValue = null;

using (ExpressionCaptureScope conditionValueCapture = new ExpressionCaptureScope(visitorContext, null))
{
Visit(switchLabel);

if (!conditionValueCapture.IsUnknownArchetype())
switchLabelValue = conditionValueCapture.ExecuteGet();
}

if (switchLabelValue == null)
{
defaultJump = sectionJump;
continue;
}

visitorContext.uasmBuilder.AddJumpLabel(nextLabelJump);
nextLabelJump = visitorContext.labelTable.GetNewJumpLabel("nextSwitchLabelJump");

SymbolDefinition conditionEqualitySymbol = null;
using (ExpressionCaptureScope equalityCheckScope = new ExpressionCaptureScope(visitorContext, null))
{
List<MethodInfo> operatorMethods = new List<MethodInfo>();
operatorMethods.AddRange(UdonSharpUtils.GetOperators(switchExpressionSymbol.symbolCsType, BuiltinOperatorType.Equality));
operatorMethods.AddRange(GetImplicitHigherPrecisionOperator(switchExpressionSymbol.symbolCsType, switchLabelValue.symbolCsType, BuiltinOperatorType.Equality));
equalityCheckScope.SetToMethods(operatorMethods.ToArray());
conditionEqualitySymbol = equalityCheckScope.Invoke(new SymbolDefinition[] { switchExpressionSymbol, switchLabelValue });
}

// Jump past the jump to the section if false
visitorContext.uasmBuilder.AddJumpIfFalse(nextLabelJump, conditionEqualitySymbol);
visitorContext.uasmBuilder.AddJump(sectionJump);
}
}

visitorContext.uasmBuilder.AddJumpLabel(nextLabelJump);

if (defaultJump != null)
visitorContext.uasmBuilder.AddJump(defaultJump);
else
visitorContext.uasmBuilder.AddJump(switchExitLabel);

// Now fill out the code sections for each condition and resolve the jump labels for each section
for (int i = 0; i < node.Sections.Count; ++i)
{
visitorContext.uasmBuilder.AddJumpLabel(sectionJumps[i]);
foreach (StatementSyntax statment in node.Sections[i].Statements)
{
Visit(statment);
}
}

visitorContext.uasmBuilder.AddJumpLabel(switchExitLabel);
visitorContext.breakLabelStack.Pop();
}

public override void VisitDefaultSwitchLabel(DefaultSwitchLabelSyntax node)
{
// Just do nothing here so the outer scope is unknown type
UpdateSyntaxNode(node);
}

public override void VisitCaseSwitchLabel(CaseSwitchLabelSyntax node)
{
UpdateSyntaxNode(node);

Visit(node.Value);
}

public override void VisitGotoStatement(GotoStatementSyntax node)
Expand Down

0 comments on commit d72ce7b

Please sign in to comment.