public override bool VisitStmtFnCall([NotNull] GamaParser.StmtFnCallContext context) { var fn = VisitExpression(context.expr()); if (!ExpressionCompiler.IsEmptyCall) { var list = ExpressionCompiler.TopCall(); 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 = VisitExpression(exprs[i]); if (val == null) { if (!ExpressionCompiler.IsEmptyCall) { resolver.Resolve(i, ExpressionCompiler.TopCall()); } else { NamespaceContext.Context.AddError(new ErrorInternalExpressionNull(exprs[i])); return(false); } } else { resolver.Resolve(i, val); } } } var resolved = resolver.Resolve(); if (resolved == null) { if (resolver.Remaining.Count == 0) { NamespaceContext.Context.AddError(new ErrorNoViableOverride(context)); return(false); } NamespaceContext.Context.AddError(new ErrorAmbiguousCall(context)); return(false); } if (resolved.IsMethod) // Compiler forgot the provide object reference to method call, check FQMB expression if this happens { if (ExpressionCompiler.Reference == null) { NamespaceContext.Context.AddError(new ErrorInternalObjectRefMethodReq(context)); return(false); } } 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) { NamespaceContext.Context.AddError(new ErrorNoViableOverride(context)); return(false); } if (resolved.IsMethod) { args.Item2[0] = ExpressionCompiler.Reference; } var argsnative = args.Item2.Select(a => a.Value).ToArray(); var fnty = resolved.Type as GamaFunction; /* LLVM */ var block = CurrentBlock; var builder = 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; } } } builder.BuildCall(resolved.Value, argsnative); } else { if (fn == null) { NamespaceContext.Context.AddError(new ErrorInternalExpressionNull(context.expr())); return(false); } if (!(fn is GamaFunctionRef fnref)) { NamespaceContext.Context.AddError(new ErrorNonFunctionCall(context.expr())); return(false); } var fnty = fn.Type as GamaFunction; var argslist = context.exprList(); var argsnative = new LLVMValueRef[0]; if (argslist != null) { var exprs = argslist.expr(); if (exprs.Length != fnty.ParameterTypes.Length) { NamespaceContext.Context.AddError(new ErrorNoViableOverride(argslist)); return(false); } argsnative = new LLVMValueRef[exprs.Length]; for (int i = 0; i < exprs.Length; i++) { ExpressionCompiler.PushTT(fnty.ParameterTypes[i]); var val = VisitExpression(exprs[i]); ExpressionCompiler.PopTT(); if (val == null) { NamespaceContext.Context.AddError(new ErrorInternalExpressionNull(exprs[i])); return(false); } argsnative[i] = val.Value; } } else if (fnty.ParameterTypes.Length != 0) { NamespaceContext.Context.AddError(new ErrorNoViableOverride(context)); return(false); } if (fnref.IsMethod) { if (ExpressionCompiler.Reference == null) { NamespaceContext.Context.AddError(new ErrorInternalObjectRefMethodReq(context)); return(false); } } else { argsnative[0] = ExpressionCompiler.Reference.Value; } /* LLVM */ var block = CurrentBlock; var builder = Builder; block.PositionBuilderAtEnd(builder); builder.BuildCall(fn.Value, argsnative); return(true); } return(true); }
/// <summary> /// Visit a parse tree produced by <see cref="GamaParser.stmtFnCall"/>. /// <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 VisitStmtFnCall([NotNull] GamaParser.StmtFnCallContext context) { return(VisitChildren(context)); }
/// <summary> /// Exit a parse tree produced by <see cref="GamaParser.stmtFnCall"/>. /// <para>The default implementation does nothing.</para> /// </summary> /// <param name="context">The parse tree.</param> public virtual void ExitStmtFnCall([NotNull] GamaParser.StmtFnCallContext context) { }