示例#1
0
        public static string MethodSignature(string type, string name, IMethodInvokeFactory method)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append(type.ToLowerInvariant());
            sb.Append(".");
            sb.Append(name);

            if (method.DeclaredParameters.Count == 0)
            {
                sb.Append(" (");
            }
            else
            {
                sb.Append(" ( ");

                string offset = new String(' ', sb.Length);

                sb.Append(MethodParameterSignature(method.DeclaredParameters.First()));
                foreach (FunctionParameter parameter in method.DeclaredParameters.Skip(1))
                {
                    sb.Append(",\n");
                    sb.Append(offset);
                    sb.Append(MethodParameterSignature(parameter));
                }
            }

            sb.Append(" ) -> ");
            sb.Append(method.DeclaredReturn);

            return(sb.ToString());
        }
示例#2
0
        public override TO2Type ResultType(IBlockContext context)
        {
            TO2Type targetType          = target.ResultType(context);
            IMethodInvokeFactory method = targetType.FindMethod(context.ModuleContext, methodName);

            if (method != null)
            {
                IMethodInvokeEmitter methodInvoker = method.Create(context,
                                                                   arguments.Select(arg => arg.ResultType(context)).ToList(), this);

                if (methodInvoker != null)
                {
                    return(methodInvoker.ResultType);
                }
            }

            IFieldAccessFactory field = targetType.FindField(context.ModuleContext, methodName);

            if (field != null)
            {
                IFieldAccessEmitter fieldAccess  = field.Create(context.ModuleContext);
                FunctionType        functionType = fieldAccess.FieldType as FunctionType;

                if (functionType == null)
                {
                    context.AddError(new StructuralError(
                                         StructuralError.ErrorType.NoSuchMethod,
                                         $"Field '{methodName}' of type '{targetType.Name}' is neither a method or a function",
                                         Start,
                                         End
                                         ));
                    return(BuiltinType.Unit);
                }
                else
                {
                    return(functionType.returnType);
                }
            }

            context.AddError(new StructuralError(
                                 StructuralError.ErrorType.NoSuchMethod,
                                 $"Type '{targetType.Name}' does not have a method or field '{methodName}'",
                                 Start,
                                 End
                                 ));
            return(BuiltinType.Unit);
        }
示例#3
0
        public MethodCall(Expression target, string methodName, List <Expression> arguments,
                          Position start = new Position(), Position end = new Position()) : base(start, end)
        {
            this.target     = target;
            this.methodName = methodName;
            this.arguments  = arguments;
            for (int j = 0; j < this.arguments.Count; j++)
            {
                int i = j; // Copy for lambda
                this.arguments[i].TypeHint = context => {
                    TO2Type targetType = this.target.ResultType(context);
                    IMethodInvokeFactory methodInvoker = targetType.FindMethod(context.ModuleContext, this.methodName);

                    return(methodInvoker?.ArgumentHint(i)?.Invoke(context));
                };
            }
        }
示例#4
0
        public override void EmitCode(IBlockContext context, bool dropResult)
        {
            if (preparedResult != null)
            {
                if (!dropResult)
                {
                    preparedResult.EmitLoad(context);
                }
                preparedResult = null;
                return;
            }

            TO2Type targetType          = target.ResultType(context);
            IMethodInvokeFactory method = targetType.FindMethod(context.ModuleContext, methodName);

            if (method != null)
            {
                EmitCodeMethodCall(context, targetType, method, dropResult);
                return;
            }

            IFieldAccessFactory field = targetType.FindField(context.ModuleContext, methodName);

            if (field != null)
            {
                EmitCodeDelegateCall(context, targetType, field, dropResult);
                return;
            }

            context.AddError(new StructuralError(
                                 StructuralError.ErrorType.NoSuchMethod,
                                 $"Type '{targetType.Name}' does not have a method or field '{methodName}'",
                                 Start,
                                 End
                                 ));
        }
 public void AddMethod(string name, IMethodInvokeFactory methodInvokeFactory) =>
 realizedType.DeclaredMethods.Add(name, methodInvokeFactory);
示例#6
0
        private void EmitCodeMethodCall(IBlockContext context, TO2Type targetType, IMethodInvokeFactory method,
                                        bool dropResult)
        {
            if (target is IAssignContext assignContext)
            {
                if (assignContext.IsConst(context) && !method.IsConst)
                {
                    context.AddError(new StructuralError(
                                         StructuralError.ErrorType.NoSuchMethod,
                                         $"Method '{methodName}' will mutate const variable.",
                                         Start,
                                         End
                                         ));
                }
            }

            List <TO2Type>       argumentTypes = arguments.Select(arg => arg.ResultType(context)).ToList();
            IMethodInvokeEmitter methodInvoker = method.Create(context, argumentTypes, this);

            if (methodInvoker == null)
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.NoSuchMethod,
                                     $"Type '{targetType.Name}' does not have a method '{methodName}' matching arguments ({string.Join(", ", argumentTypes)})",
                                     Start,
                                     End
                                     ));
                return;
            }

            if (methodInvoker.IsAsync && !context.IsAsync)
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.NoSuchFunction,
                                     $"Cannot call async method of variable '{targetType.Name}.{methodName}' from a sync context",
                                     Start,
                                     End
                                     ));
                return;
            }

            if (methodInvoker.RequiredParameterCount() > arguments.Count)
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.ArgumentMismatch,
                                     $"Method '{targetType.Name}.{methodName}' requires {methodInvoker.RequiredParameterCount()} arguments",
                                     Start,
                                     End
                                     ));
                return;
            }

            int i;

            for (i = 0; i < arguments.Count; i++)
            {
                TO2Type argumentType = arguments[i].ResultType(context);
                if (!methodInvoker.Parameters[i].type.IsAssignableFrom(context.ModuleContext, argumentType))
                {
                    context.AddError(new StructuralError(
                                         StructuralError.ErrorType.ArgumentMismatch,
                                         $"Argument {methodInvoker.Parameters[i].name} of '{targetType.Name}.{methodName}' has to be a {methodInvoker.Parameters[i].type}, but got {argumentType}",
                                         Start,
                                         End
                                         ));
                    return;
                }
            }

            foreach (Expression argument in arguments)
            {
                argument.Prepare(context);
            }

            if (methodInvoker.RequiresPtr)
            {
                target.EmitPtr(context);
            }
            else
            {
                target.EmitCode(context, false);
            }
            for (i = 0; i < arguments.Count; i++)
            {
                arguments[i].EmitCode(context, false);
                if (!context.HasErrors)
                {
                    methodInvoker.Parameters[i].type.AssignFrom(context.ModuleContext, arguments[i].ResultType(context))
                    .EmitConvert(context);
                }
            }

            if (!context.HasErrors)
            {
                for (; i < methodInvoker.Parameters.Count; i++)
                {
                    methodInvoker.Parameters[i].defaultValue.EmitCode(context);
                }
            }

            if (context.HasErrors)
            {
                return;
            }

            methodInvoker.EmitCode(context);
            if (methodInvoker.IsAsync)
            {
                context.RegisterAsyncResume(methodInvoker.ResultType);
            }
            if (dropResult)
            {
                context.IL.Emit(OpCodes.Pop);
            }
        }