Example #1
0
        private static bool TryCompileCall(FunctionCallSyntax call, CompiledMethod method, BasicBlockBuilder builder,
                                           IDiagnosticSink diagnostics, INameResolver nameResolver, out Temporary value)
        {
            value = default;

            // Get the callee
            var matchingMethods = nameResolver.ResolveMethod(call.Function.Name);

            if (matchingMethods.Count == 0)
            {
                diagnostics.Add(DiagnosticCode.MethodNotFound, call.Function.Position, call.Function.Name);
                return(false);
            }
            else if (matchingMethods.Count > 1)
            {
                // TODO: Test this case
                throw new NotImplementedException("Multiple matching methods");
            }
            var declaration = matchingMethods[0];

            // Assert that there is the right number of parameters
            if (call.Parameters.Count != declaration.ParameterTypes.Count)
            {
                diagnostics.Add(DiagnosticCode.ParameterCountMismatch, call.Position,
                                actual: call.Parameters.Count.ToString(), expected: declaration.ParameterTypes.Count.ToString());
                return(false);
            }

            // Evaluate the parameters, verifying their types
            var parameterIndices = new int[declaration.ParameterTypes.Count];

            for (var i = 0; i < parameterIndices.Length; i++)
            {
                var paramIndex = TryCompileExpression(call.Parameters[i], declaration.ParameterTypes[i],
                                                      method, builder, nameResolver, diagnostics);

                // If the compilation of the expression failed for some reason, the diagnostic is already logged
                if (paramIndex == -1)
                {
                    return(false);
                }
                parameterIndices[i] = paramIndex;
            }

            // Emit a call operation
            var callType = declaration is ImportedMethodDeclaration ? MethodCallType.Imported : MethodCallType.Native;

            var callInfoIndex = method.AddCallInfo(declaration.BodyIndex, parameterIndices, declaration.FullName, callType);
            var resultIndex   = method.AddLocal(declaration.ReturnType, LocalFlags.None);

            builder.AppendInstruction(Opcode.Call, callInfoIndex, 0, resultIndex);

            value = Temporary.FromLocal(declaration.ReturnType, resultIndex);
            return(true);
        }