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)); } }
/// <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)); }
/// <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) { }