示例#1
0
        public override TO2Type ResultType(IBlockContext context)
        {
            TO2Type             targetType  = target.ResultType(context);
            IFieldAccessEmitter fieldAccess =
                targetType.FindField(context.ModuleContext, fieldName)?.Create(context.ModuleContext);

            if (fieldAccess == null)
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.NoSuchField,
                                     $"Type '{targetType.Name}' does not have a field '{fieldName}'",
                                     Start,
                                     End
                                     ));
                return(BuiltinType.Unit);
            }

            if (!fieldAccess.CanStore)
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.NoSuchField,
                                     $"Type '{targetType.Name}' field '{fieldName}' is read-only",
                                     Start,
                                     End
                                     ));
                return(BuiltinType.Unit);
            }

            return(fieldAccess.FieldType);
        }
示例#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 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
                                 ));
        }
示例#4
0
        public override void EmitCode(IBlockContext context, bool dropResult)
        {
            TO2Type             targetType  = target.ResultType(context);
            IFieldAccessEmitter fieldAccess =
                targetType.FindField(context.ModuleContext, fieldName)?.Create(context.ModuleContext);
            TO2Type valueType = expression.ResultType(context);

            if (fieldAccess == null)
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.NoSuchField,
                                     $"Type '{targetType.Name}' does not have a field '{fieldName}'",
                                     Start,
                                     End
                                     ));
                return;
            }

            if (!fieldAccess.CanStore)
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.NoSuchField,
                                     $"Type '{targetType.Name}' field '{fieldName}' is read-only",
                                     Start,
                                     End
                                     ));
                return;
            }

            if (target is IAssignContext assignContext)
            {
                if (fieldAccess.RequiresPtr && assignContext.IsConst(context))
                {
                    context.AddError(new StructuralError(
                                         StructuralError.ErrorType.NoSuchField,
                                         $"Type '{targetType.Name}' field '{fieldName}' can not be set on a read-only variable",
                                         Start,
                                         End
                                         ));
                    return;
                }
            }
            else
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.CoreGeneration,
                                     $"Field assign '{targetType.Name}'.'{fieldName}' on invalid target expression",
                                     Start,
                                     End
                                     ));
                return;
            }

            if (!fieldAccess.FieldType.IsAssignableFrom(context.ModuleContext, valueType))
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.IncompatibleTypes,
                                     $"Type '{targetType.Name}' field '{fieldName}' is of type {fieldAccess.FieldType} but is assigned to {valueType}",
                                     Start,
                                     End
                                     ));
                return;
            }

            if (op == Operator.Assign)
            {
                if (fieldAccess.RequiresPtr)
                {
                    target.EmitPtr(context);
                }
                else
                {
                    target.EmitCode(context, false);
                }

                if (context.HasErrors)
                {
                    return;
                }

                expression.EmitCode(context, false);
                fieldAccess.FieldType.AssignFrom(context.ModuleContext, valueType).EmitConvert(context);

                if (!dropResult)
                {
                    using ITempBlockVariable tmpResult = context.MakeTempVariable(fieldAccess.FieldType);

                    context.IL.Emit(OpCodes.Dup);
                    tmpResult.EmitStore(context);

                    fieldAccess.EmitStore(context);

                    tmpResult.EmitLoad(context);
                }
                else
                {
                    fieldAccess.EmitStore(context);
                }
            }
            else
            {
                IOperatorEmitter operatorEmitter = fieldAccess.FieldType.AllowedSuffixOperators(context.ModuleContext)
                                                   .GetMatching(context.ModuleContext, op, valueType);

                if (operatorEmitter == null)
                {
                    context.AddError(new StructuralError(
                                         StructuralError.ErrorType.IncompatibleTypes,
                                         $"Type '{targetType.Name}' field '{fieldName}': Cannot {op} a {fieldAccess.FieldType} with a {valueType}",
                                         Start,
                                         End
                                         ));
                    return;
                }

                expression.Prepare(context);

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

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

                if (context.HasErrors)
                {
                    return;
                }

                fieldAccess.EmitLoad(context);
                expression.EmitCode(context, false);
                operatorEmitter.OtherType.AssignFrom(context.ModuleContext, valueType).EmitConvert(context);
                operatorEmitter.EmitCode(context, this);

                if (!dropResult)
                {
                    using ITempBlockVariable tmpResult = context.MakeTempVariable(fieldAccess.FieldType);

                    context.IL.Emit(OpCodes.Dup);
                    tmpResult.EmitStore(context);

                    fieldAccess.EmitStore(context);

                    tmpResult.EmitLoad(context);
                }
                else
                {
                    fieldAccess.EmitStore(context);
                }
            }
        }
示例#5
0
 public override IFieldAccessFactory FindField(ModuleContext context, string fieldName) =>
 aliasedType.FindField(declaredModule, fieldName);