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--;
        }
Example #2
0
        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
                };
            }
        }
Example #3
0
        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;
            }
        }