Ejemplo n.º 1
0
        protected override void EmitAssignToPtr(IBlockContext context, IBlockVariable tempSource)
        {
            foreach (var kv in targetType.fields)
            {
                IFieldAccessFactory sourceFieldFactory = sourceType.FindField(context.ModuleContext, kv.Key);
                if (sourceFieldFactory == null)
                {
                    continue;
                }

                IFieldAccessEmitter sourceField = sourceFieldFactory.Create(context.ModuleContext);
                context.IL.Emit(OpCodes.Dup);
                if (sourceField.RequiresPtr)
                {
                    tempSource.EmitLoadPtr(context);
                }
                else
                {
                    tempSource.EmitLoad(context);
                }
                sourceField.EmitLoad(context);
                targetType.ItemTypes[kv.Key].AssignFrom(context.ModuleContext, sourceType.ItemTypes[kv.Key])
                .EmitConvert(context);
                context.IL.Emit(OpCodes.Stfld, kv.Value);
            }

            context.IL.Emit(OpCodes.Pop);
        }
Ejemplo n.º 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);
        }
Ejemplo n.º 3
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
                                 ));
        }
Ejemplo n.º 4
0
        private void EmitCodeDelegateCall(IBlockContext context, TO2Type targetType, IFieldAccessFactory field,
                                          bool dropResult)
        {
            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;
            }

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

            if (functionType.parameterTypes.Count != arguments.Count)
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.ArgumentMismatch,
                                     $"Call to '{methodName}' of type '{targetType.Name}' requires {functionType.parameterTypes.Count} arguments",
                                     Start,
                                     End
                                     ));
                return;
            }

            if (fieldAccess.RequiresPtr)
            {
                target.EmitPtr(context);
            }
            else
            {
                target.EmitCode(context, false);
            }
            fieldAccess.EmitLoad(context);

            for (int i = 0; i < arguments.Count; i++)
            {
                arguments[i].EmitCode(context, false);
                if (!context.HasErrors)
                {
                    functionType.parameterTypes[i].AssignFrom(context.ModuleContext, arguments[i].ResultType(context))
                    .EmitConvert(context);
                }
            }

            if (context.HasErrors)
            {
                return;
            }

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

            MethodInfo invokeMethod = functionType.GeneratedType(context.ModuleContext).GetMethod("Invoke") ??
                                      throw new ArgumentException($"No Invoke method in generated ${functionType}");

            context.IL.EmitCall(OpCodes.Callvirt, invokeMethod, arguments.Count + 1);
            if (functionType.isAsync)
            {
                context.RegisterAsyncResume(functionType.returnType);
            }
            if (dropResult && invokeMethod.ReturnType != typeof(void))
            {
                context.IL.Emit(OpCodes.Pop);
            }
            if (!dropResult && invokeMethod.ReturnType == typeof(void))
            {
                context.IL.Emit(OpCodes.Ldnull);
            }
        }