public override void ExitTypeSwitchStmt(GoParser.TypeSwitchStmtContext context) { // typeSwitchStmt // : 'switch'(simpleStmt ';') ? typeSwitchGuard '{' typeCaseClause * '}' // typeSwitchGuard // : ( IDENTIFIER ':=' )? primaryExpr '.' '(' 'type' ')' // Default case always needs to be last case clause in SwitchExpression - Go allows its declaration anywhere m_targetFile.Append($"{m_typeSwitchDefaultCase.Pop()}{CheckForCommentsRight(context)}"); if (PrimaryExpressions.TryGetValue(context.typeSwitchGuard().primaryExpr(), out ExpressionInfo expression)) { // Replace type switch expression marker m_targetFile.Replace(string.Format(TypeSwitchExpressionMarker, m_typeSwitchExpressionLevel), $"{expression.Text}.type()"); } else { AddWarning(context, $"Failed to find primary expression for type switch statement: {context.typeSwitchGuard().GetText()}"); } if (!(context.simpleStmt() is null) && context.simpleStmt().emptyStmt() is null) { if (m_simpleStatements.TryGetValue(context.simpleStmt(), out string statement)) { m_targetFile.Replace(string.Format(TypeSwitchStatementMarker, m_typeSwitchExpressionLevel), $"{statement}{Environment.NewLine}"); } else { AddWarning(context, $"Failed to find simple statement for type switch statement: {context.simpleStmt().GetText()}"); } // Close any locally scoped declared variable sub-block if (!(context.simpleStmt().shortVarDecl() is null)) { // Handle restoration of previous values of any redeclared variables m_targetFile.Append(CloseRedeclaredVariableBlock(context.simpleStmt().shortVarDecl().identifierList(), m_typeSwitchExpressionLevel)); IndentLevel--; m_targetFile.AppendLine(); m_targetFile.Append($"{Spacing()}}}"); } } IndentLevel--; m_targetFile.Append($"{Spacing()}}}{CheckForCommentsRight(context)}"); m_typeSwitchExpressionLevel--; }
public override void ExitUnaryExpr(GoParser.UnaryExprContext context) { base.ExitUnaryExpr(context); if (!InFunction || !(context.primaryExpr() is null) && PrimaryExpressions.ContainsKey(context.primaryExpr()) || context.expression() is null || !Expressions.TryGetValue(context.expression(), out ExpressionInfo expression)) { return; } ParameterInfo[] parameters = CurrentFunction.Signature.Signature.Parameters; string unaryOP = context.children[0].GetText(); if (!unaryOP.Equals("*", StringComparison.Ordinal)) { return; } ParameterInfo pointerParam = parameters.FirstOrDefault(parameter => parameter.Name.Equals(expression.Text)); if (!(pointerParam is null) && pointerParam.Type is PointerTypeInfo pointer) { TypeInfo targetType = pointer.TargetTypeInfo.Clone(); targetType.IsByRefPointer = true; string derefPointerExpression = expression.Text; // Handle pointer-to-pointer dereferencing int derefs = pointer.Name.Count(chr => chr == '*'); if (derefs > 1) { for (int i = 1; i < derefs; i++) { derefPointerExpression += ".val"; } } // Implicitly dereference pointer parameter when dereference operator (*) is used UnaryExpressions[context] = new ExpressionInfo { Text = derefPointerExpression, Type = targetType }; } }
public override void ExitUnaryExpr(GoParser.UnaryExprContext context) { base.ExitUnaryExpr(context); ExpressionInfo expression = null; if (!(context.primaryExpr() is null) && !PrimaryExpressions.ContainsKey(context.primaryExpr()) || !(context.expression() is null) && !Expressions.TryGetValue(context.expression(), out expression) || expression is null) { return; } // Taking the address of a variable means making a stack variable heap allocated if (context.children[0].GetText().Equals("&", StringComparison.Ordinal) && m_variables.TryGetValue(expression.Text, out VariableInfo variable)) { variable.HeapAllocated = true; } }