public override GamaValueRef VisitExprCall([NotNull] GamaParser.ExprCallContext context)
        {
            var fn = Visit(context.expr());

            if (!IsEmptyCall)
            {
                var list     = PopCall();
                var resolver = new GamaFunctionResolver(list);

                var argslist = context.exprList();

                if (argslist != null)
                {
                    var exprs = argslist.expr();

                    for (int i = 0; i < exprs.Length; i++)
                    {
                        var val = Visit(exprs[i]);
                        if (val == null)
                        {
                            if (!IsEmptyCall)
                            {
                                resolver.Resolve(i, PopCall());
                            }
                            else
                            {
                                return(null);
                            }
                        }
                        else
                        {
                            resolver.Resolve(i, val);
                        }
                    }
                }

                var resolved = resolver.Resolve();
                if (resolved == null)
                {
                    if (resolver.Remaining.Count == 0)
                    {
                        Parent.NamespaceContext.Context.AddError(new ErrorNoViableOverride(context));
                        return(null);
                    }

                    Parent.NamespaceContext.Context.AddError(new ErrorAmbiguousCall(context));
                    return(null);
                }

                if (resolved.IsMethod)
                {
                    if (Reference == null) // Compiler forgot the provide object reference to method call, check FQMB expression if this happens
                    {
                        Parent.NamespaceContext.Context.AddError(new ErrorInternalObjectRefMethodReq(context));
                        return(null);
                    }
                }

                if (resolved.HasAttribute("obsolete"))
                {
                    Console.WriteLine("Function '{0}' is marked as obsolete, this method should be avoided", context.expr().GetText());
                }

                var args = resolver.ResolveArgs();
                if (args.Item1 != GamaFunctionResolver.ArgResolveStatus.Success)
                {
                    Parent.NamespaceContext.Context.AddError(new ErrorNoViableOverride(context));
                    return(null);
                }

                if (resolved.IsMethod)
                {
                    args.Item2[0] = Reference;
                }

                var argsnative = args.Item2.Select(a => a.Value).ToArray();
                var fnty       = resolved.Type as GamaFunction;

                /* LLVM */
                var block   = Parent.CurrentBlock;
                var builder = Parent.Builder;
                block.PositionBuilderAtEnd(builder);

                if (fnty.IsVarArg)
                {
                    for (int i = resolved.Parameters.Count; i < argsnative.Length; i++)
                    {
                        var arg = argsnative[i];
                        // C11 n1570 6.5.2.2.6; varargs promote floats to doubles
                        if (args.Item2[i].Type == InstanceTypes.F32) // promotion needed
                        {
                            var trunc = builder.BuildFPExt(argsnative[i], InstanceTypes.F64.UnderlyingType);
                            argsnative[i] = trunc;
                        }
                    }
                }

                var result = builder.BuildCall(resolved.Value, argsnative);

                return(new GamaValueRef(resolved.ReturnType, result, false));
            }
            else
            {
                if (fn == null)
                {
                    return(null);
                }

                var fnref = fn as GamaFunctionRef;
                if (!(fn.Type is GamaFunction fnty))
                {
                    Parent.NamespaceContext.Context.AddError(new ErrorNonFunctionCall(context.expr()));
                    return(null);
                }

                var start      = fnref.IsMethod ? 1 : 0;
                var argslist   = context.exprList();
                var argsnative = new LLVMValueRef[0 + start];

                if (argslist != null)
                {
                    var exprs = argslist.expr();
                    if (exprs.Length != fnty.ParameterTypes.Length)
                    {
                        Parent.NamespaceContext.Context.AddError(new ErrorNoViableOverride(argslist));
                        return(null);
                    }

                    argsnative = new LLVMValueRef[exprs.Length + start];

                    for (int i = start; i < exprs.Length; i++)
                    {
                        PushTT(fnty.ParameterTypes[i]);
                        var val = Visit(exprs[i - start]);
                        PopTT();
                        if (val == null)
                        {
                            return(null);
                        }
                        argsnative[i] = val.Value;
                    }
                }
                else if (fnty.ParameterTypes.Length != 0)
                {
                    Parent.NamespaceContext.Context.AddError(new ErrorNoViableOverride(context));
                    return(null);
                }

                if (fnref.IsMethod)
                {
                    if (Reference == null)
                    {
                        Parent.NamespaceContext.Context.AddError(new ErrorInternalObjectRefMethodReq(context));
                        return(null);
                    }
                }
                else
                {
                    argsnative[0] = Reference.Value;
                }

                /* LLVM */
                var block   = Parent.CurrentBlock;
                var builder = Parent.Builder;
                block.PositionBuilderAtEnd(builder);
                var result = builder.BuildCall(fn.Value, argsnative);

                return(new GamaValueRef(fnty.ReturnType, result, false));
            }
        }
Beispiel #2
0
 /// <summary>
 /// Visit a parse tree produced by the <c>ExprCall</c>
 /// labeled alternative in <see cref="GamaParser.expr"/>.
 /// <para>
 /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
 /// on <paramref name="context"/>.
 /// </para>
 /// </summary>
 /// <param name="context">The parse tree.</param>
 /// <return>The visitor result.</return>
 public virtual Result VisitExprCall([NotNull] GamaParser.ExprCallContext context)
 {
     return(VisitChildren(context));
 }
Beispiel #3
0
 /// <summary>
 /// Exit a parse tree produced by the <c>ExprCall</c>
 /// labeled alternative in <see cref="GamaParser.expr"/>.
 /// <para>The default implementation does nothing.</para>
 /// </summary>
 /// <param name="context">The parse tree.</param>
 public virtual void ExitExprCall([NotNull] GamaParser.ExprCallContext context)
 {
 }