Exemple #1
0
        Statement CreateBuildError(Source src, bool isError, AstExpression value = null)
        {
            var type = "build_" + (isError
                                    ? "error"
                                    : "warning");

            if (!IsFunctionScope)
            {
                return(Error(src, ErrorCode.E0000, type.Quote() + " can only be used in methods"));
            }

            var message = value != null
                    ? Compiler.CompileConstant(value, Namescope, Essentials.String).Value as string ??
                          "<invalid>"
                    : Function.Quote() + " does not support this build target";

            if (isError)
            {
                /*if (!Compiler.Backend.IsDefault)
                 *  Log.Error(s.Source, ErrorCode.E0000, message);*/
                return(new Throw(src,
                                 ILFactory.NewObject(src, Essentials.Exception,
                                                     new Constant(src, Essentials.String, type + ": " + message))));
            }

            if (!Compiler.Backend.IsDefault)
            {
                Log.Warning(src, ErrorCode.W0000, type + ": " + message);
            }
            return(new NoOp(src, message));
        }
Exemple #2
0
        Field GetField(Draw draw)
        {
            var prog = GetProgram(draw);
            var key  = Type + ":" + prog;

            Field result;

            if (!_fields.TryGetValue(key, out result))
            {
                var src        = draw.Source;
                var initMethod = Type.TryGetMethod("init_DrawCalls", false);

                if (initMethod == null)
                {
                    throw new SourceException(src, "No 'init_DrawCalls()' method was found in " + Type.Quote());
                }

                var dc = ILFactory.NewObject(src, "Uno.Graphics.OpenGL.GLDrawCall", prog);
                result = new Field(src, Type, "_draw_" + draw.State.Path.Suffix, null, Modifiers.Private | Modifiers.Generated, 0, dc.ReturnType);
                initMethod.Body.Statements.Add(new StoreField(src, new This(src, Type), result, dc));
                Type.Fields.Add(result);
                _fields.Add(key, result);
            }

            return(result);
        }
Exemple #3
0
        Expression ProcessVertexBuffer(StageValue vertexBuffer)
        {
            Expression result;

            if (!VertexBuffers.TryGetValue(vertexBuffer.Value.ToString(), out result))
            {
                var src  = vertexBuffer.Value.Source;
                var type = ILFactory.GetType(src, "Uno.Graphics.VertexBuffer");

                if (vertexBuffer.Value.ReturnType.Equals(type))
                {
                    result = ProcessStage(vertexBuffer, MetaStage.Volatile, MetaStage.Volatile).Value;
                    VertexBuffers.Add(vertexBuffer.Value.ToString(), result);
                    return(result);
                }

                var loc = LocationStack.Last();
                var mp  = GetProperty(loc);

                var name  = CreateFieldName(mp, loc);
                var owner = Path.DrawBlock.Method.DeclaringType;

                var field = new Field(src, owner, name, null, Modifiers.Private | Modifiers.Generated, 0, type);
                owner.Fields.Add(field);

                result = new LoadField(src, new This(src, owner), field);
                VertexBuffers.Add(vertexBuffer.Value.ToString(), result);

                if (vertexBuffer.MinStage > MetaStage.Volatile)
                {
                    Log.Error(src, ErrorCode.E5025, "Vertex buffer cannot be accessed from " + vertexBuffer.MinStage + " stage");
                    return(result);
                }
                else if (vertexBuffer.MinStage == MetaStage.Volatile)
                {
                    InitScope.Statements.Add(
                        new StoreField(src, new This(src, owner), field,
                                       ILFactory.NewObject(src, "Uno.Graphics.VertexBuffer",
                                                           ILFactory.GetExpression(src, "Uno.Graphics.BufferUsage.Dynamic"))));

                    FrameScope.Statements.Add(
                        ILFactory.CallMethod(src, new LoadField(src, new This(src, owner), field), "Update",
                                             vertexBuffer.Value));
                }
                else
                {
                    InitScope.Statements.Add(
                        new StoreField(src, new This(src, owner), field,
                                       ILFactory.NewObject(src, "Uno.Graphics.VertexBuffer",
                                                           vertexBuffer.Value,
                                                           ILFactory.GetExpression(src, "Uno.Graphics.BufferUsage.Immutable"))));
                }

                FreeScope.Statements.Add(
                    ILFactory.CallMethod(src, new LoadField(src, new This(src, owner), field), "Dispose"));
            }

            return(result);
        }
Exemple #4
0
        private void RegisterTestMethods()
        {
            var registryObject   = ILFactory.NewObject(_source, _testRegistryType);
            var registryVariable = new Variable(_source, _mainConstructor, "registry", _testRegistryType, VariableType.Default, registryObject);
            var body             = new Scope(_source);

            body.Statements.Add(new CallConstructor(_source, _appClass.Constructors[0]));
            body.Statements.Add(new VariableDeclaration(registryVariable));

            var methods = _methods;

            if (_testOptions.Filter != null)
            {
                var regex = new Regex(_testOptions.Filter, RegexOptions.CultureInvariant);
                methods = methods.Where(m => regex.IsMatch(m.FullName)).ToList();
            }

            methods.Sort((a, b) => string.Compare(a.FullName, b.FullName, StringComparison.InvariantCultureIgnoreCase));

            var ret = new List <TestMethod>();

            foreach (var method in methods)
            {
                var testMethod      = CreateTestMethod(method);
                var invokerMethod   = CreateInvoker(method);
                var invokerInstance = InstantiateTestFixture(invokerMethod);
                var testExpression  = RegisterTest(testMethod,
                                                   new LoadLocal(_source, registryVariable),
                                                   new NewDelegate(_source, _actionType,
                                                                   invokerInstance, invokerMethod));

                body.Statements.Add(testExpression);
                ret.Add(testMethod);
            }

            var registryExpr          = new LoadLocal(_source, registryVariable);
            var testSetupConstruction = ILFactory.NewObject(_source, _testSetupType, registryExpr);

            body.Statements.Add(new StoreField(_source, new This(_source, _mainClass), _testSetupField, testSetupConstruction));

            _mainConstructor.SetBody(body);
        }
Exemple #5
0
        Closure CreateClosure(Closure parent, HashSet <Variable> locals)
        {
            if (parent != null && locals.Count == 0)
            {
                return(parent);
            }

            var type = new ClassType(
                Source.Unknown,
                Function.DeclaringType,
                Function.Name + " lambda closure",
                Modifiers.Private | Modifiers.Generated,
                Function.DeclaringType.GetUniqueIdentifier(Function.Name + "_$closure"));

            type.SetBase(Essentials.Object);

            var constrBody = new Scope(
                Source.Unknown,
                new CallConstructor(Source.Unknown, Essentials.Object.TryGetConstructor()));

            type.Constructors.Add(
                new Constructor(
                    Source.Unknown,
                    type,
                    "",
                    Modifiers.Public | Modifiers.Generated,
                    ParameterList.Empty,
                    constrBody));

            Function.DeclaringType.NestedTypes.Add(type);
            _generatedTypes.Add(type);

            var decl = new VariableDeclaration(
                Source.Unknown,
                Function,
                Function.DeclaringType.GetUniqueIdentifier("generated_closure"),
                type,
                optionalValue: ILFactory.NewObject(type));

            var statements = new List <Statement>();

            statements.Add(decl);

            var result = new Closure(type, statements, new LoadLocal(Source.Unknown, decl.Variable), parent);

            // The root closure gets 'this' and the params
            if (parent == null)
            {
                if (_closureVars.This)
                {
                    var field = new Field(
                        Source.Unknown,
                        type,
                        type.GetUniqueIdentifier("self"),
                        "",
                        Modifiers.Public | Modifiers.Generated,
                        0,
                        Function.DeclaringType);

                    type.Fields.Add(field);

                    statements.Add(result.StoreThis(new This(Function.DeclaringType)));
                }

                foreach (var p in _closureVars.Params)
                {
                    var field = new Field(
                        p.Source,
                        type,
                        type.GetUniqueIdentifier(p.Name),
                        "",
                        Modifiers.Public | Modifiers.Generated,
                        0,
                        p.Type);

                    type.Fields.Add(field);
                    result.ParameterFields[p] = field;
                    statements.Add(result.Store(p, new LoadArgument(Source.Unknown, Function, ParamIndex(p))));
                }
            }
            // Non-root closures get a parent field for the parent closure
            else
            {
                type.Fields.Add(
                    new Field(
                        Source.Unknown,
                        type,
                        type.GetUniqueIdentifier("parent"),
                        "",
                        Modifiers.Public | Modifiers.Generated,
                        0,
                        parent.Type));
                statements.Add(result.StoreParent(parent.Expression));
            }

            foreach (var v in locals)
            {
                var field = new Field(
                    v.Source,
                    type,
                    type.GetUniqueIdentifier(v.Name),
                    "",
                    Modifiers.Public | Modifiers.Generated,
                    0,
                    v.ValueType);

                type.Fields.Add(field);
                result.VariableFields[v] = field;
            }

            return(result);
        }
Exemple #6
0
        void ProcessIndexBuffer(Source vaSrc, StageValue indexBuffer, StageValue indexType)
        {
            if (IndexBuffer == null && indexBuffer.Value == null && IndexType == null && indexType.Value == null ||
                indexBuffer.Value != null && IndexBuffer == indexBuffer.Value.ToString() && indexType.Value != null && IndexType == indexType.Value.ToString())
            {
                // OK
                return;
            }

            if (IndexBuffer != null || indexBuffer.Value == null || IndexType != null || indexType.Value == null)
            {
                Log.Error(vaSrc, ErrorCode.E5023, "Index buffer argument must be consistent for all <vertex_attrib>s in " + Path.Quote());
                return;
            }

            var src  = indexBuffer.Value.Source;
            var type = ILFactory.GetType(src, "Uno.Graphics.IndexBuffer");

            IndexBuffer = indexBuffer.Value.ToString();
            IndexType   = indexType.Value.ToString();

            if (indexBuffer.Value.ReturnType.Equals(type))
            {
                DrawState.OptionalIndices = new IndexBinding(
                    ProcessStage(indexType, MetaStage.Volatile, MetaStage.Volatile).Value,
                    ProcessStage(indexBuffer, MetaStage.Volatile, MetaStage.Volatile).Value);

                return;
            }

            var loc = LocationStack.Last();
            var mp  = GetProperty(loc);

            var name  = CreateFieldName(mp, loc);
            var owner = Path.DrawBlock.Method.DeclaringType;

            var field = new Field(src, owner, name,
                                  null, Modifiers.Private | Modifiers.Generated, 0, type);

            owner.Fields.Add(field);

            DrawState.OptionalIndices = new IndexBinding(
                ProcessStage(indexType, MetaStage.Volatile, MetaStage.Volatile).Value,
                new LoadField(src, new This(src, owner), field));

            if (indexBuffer.MinStage > MetaStage.Volatile)
            {
                Log.Error(src, ErrorCode.E5024, "Index buffer cannot be accessed from " + indexBuffer.MinStage + " stage");
                return;
            }

            if (indexBuffer.MinStage == MetaStage.Volatile)
            {
                InitScope.Statements.Add(
                    new StoreField(src, new This(src, owner), field,
                                   ILFactory.NewObject(src, "Uno.Graphics.IndexBuffer",
                                                       ILFactory.GetExpression(src, "Uno.Graphics.BufferUsage.Dynamic"))));

                FrameScope.Statements.Add(
                    ILFactory.CallMethod(src, new LoadField(src, new This(src, owner), field), "Update",
                                         indexBuffer.Value));
            }
            else
            {
                InitScope.Statements.Add(
                    new StoreField(src, new This(src, owner), field, ILFactory.NewObject(src, "Uno.Graphics.IndexBuffer",
                                                                                         indexBuffer.Value,
                                                                                         ILFactory.GetExpression(src, "Uno.Graphics.BufferUsage.Immutable"))));
            }

            FreeScope.Statements.Add(
                ILFactory.CallMethod(src, new LoadField(src, new This(src, owner), field), "Dispose"));
        }
        Expression TryCompileImplicitCast(Source src, DataType expectedType, Expression value, bool reportErrorIfNotFound)
        {
            if (ImplicitCastStack.Contains(expectedType))
            {
                ImplicitCastStack.Add(expectedType);
            }
            else
            {
                ImplicitCastStack.Add(expectedType);

                if (Equals(expectedType, value.ReturnType))
                {
                    return(value);
                }

                if (value.ReturnType is InvalidType || expectedType is InvalidType)
                {
                    return(Expression.Invalid);
                }

                // (EnumType)0
                if (expectedType is EnumType && value is Constant && value.ConstantValue is int && (int)value.ConstantValue == 0)
                {
                    return(new Constant(value.Source, (EnumType)expectedType, (int)value.ConstantValue));
                }

                // Null type (must be done before delegate)
                if (value.ReturnType.IsNull)
                {
                    return(expectedType.IsReferenceType
                            ? new Constant(src, expectedType, null) :
                           !reportErrorIfNotFound
                            ? null
                            : Error(src, ErrorCode.E2043, "'<null>' has no implicit cast to " + expectedType.Quote() + " because that is not a reference type"));
                }

                // Delegate
                if (expectedType is DelegateType && value is MethodGroup)
                {
                    var dt = expectedType as DelegateType;
                    dt.AssignBaseType();

                    var mg                = value as MethodGroup;
                    var candidates        = mg.Candidates;
                    var compatibleMethods = new List <Method>();

                    foreach (var m in candidates)
                    {
                        if (!m.IsGenericDefinition &&
                            m.ReturnType.Equals(dt.ReturnType) &&
                            dt.CompareParameters(m))
                        {
                            compatibleMethods.Add(m);
                        }
                    }

                    if (compatibleMethods.Count == 0)
                    {
                        foreach (var c in candidates)
                        {
                            if (c.IsGenericDefinition)
                            {
                                var dummyArgs = new Expression[dt.Parameters.Length];

                                for (int i = 0; i < dummyArgs.Length; i++)
                                {
                                    var p = dt.Parameters[i];
                                    dummyArgs[i] = new Default(p.Source, p.Type);

                                    switch (p.Modifier)
                                    {
                                    case ParameterModifier.Const:
                                        dummyArgs[i] = new AddressOf(dummyArgs[i], AddressType.Const);
                                        break;

                                    case ParameterModifier.Ref:
                                        dummyArgs[i] = new AddressOf(dummyArgs[i], AddressType.Ref);
                                        break;

                                    case ParameterModifier.Out:
                                        dummyArgs[i] = new AddressOf(dummyArgs[i], AddressType.Out);
                                        break;
                                    }
                                }

                                candidates = CopyAndParameterizeGenericMethods(src, candidates, dummyArgs);

                                foreach (var m in candidates)
                                {
                                    if (!m.IsGenericDefinition &&
                                        m.ReturnType.Equals(dt.ReturnType) &&
                                        dt.CompareParameters(m))
                                    {
                                        compatibleMethods.Add(m);
                                    }
                                }
                                break;
                            }
                        }

                        if (compatibleMethods.Count == 0)
                        {
                            foreach (var m in candidates)
                            {
                                if (!m.IsGenericDefinition &&
                                    (m.ReturnType.Equals(dt.ReturnType) || m.ReturnType.IsReferenceType && m.ReturnType.IsSubclassOfOrEqual(dt.ReturnType)) &&
                                    dt.CompareParametersEqualOrSubclassOf(m))
                                {
                                    compatibleMethods.Add(m);
                                }
                            }
                        }
                    }

                    if (compatibleMethods.Count == 1)
                    {
                        var m = compatibleMethods[0];

                        if (m.IsStatic)
                        {
                            return(new NewDelegate(src, dt, null, m));
                        }

                        if (mg.Object != null && !mg.Object.ReturnType.IsReferenceType)
                        {
                            mg.Object = new CastOp(src, Essentials.Object, mg.Object.ActualValue);
                        }

                        return(new NewDelegate(src, dt, mg.Object, m));
                    }

                    return(!reportErrorIfNotFound
                        ? null
                        : compatibleMethods.Count == 0
                            ? Error(src, ErrorCode.E2045, "No methods matches the parameter list and return type of delegate type " + dt.Quote())
                            : ReportAmbiguousMatchError(src, compatibleMethods));
                }

                // Lambda
                if (expectedType is DelegateType && value is UncompiledLambda)
                {
                    expectedType.AssignBaseType();
                    return(TryCompileImplicitLambdaCast((UncompiledLambda)value, (DelegateType)expectedType));
                }

                // Constant
                if (value is Constant && expectedType.IsIntrinsic)
                {
                    var constant = value as Constant;

                    if (constant.Value is int)
                    {
                        int intValue = (int)constant.Value;

                        switch (expectedType.BuiltinType)
                        {
                        case BuiltinType.SByte:
                            if (intValue >= -0x80 && intValue <= 0x7f)
                            {
                                return(new Constant(constant.Source, expectedType, (sbyte)intValue));
                            }
                            break;

                        case BuiltinType.Byte:
                            if (intValue >= 0 && intValue <= 0xff)
                            {
                                return(new Constant(constant.Source, expectedType, (byte)intValue));
                            }
                            break;

                        case BuiltinType.Short:
                            if (intValue >= -0x8000 && intValue <= 0x7fff)
                            {
                                return(new Constant(constant.Source, expectedType, (short)intValue));
                            }
                            break;

                        case BuiltinType.UShort:
                            if (intValue >= 0 && intValue <= 0xffff)
                            {
                                return(new Constant(constant.Source, expectedType, (ushort)intValue));
                            }
                            break;

                        case BuiltinType.UInt:
                            if (intValue >= 0)
                            {
                                return(new Constant(constant.Source, expectedType, (uint)intValue));
                            }
                            break;

                        case BuiltinType.ULong:
                            if (intValue >= 0)
                            {
                                return(new Constant(constant.Source, expectedType, (ulong)intValue));
                            }
                            break;
                        }
                    }

                    if (constant.Value is long)
                    {
                        long longValue = (long)constant.Value;

                        switch (expectedType.BuiltinType)
                        {
                        case BuiltinType.ULong:
                            if (longValue >= 0)
                            {
                                return(new Constant(constant.Source, expectedType, (ulong)longValue));
                            }
                            break;
                        }
                    }
                }

                // Implict cast
                bool ambiguous;
                var  cast = TryResolveCastOverload(src, NameResolver.GetTypeCasts(expectedType, value.ReturnType),
                                                   ref value, reportErrorIfNotFound, out ambiguous);

                if (ambiguous)
                {
                    goto ERROR;
                }

                if (cast != null && cast.IsImplicitCast)
                {
                    return(new CallCast(src, cast, value));
                }

                // Up cast
                if (expectedType == Essentials.Object ||
                    value.ReturnType.IsSubclassOf(expectedType) ||
                    expectedType.IsInterface && value.ReturnType.IsImplementingInterface(expectedType))
                {
                    return(new CastOp(src, expectedType, value));
                }

                // Fixed Array
                if (expectedType.IsFixedArray && value.ReturnType.IsFixedArray)
                {
                    var t1 = expectedType as FixedArrayType;
                    var t2 = value.ReturnType as FixedArrayType;

                    if (t1.ElementType.Equals(t2.ElementType) && (
                            t1.OptionalSize == null || t2.OptionalSize == null ||
                            t1.OptionalSize is Constant && t2.OptionalSize is Constant && Equals(t1.OptionalSize.ConstantValue, t2.OptionalSize.ConstantValue)
                            ))
                    {
                        return(value);
                    }
                }

                // T[] -> IEnumerable<T>
                if (value.ReturnType.IsRefArray && expectedType.MasterDefinition == Essentials.IEnumerable_T)
                {
                    ImplicitCastStack.RemoveLast();
                    var arrayEnumerable = TypeBuilder.Parameterize(src, Essentials.ArrayEnumerable_T, value.ReturnType.ElementType);
                    return(TryCompileImplicitCast(src, expectedType,
                                                  ILFactory.NewObject(src, arrayEnumerable, value), reportErrorIfNotFound));
                }
            }

ERROR:
            return(!reportErrorIfNotFound
                ? null
                : Error(src, ErrorCode.E2047, "No implicit cast from " + value.ReturnType.Quote() + " to " + expectedType.Quote()));
        }