public override void ExitUnaryExpr(GoParser.UnaryExprContext context) { // unaryExpr // : primaryExpr // | ('+' | '-' | '!' | '^' | '*' | '&' | '<-') expression if (PrimaryExpressions.TryGetValue(context.primaryExpr(), out string primaryExpression)) { UnaryExpressions[context] = primaryExpression; } else if (context.expression() != null) { string unaryOP = context.children[0].GetText(); if (unaryOP.Equals("^", StringComparison.Ordinal)) { unaryOP = "~"; } else if (unaryOP.Equals("<-", StringComparison.Ordinal)) { // TODO: Handle channel value access (update when channel class is created): unaryOP = null; UnaryExpressions[context] = $"{Expressions[context.expression()]}.Receive()"; } else if (unaryOP.Equals("&", StringComparison.Ordinal)) { // TODO: Handle pointer acquisition context - may need to augment pre-scan metadata for heap allocation notation unaryOP = null; UnaryExpressions[context] = $"ref {Expressions[context.expression()]}"; } else if (unaryOP.Equals("*", StringComparison.Ordinal)) { // TODO: Handle pointer dereference context - if this is a ref variable, Deref call is unnecessary unaryOP = null; UnaryExpressions[context] = $"{Expressions[context.expression()]}.Deref"; } if ((object)unaryOP != null) { UnaryExpressions[context] = $"{unaryOP}{Expressions[context.expression()]}"; } } else if (!UnaryExpressions.ContainsKey(context)) { AddWarning(context, $"Unexpected unary expression \"{context.GetText()}\""); } }
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; } }