Ejemplo n.º 1
0
        Statement CompileFixedArrayDeclaration(AstFixedArrayDeclaration e)
        {
            var s    = e.Type;
            var size = s.OptionalSize != null
                ? CompileImplicitCast(s.OptionalSize.Source, Essentials.Int,
                                      CompileExpression(s.OptionalSize))
                : null;

            var elementType = NameResolver.GetType(Namescope, s.ElementType);
            var dt          = new FixedArrayType(s.Source, elementType, size, Essentials.Int);

            VerifyVariableName(e.Source, e.Name.Symbol);

            var fixedInit = e.OptionalValue as AstFixedArrayInitializer;

            if (fixedInit != null)
            {
                return(CompileFixedArrayDeclaration(e.Source, dt, e.Name.Symbol, fixedInit));
            }

            var var = new Variable(e.Source, Function, e.Name.Symbol, dt, 0,
                                   e.OptionalValue != null
                ? CompileImplicitCast(e.Source, dt, CompileExpression(e.OptionalValue))
                : null);

            CurrentVariableScope.Variables[e.Name.Symbol] = var;
            return(new FixedArrayDeclaration(var, null));
        }
        public Expression CompileCast(AstCast ce)
        {
            var targetType = NameResolver.GetType(Namescope, ce.TargetType);
            var operand    = CompileExpression(ce.Argument);

            return(TryCompileCast(ce.Source, targetType, operand) ??
                   Error(ce.Source, ErrorCode.E2029, operand.ReturnType.Quote() + " has no defined cast to type " + targetType.Quote()));
        }
Ejemplo n.º 3
0
        public Expression CompileVertexAttribExplicit(AstVertexAttribExplicit e)
        {
            var type = NameResolver.GetType(Namescope, e.Type);
            var args = CompileArgumentList(e.Arguments);

            if (args.Length < 4)
            {
                return(Error(e.Source, ErrorCode.E0000, "Minimum 4 arguments are required for 'vertex_attrib'"));
            }

            return(new NewVertexAttrib(e.Source, type,
                                       CompileImplicitCast(args[0].Source, "Uno.Graphics.VertexAttributeType", args[0]),
                                       CompileImplicitCast(args[1].Source, "Uno.Graphics.VertexBuffer", args[1]),
                                       CompileImplicitCast(args[2].Source, Essentials.Int, args[2]),
                                       CompileImplicitCast(args[3].Source, Essentials.Int, args[3]),
                                       args.Length > 4
                    ? CompileImplicitCast(args[4].Source, "Uno.Graphics.IndexType", args[4])
                    : null,
                                       args.Length > 5
                    ? CompileImplicitCast(args[5].Source, "Uno.Graphics.IndexBuffer", args[5])
                    : null));
        }
        public Expression CompileCall(AstCall e)
        {
            // Builtin struct initialization
            if (e.Base is AstBuiltinType)
            {
                var dt = NameResolver.GetType(Namescope, e.Base);

                if (dt.IsStruct)
                {
                    // Default ctor
                    if (e.Arguments.Count == 0)
                    {
                        return(new Default(e.Source, dt));
                    }

                    dt.PopulateMembers();

                    Constructor  ctor;
                    Expression[] args;
                    return(TryResolveConstructorOverload(e.Source, dt.Constructors, e.Arguments, out ctor, out args)
                        ? new NewObject(e.Source, ctor, args)
                        : Error(e.Source, ErrorCode.E3125, dt.Quote() + " has no constructors matching the argument list " +
                                PrintableArgumentList(e.Arguments) +
                                NameResolver.SuggestCandidates(dt.Constructors)));
                }

                return(Error(e.Source, ErrorCode.E3126, dt.Quote() + " must be instantiated using 'new' because it is not a struct"));
            }

            var pe = ResolveExpression(e.Base, null);

            switch (pe.ExpressionType)
            {
            case PartialExpressionType.Block:
            case PartialExpressionType.Type:
            case PartialExpressionType.Namespace:
                if (e.Base is AstIdentifier)
                {
                    var p2 = NameResolver.TryResolveUsingType(Namescope, e.Base as AstIdentifier, null);
                    if (p2 != null)
                    {
                        pe = p2;
                    }
                }
                break;
            }

            var sym = CompilePartial(pe);

            if (sym.IsInvalid)
            {
                return(Expression.Invalid);
            }

            // Delegate call
            if (sym.ReturnType.IsDelegate)
            {
                var dt = (DelegateType)sym.ReturnType;
                dt.AssignBaseType();
                var args = TryApplyDefaultValuesOnArgumentList(sym.Source, dt.Parameters, CompileArgumentList(e.Arguments));
                return(TryApplyImplicitCastsOnArgumentList(dt.Parameters, args)
                    ? new CallDelegate(e.Source, sym, args)
                    : Error(e.Source, ErrorCode.E3127, "Call to delegate of type " + dt.Quote() + " has some invalid arguments " +
                            PrintableArgumentList(e.Arguments)));
            }

            // Using static fall back
            if (!(sym is MethodGroup) && e.Base is AstIdentifier)
            {
                var p2 = NameResolver.TryResolveUsingType(Namescope, e.Base as AstIdentifier, null);
                if (p2 != null)
                {
                    sym = CompilePartial(p2);
                    if (sym.IsInvalid)
                    {
                        return(Expression.Invalid);
                    }
                }
            }

            // Method call
            if (sym is MethodGroup)
            {
                var g = sym as MethodGroup;

                Method       method;
                Expression[] args;
                return(TryResolveMethodOverload(e.Source, g.Candidates, e.Arguments, out method, out args)
                    ? (g.IsQualified && g.Object != null && method.IsStatic
                            ? Error(sym.Source, ErrorCode.E3123, method.Quote() + " is static -- qualify with the type name") :
                       g.Object == null && !method.IsStatic
                            ? Error(sym.Source, ErrorCode.E3124, method.Quote() + " is non-static and cannot be accessed from a static context")
                            : new CallMethod(e.Source, method.IsStatic ? null : g.Object, method, args))
                    : g.Candidates.Count == 1
                        ? Error(e.Source, ErrorCode.E3128, "Call to " + g.Candidates[0].Quote() + " has some invalid arguments " +
                                PrintableArgumentList(e.Arguments))
                        : Error(e.Source, ErrorCode.E3129, "No overloads of " + g.CandidatesBaseName.Quote() + " matches the argument list " +
                                PrintableArgumentList(e.Arguments) +
                                NameResolver.SuggestCandidates(g.Candidates)));
            }

            // Extension method call
            if (sym is ExtensionGroup)
            {
                var g = sym as ExtensionGroup;

                Method       method;
                Expression[] args;
                var          astArgs = new AstArgument[e.Arguments.Count + 1];
                astArgs[0] = new AstIL(g.Object);
                for (int i = 0; i < e.Arguments.Count; i++)
                {
                    astArgs[i + 1] = e.Arguments[i];
                }

                return(TryResolveMethodOverload(e.Source, g.Candidates, astArgs, out method, out args)
                    ? new CallMethod(e.Source, null, method, args)
                    : g.Candidates.Count == 1
                        ? Error(e.Source, ErrorCode.E3128, "Call to " + g.Candidates[0].Quote() + " has some invalid arguments " +
                                PrintableArgumentList(astArgs))
                        : Error(e.Source, ErrorCode.E3129, "No overloads of " + g.CandidatesBaseName.Quote() + " matches the argument list " +
                                PrintableArgumentList(e.Arguments) +
                                NameResolver.SuggestCandidates(g.Candidates)));
            }

            return(Error(e.Source, ErrorCode.E3130, "Instances of type " + sym.ReturnType.Quote() + " cannot be called as a function"));
        }
Ejemplo n.º 5
0
        public Expression CompileExpression(AstExpression e)
        {
            switch (e.ExpressionType)
            {
            case AstExpressionType.Initializer:
            {
                var s    = (AstInitializer)e;
                var root = CompileExpression(s.Expressions[0]);
                for (var i = 1; i < s.Expressions.Count; i++)
                {
                    root = new SequenceOp(root, CompileExpression(s.Expressions[i]));
                }
                return(root);
            }

            case AstExpressionType.Identifier:
                return(CompilePartial(ResolveIdentifier(e as AstIdentifier, null)));

            case AstExpressionType.Macro:
                return(new ExternString(e.Source, Essentials.String, ((AstMacro)e).Value, GetUsings(e.Source)));

            case AstExpressionType.Void:
            case AstExpressionType.Global:
            case AstExpressionType.Generic:
            case AstExpressionType.BuiltinType:
            case AstExpressionType.Array:
            case AstExpressionType.FixedArray:
            case AstExpressionType.Parameterizer:
                return(CompilePartial(NameResolver.ResolveExpression(Namescope, e, null)));

            case AstExpressionType.Add:
            case AstExpressionType.Sub:
            case AstExpressionType.Mul:
            case AstExpressionType.Div:
            case AstExpressionType.Mod:
            case AstExpressionType.NullOp:
            case AstExpressionType.LogAnd:
            case AstExpressionType.LogOr:
            case AstExpressionType.Equal:
            case AstExpressionType.NotEqual:
            case AstExpressionType.LessThan:
            case AstExpressionType.LessThanOrEqual:
            case AstExpressionType.GreaterThan:
            case AstExpressionType.GreaterThanOrEqual:
            case AstExpressionType.BitwiseAnd:
            case AstExpressionType.BitwiseOr:
            case AstExpressionType.BitwiseXor:
            case AstExpressionType.ShiftLeft:
            case AstExpressionType.ShiftRight:
            case AstExpressionType.Assign:
            case AstExpressionType.AddAssign:
            case AstExpressionType.SubAssign:
            case AstExpressionType.MulAssign:
            case AstExpressionType.DivAssign:
            case AstExpressionType.ModAssign:
            case AstExpressionType.BitwiseAndAssign:
            case AstExpressionType.BitwiseOrAssign:
            case AstExpressionType.BitwiseXorAssign:
            case AstExpressionType.ShiftLeftAssign:
            case AstExpressionType.ShiftRightAssign:
            case AstExpressionType.LogAndAssign:
            case AstExpressionType.LogOrAssign:
            case AstExpressionType.Sequence:
                return(CompileBinOp(e as AstBinary));

            case AstExpressionType.DecreasePrefix:
            case AstExpressionType.DecreasePostfix:
            case AstExpressionType.IncreasePrefix:
            case AstExpressionType.IncreasePostfix:
            case AstExpressionType.Negate:
            case AstExpressionType.LogNot:
            case AstExpressionType.BitwiseNot:
                return(CompileUnOp(e as AstUnary));

            case AstExpressionType.Cast:
                return(CompileCast(e as AstCast));

            case AstExpressionType.Call:
                return(CompileCall(e as AstCall));

            case AstExpressionType.LookUp:
                return(CompilePartial(ResolveLookUp(e as AstCall)));

            case AstExpressionType.Member:
                return(CompilePartial(ResolveMember(e as AstMember, null)));

            case AstExpressionType.New:
                return(CompileNewExpression(e as AstNew));

            case AstExpressionType.This:
                return(CompileThis(e.Source));

            case AstExpressionType.Base:
                return(CompileBase(e.Source));

            case AstExpressionType.Import:
                return(CompileImport(e as AstImport));

            case AstExpressionType.VertexAttribImplicit:
                return(CompileVertexAttribImplicit(e as AstVertexAttribImplicit));

            case AstExpressionType.VertexAttribExplicit:
                return(CompileVertexAttribExplicit(e as AstVertexAttribExplicit));

            case AstExpressionType.Null:
                return(new Constant(e.Source, DataType.Null, null));

            case AstExpressionType.Defined:
                return(new Constant(e.Source, Essentials.Bool, Environment.Test(e.Source, (e as AstDefined).Condition)));

            case AstExpressionType.Default:
                return(new Default(e.Source, NameResolver.GetType(Namescope, ((AstUnary)e).Operand)));

            case AstExpressionType.True:
                return(new Constant(e.Source, Essentials.Bool, true));

            case AstExpressionType.False:
                return(new Constant(e.Source, Essentials.Bool, false));

            case AstExpressionType.Zero:
                return(new Constant(e.Source, Essentials.Int, 0));

            case AstExpressionType.Int:
                return(new Constant(e.Source, Essentials.Int, ((AstInt)e).Value));

            case AstExpressionType.UInt:
                return(new Constant(e.Source, Essentials.UInt, ((AstUInt)e).Value));

            case AstExpressionType.Long:
                return(new Constant(e.Source, Essentials.Long, ((AstLong)e).Value));

            case AstExpressionType.ULong:
                return(new Constant(e.Source, Essentials.ULong, ((AstULong)e).Value));

            case AstExpressionType.Float:
                return(new Constant(e.Source, Essentials.Float, ((AstFloat)e).Value));

            case AstExpressionType.Double:
                return(new Constant(e.Source, Essentials.Double, ((AstDouble)e).Value));

            case AstExpressionType.Char:
                return(new Constant(e.Source, Essentials.Char, ((AstChar)e).Value));

            case AstExpressionType.String:
                return(new Constant(e.Source, Essentials.String, ((AstString)e).Value));

            case AstExpressionType.Unchecked:
            {
                CheckCastStack.Add(false);
                var result = CompileExpression(((AstUnary)e).Operand);
                CheckCastStack.RemoveLast();
                return(result);
            }

            case AstExpressionType.ReadOnly:
            {
                var s = e as AstUnary;
                return(new StageOp(s.Source, MetaStage.ReadOnly, CompileExpression(s.Operand)));
            }

            case AstExpressionType.Volatile:
            {
                var s = e as AstUnary;
                return(new StageOp(s.Source, MetaStage.Volatile, CompileExpression(s.Operand)));
            }

            case AstExpressionType.Vertex:
            {
                var s = e as AstUnary;
                return(new StageOp(s.Source, MetaStage.Vertex, CompileExpression(s.Operand)));
            }

            case AstExpressionType.Pixel:
            {
                var s = e as AstUnary;
                return(new StageOp(s.Source, MetaStage.Pixel, CompileExpression(s.Operand)));
            }

            case AstExpressionType.Extern:
            {
                var s = (AstExtern)e;
                return(new ExternOp(s.Value.Source,
                                    Compiler.CompileAttributes(Namescope, s.Attributes),
                                    s.OptionalType != null
                            ? NameResolver.GetType(Namescope, s.OptionalType)
                            : DataType.Void,
                                    s.Value.String,
                                    ExtensionTransform.CreateObject(s.Source, Function, TypeBuilder.Parameterize(Function.DeclaringType)),
                                    s.OptionalArguments != null
                            ? CompileArgumentList(s.OptionalArguments)
                            : ExtensionTransform.CreateArgumentList(s.Source, Function),
                                    GetUsings(s.Source)));
            }

            case AstExpressionType.Ternary:
            {
                var s = e as AstTernary;

                if (s.Condition is AstDefined)
                {
                    var def    = s.Condition as AstDefined;
                    var result = Environment.Test(def.Source, def.Condition)
                            ? CompileExpression(s.True)
                            : CompileExpression(s.False);
                    return(result.ReturnType.IsNull
                            ? Error(s.Source, ErrorCode.E0000, "Cannot resolve type of <null> in constant folded conditional expression")
                            : result);
                }

                var cond  = CompileImplicitCast(s.Condition.Source, Essentials.Bool, CompileExpression(s.Condition));
                var left  = CompileExpression(s.True);
                var right = CompileExpression(s.False);

                if (!left.ReturnType.IsNull)
                {
                    right = CompileImplicitCast(s.False.Source, left.ReturnType, right);
                }
                else if (!right.ReturnType.IsNull)
                {
                    left = CompileImplicitCast(s.True.Source, right.ReturnType, left);
                }
                else
                {
                    return(Error(s.Source, ErrorCode.E2086, "The type of the conditional expression could not be resolved because there is no implicit conversion between <null> and <null>"));
                }

                return(new ConditionalOp(s.Source, cond, left, right));
            }

            case AstExpressionType.Local:
            {
                var s = e as AstLocal;
                var p = TryResolveLocalIdentifier(s.Name);

                if (p == null && Namescope is BlockBase)
                {
                    p = TryResolveCapturedLocalIdentifier(Namescope as BlockBase, s.Name);
                }

                return(p != null
                        ? CompilePartial(p)
                        : Error(e.Source, ErrorCode.E0000, s.Name.Quote() + " is not a local variable or method parameter"));
            }

            case AstExpressionType.Prev:
            {
                var s = e as AstPrev;

                if (s.OptionalName != null)
                {
                    var b = CompileExpression(s.OptionalName);
                    if (b.IsInvalid)
                    {
                        return(b);
                    }
                    var mp = b as GetMetaProperty;
                    return(mp == null
                            ? Error(s.OptionalName.Source, ErrorCode.E2035, b.Quote() + " is not a meta property")
                            : new GetMetaProperty(s.Source, mp.ReturnType, mp.Name, mp.Offset + s.Offset));
                }

                return(MetaProperty != null
                        ? new GetMetaProperty(s.Source, MetaProperty.ReturnType, MetaProperty.Name, 1)
                        : Error(s.Source, ErrorCode.E2036, "Current scope is not a meta property scope"));
            }

            case AstExpressionType.PixelSampler:
            {
                var s       = e as AstPixelSampler;
                var texture = CompileExpression(s.Texture);

                Expression samplerState = null;
                if (s.OptionalState != null)
                {
                    var samplerStateType = ILFactory.GetType(s.OptionalState.Source, "Uno.Graphics.SamplerState");
                    samplerState = CompileImplicitCast(s.OptionalState.Source, samplerStateType, CompileExpression(s.OptionalState));
                }

                switch (texture.ReturnType.BuiltinType)
                {
                case BuiltinType.Texture2D:
                    return(new NewPixelSampler(s.Source, Essentials.Sampler2D, texture, samplerState));

                case BuiltinType.TextureCube:
                    return(new NewPixelSampler(s.Source, Essentials.SamplerCube, texture, samplerState));

                case BuiltinType.VideoTexture:
                    return(new NewPixelSampler(s.Source, Essentials.VideoSampler, texture, samplerState));
                }

                return(!texture.IsInvalid
                        ? Error(s.Texture.Source, ErrorCode.E0000, "First argument to 'pixel_sampler' must be an object of type 'texture2D' or 'textureCube'")
                        : Expression.Invalid);
            }

            case AstExpressionType.Is:
            {
                var s    = (AstBinary)e;
                var obj  = CompileExpression(s.Left);
                var type = NameResolver.GetType(Namescope, s.Right);
                return(new IsOp(e.Source, obj, type, Essentials.Bool));
            }

            case AstExpressionType.As:
            {
                var s    = (AstBinary)e;
                var obj  = CompileExpression(s.Left);
                var type = NameResolver.GetType(Namescope, s.Right);
                return(new AsOp(e.Source, obj, type));
            }

            case AstExpressionType.SizeOf:
            {
                var s  = (AstUnary)e;
                var dt = NameResolver.GetType(Namescope, s.Operand);
                return(new Constant(s.Source, Essentials.Int, NameResolver.GetSizeOf(s.Source, dt)));
            }

            case AstExpressionType.TypeOf:
            {
                var s = (AstUnary)e;
                return(new TypeOf(s.Source, Essentials.Type, NameResolver.GetType(Namescope, s.Operand)));
            }

            case AstExpressionType.NameOf:
            {
                // TODO: Missing verification
                var s = (AstUnary)e;
                return(new Constant(s.Source, Essentials.String, ResolveExpression(s.Operand, null).ToString()));
            }

            case AstExpressionType.Lambda:
                return(CompileLambda((AstLambda)e));

            case AstExpressionType.ArrayInitializer:
                return(Error(e.Source, ErrorCode.E2075, "Array initializers are not supported in this context"));
            }

            return(e is AstIL
                ? (e as AstIL).Expression
                : Error(e.Source, ErrorCode.I2042, "Unhandled expression type in CompileExpression: " + e.ExpressionType));
        }
Ejemplo n.º 6
0
 public DataType GetType(Source src, string type)
 {
     return(_resolver.GetType(_il, Parser.ParseType(Log, src, type)));
 }
Ejemplo n.º 7
0
        public Expression CompileNewExpression(AstNew e)
        {
            // Implicitly typed arrays
            if (e.OptionalType == null)
            {
                if (e.OptionalArguments != null)
                {
                    return(Error(e.Source, ErrorCode.E2001, "Array constructors cannot have argument list"));
                }
                if (e.OptionalArraySize != null)
                {
                    return(Error(e.Source, ErrorCode.E2002, "Cannot specify size on implicitly typed arrays"));
                }
                if (e.OptionalCollectionInitializer == null || e.OptionalCollectionInitializer.Count == 0)
                {
                    return(Error(e.Source, ErrorCode.E2003, "Must provide non-empty initializer list for implicitly typed arrays"));
                }

                var values = new Expression[e.OptionalCollectionInitializer.Count];
                for (int i = 0; i < values.Length; i++)
                {
                    values[i] = CompileExpression(e.OptionalCollectionInitializer[i]);
                }

                var et = TryGetImplicitElementType(values);

                if (et == null)
                {
                    return(Error(e.Source, ErrorCode.E2004, "No best type found for implicitly typed array"));
                }

                for (int i = 0; i < values.Length; i++)
                {
                    values[i] = CompileImplicitCast(e.Source, et, values[i]);
                }

                return(et.IsValueType || et.IsReferenceType
                        ? new NewArray(e.Source, TypeBuilder.GetArray(et), values) :
                       et != DataType.Invalid
                        ? Error(e.Source, ErrorCode.E2080, "Cannot create an implicitly typed array of type " + et.Quote())
                        : Expression.Invalid);
            }

            var dt = NameResolver.GetType(Namescope, e.OptionalType);

            switch (dt.TypeType)
            {
            case TypeType.RefArray:
            {
                if (e.OptionalArguments != null)
                {
                    return(Error(e.Source, ErrorCode.E2005, "Array constructors cannot have argument list"));
                }

                var        at   = dt as RefArrayType;
                Expression size = null;

                if (e.OptionalArraySize != null)
                {
                    size = CompileImplicitCast(e.Source, Essentials.Int, CompileExpression(e.OptionalArraySize));
                    if (size.IsInvalid)
                    {
                        return(Expression.Invalid);
                    }
                }

                if (e.OptionalCollectionInitializer != null)
                {
                    var values = new Expression[e.OptionalCollectionInitializer.Count];
                    for (int i = 0; i < values.Length; i++)
                    {
                        values[i] = CompileExpression(e.OptionalCollectionInitializer[i]);
                    }

                    if (size != null)
                    {
                        var c = Compiler.ConstantFolder.TryMakeConstant(size);
                        if (c == null || !c.Value.Equals(values.Length))
                        {
                            return(Error(size.Source, ErrorCode.E2006, "Inconsistent array size and initializer list length"));
                        }
                    }

                    switch (at.ElementType.BuiltinType)
                    {
                    case BuiltinType.Bool:
                    case BuiltinType.Byte:
                    case BuiltinType.Char:
                    case BuiltinType.Double:
                    case BuiltinType.Int:
                    case BuiltinType.Float:
                    case BuiltinType.Long:
                    case BuiltinType.SByte:
                    case BuiltinType.Short:
                    case BuiltinType.UInt:
                    case BuiltinType.ULong:
                    case BuiltinType.UShort:
                        // Disable warning on primitive types
                        break;

                    default:
                        if (TryGetImplicitElementType(values) == at.ElementType)
                        {
                            Log.Warning3(e.Source, ErrorCode.W2007, "Array can be instantiated as implicitly typed array (new[] { ... })");
                        }

                        break;
                    }

                    for (int i = 0; i < values.Length; i++)
                    {
                        values[i] = CompileImplicitCast(values[i].Source, at.ElementType, values[i]);
                    }

                    return(new NewArray(e.Source, at, values));
                }

                return(new NewArray(e.Source, at, size));
            }

            case TypeType.Class:
            case TypeType.Struct:
            case TypeType.GenericParameter:
            {
                if (dt.IsStatic)
                {
                    return(Error(e.Source, ErrorCode.E2090, "Cannot instantiate static class"));
                }

                if (e.OptionalArguments != null || e.OptionalCollectionInitializer != null)
                {
                    if (e.OptionalArraySize != null)
                    {
                        return(Error(e.Source, ErrorCode.E2008, "Object constructors cannot have array size"));
                    }

                    Expression newObject;

                    if (dt.IsStruct && (e.OptionalArguments == null || e.OptionalArguments.Count == 0))
                    {
                        newObject = new Default(e.Source, dt);
                    }
                    else
                    {
                        dt.PopulateMembers();

                        Constructor  ctor;
                        Expression[] args;

                        if (!TryResolveConstructorOverload(e.Source, dt.Constructors, e.OptionalArguments ?? AstArgument.Empty, out ctor, out args))
                        {
                            return(e.OptionalArguments != null && e.OptionalArguments.Count > 0
                                    ? (dt.Constructors.Count == 1
                                        ? Error(e.Source, ErrorCode.E2009, "Call to " + (dt + PrintableParameterList(dt.Constructors[0].Parameters)).Quote() + " has some invalid arguments " +
                                                PrintableArgumentList(e.OptionalArguments))
                                        : Error(e.Source, ErrorCode.E2009, dt.Quote() + " has no constructors matching the argument list " +
                                                PrintableArgumentList(e.OptionalArguments) +
                                                NameResolver.SuggestCandidates(dt.Constructors)))
                                    : Error(e.Source, ErrorCode.E0000, dt.Quote() + " has no default constructor"));
                        }

                        newObject = new NewObject(e.Source, ctor, args);
                    }

                    if (e.OptionalCollectionInitializer != null && e.OptionalCollectionInitializer.Count > 0)
                    {
                        var var = new Variable(e.Source, Function, Namescope.GetUniqueIdentifier("collection"), newObject.ReturnType);
                        CurrentVariableScope.Variables.Add(var.Name, var);

                        Expression root = new StoreLocal(e.Source, var, newObject);

                        // See if it is a member initializer or collection initializer
                        var containsAssignOp = false;

                        foreach (var i in e.OptionalCollectionInitializer)
                        {
                            if (i is AstBinary && (i as AstBinary).IsAssign)
                            {
                                containsAssignOp = true;
                                break;
                            }
                        }

                        if (containsAssignOp)
                        {
                            var initedMembers = new List <string>();

                            // Assign members
                            foreach (var i in e.OptionalCollectionInitializer)
                            {
                                var binOp = i as AstBinary;
                                if (binOp == null || binOp.Type != AstBinaryType.Assign || !(binOp.Left is AstIdentifier))
                                {
                                    Log.Error(i.Source, ErrorCode.E2077, "Invalid initalizer member declarator");
                                    continue;
                                }

                                var id     = (AstIdentifier)binOp.Left;
                                var member = new AstMember(new AstIdentifier(i.Source, var.Name), id);

                                if (binOp.Right is AstArrayInitializer)
                                {
                                    var ai         = binOp.Right as AstArrayInitializer;
                                    var collection = CompileExpression(member);

                                    var cvar = new Variable(e.Source, Function, Namescope.GetUniqueIdentifier("array"), collection.ReturnType);
                                    CurrentVariableScope.Variables.Add(cvar.Name, cvar);

                                    root = new SequenceOp(root, new StoreLocal(collection.Source, cvar, collection));

                                    if (collection.IsInvalid)
                                    {
                                        continue;
                                    }

                                    foreach (var ci in ai.Values)
                                    {
                                        root = new SequenceOp(root, CompileAddToCollection(cvar.Name, ci));
                                    }
                                }
                                else
                                {
                                    var assign = CompileAssign(new AstBinary(AstBinaryType.Assign, member, i.Source, binOp.Right));
                                    root = new SequenceOp(root, assign);

                                    if (assign.IsInvalid)
                                    {
                                        continue;
                                    }
                                }

                                foreach (var m in initedMembers)
                                {
                                    if (m == id.Symbol)
                                    {
                                        Log.Error(i.Source, ErrorCode.E2078, "Duplicate initialization of member " + id.Symbol.Quote());
                                        break;
                                    }
                                }

                                initedMembers.Add(id.Symbol);
                            }
                        }
                        else
                        {
                            // Add to collection
                            foreach (var i in e.OptionalCollectionInitializer)
                            {
                                root = new SequenceOp(root, CompileAddToCollection(var.Name, i));
                            }
                        }

                        return(new SequenceOp(root, new LoadLocal(e.Source, var)));
                    }

                    if (e.OptionalType is AstBuiltinType && dt.IsStruct)
                    {
                        Log.Warning(e.Source, ErrorCode.W0000, "Redundant 'new' operator on builtin struct initialization");
                    }

                    return(newObject);
                }

                return(Error(e.Source, ErrorCode.E2011, "Must provide argument list for object constructor"));
            }

            case TypeType.Delegate:
            {
                if (e.OptionalArguments == null)
                {
                    return(Error(e.Source, ErrorCode.E0000, "Must provide argument list for delegate constructor"));
                }

                var args = CompileArgumentList(e.OptionalArguments);

                if (e.OptionalCollectionInitializer != null)
                {
                    return(Error(e.Source, ErrorCode.E0000, "Delegate construction cannot have collection initializer"));
                }
                if (e.OptionalArraySize != null)
                {
                    return(Error(e.Source, ErrorCode.E0000, "Delegate construction cannot have array size"));
                }
                if (args.Length != 1 || args[0].ExpressionType != ExpressionType.MethodGroup)
                {
                    return(Error(e.Source, ErrorCode.E0000, "Delegate construction requires one method argument"));
                }

                return(CompileImplicitCast(e.Source, dt, args[0]));
            }

            case TypeType.Invalid:
                return(Expression.Invalid);

            default:
                return(Error(e.Source, ErrorCode.E2012, "Instances of type " + dt.Quote() + " cannot be created using 'new' because it is not a class, struct or array type"));
            }
        }
Ejemplo n.º 8
0
        public FixedArrayDeclaration CompileFixedArrayDeclaration(Source src, DataType dt, string name, AstFixedArrayInitializer s)
        {
            DataType   et   = null;
            Expression size = null;

            Expression[] values = null;

            if (s.OptionalElementType != null)
            {
                et = NameResolver.GetType(Namescope, s.OptionalElementType);
            }

            if (s.OptionalSize != null)
            {
                size = CompileImplicitCast(s.OptionalSize.Source, Essentials.Int, CompileExpression(s.OptionalSize));
            }

            if (s.OptionalValues != null)
            {
                values = new Expression[s.OptionalValues.Count];

                for (int i = 0; i < values.Length; i++)
                {
                    values[i] = CompileExpression(s.OptionalValues[i]);
                }

                if (et != null)
                {
                    for (int i = 0; i < values.Length; i++)
                    {
                        values[i] = CompileImplicitCast(values[i].Source, et, values[i]);
                    }
                }
                else
                {
                    var it = TryGetImplicitElementType(values);

                    if (it == null)
                    {
                        Log.Error(s.Source, ErrorCode.E0000, "No best type found for implicitly typed fixed array");
                        it = DataType.Invalid;
                    }

                    et = it;
                }

                if (size != null)
                {
                    Compiler.ConstantFolder.TryMakeConstant(ref size);

                    if (size.ExpressionType != ExpressionType.Constant || (int)size.ConstantValue != values.Length)
                    {
                        Log.Error(size.Source, ErrorCode.E0000, "Fixed array size does not match initializer count");
                    }
                }
                else
                {
                    size = new Constant(s.Source, Essentials.Int, values.Length);
                }
            }
            else if (et == null)
            {
                Log.Error(s.Source, ErrorCode.E0000, "Must provide non-empty initializer list for implicitly typed fixed arrays");
                et = DataType.Invalid;
            }
            else if (size == null)
            {
                Log.Error(s.Source, ErrorCode.E0000, "Must provide non-empty initializer list for implicitly sized fixed arrays");
                size = new Constant(s.Source, DataType.Invalid, -1);
            }

            if (dt != null)
            {
                var fat = dt as FixedArrayType;

                if (fat == null ||
                    !fat.ElementType.Equals(et) ||
                    fat.OptionalSize != null && !fat.OptionalSize.Equals(size))
                {
                    Log.Error(src, ErrorCode.E0000, "Declaring type must be 'fixed " + et + "[" + size + "]' or 'fixed " + et + "[]'");
                }
            }

            var var = new Variable(s.Source, Function, name, new FixedArrayType(s.Source, et, size, Essentials.Int));

            CurrentVariableScope.Variables[name] = var;
            return(new FixedArrayDeclaration(var, values));
        }
Ejemplo n.º 9
0
        Statement CompileVariableDeclaration(AstVariableDeclaration e)
        {
            DataType dt = null;

            switch (e.Type.ExpressionType)
            {
            case AstExpressionType.Var:
            {
                if (e.Variables.Count != 1)
                {
                    Log.Error(e.Source, ErrorCode.E0000, "Implicitly-typed variables cannot have multiple declarators");
                    dt = DataType.Invalid;
                }
                else if (e.Variables[0].OptionalValue == null)
                {
                    Log.Error(e.Source, ErrorCode.E3400, "Variable declarations using 'var' must provide an initial value");
                    dt = DataType.Invalid;
                }

                if (e.Modifier == AstVariableModifier.Const)
                {
                    Log.Error(e.Source, ErrorCode.E0000, "Implicitly-typed variables cannot be constant");
                    dt = DataType.Invalid;
                }
                break;
            }

            default:
            {
                dt = NameResolver.GetType(Namescope, e.Type);
                break;
            }
            }

            Variable root = null;
            Variable next = null;

            foreach (var v in e.Variables)
            {
                VerifyVariableName(v.Name.Source, v.Name.Symbol);
                Expression initValue = null;

                if (v.OptionalValue != null)
                {
                    initValue = CompileExpression(v.OptionalValue);
                    if (e.Modifier == 0 &&
                        initValue is NewObject &&
                        e.Type.ExpressionType != AstExpressionType.Var &&
                        initValue.ReturnType.Equals(dt) &&
                        dt.BuiltinType == 0)
                    {
                        Log.Warning3(e.Source, ErrorCode.W3401, "Variable can be implicitly typed using 'var'");
                    }

                    if (dt != null)
                    {
                        initValue = CompileImplicitCast(e.Source, dt, initValue);
                    }
                    else
                    {
                        dt = initValue.ReturnType;
                    }

                    if (e.Modifier == AstVariableModifier.Const)
                    {
                        Compiler.ConstantFolder.TryMakeConstant(ref initValue);
                    }
                }

                var var = new Variable(v.Name.Source, Function, v.Name.Symbol, dt,
                                       (VariableType)e.Modifier,
                                       initValue);
                CurrentVariableScope.Variables[v.Name.Symbol] = var;
                next            = root == null
                    ? root      = var
                    : next.Next = var;
            }

            return(new VariableDeclaration(root));
        }
Ejemplo n.º 10
0
        public Statement CompileStatement(AstStatement e)
        {
            switch (e.StatementType)
            {
            default:
                if (e is AstExpression)
                {
                    return(CompileExpression(e as AstExpression));
                }
                break;

            case AstStatementType.VariableDeclaration:
                return(CompileVariableDeclaration(e as AstVariableDeclaration));

            case AstStatementType.FixedArrayDeclaration:
                return(CompileFixedArrayDeclaration(e as AstFixedArrayDeclaration));

            case AstStatementType.Scope:
                return(CompileScope(e as AstScope));

            case AstStatementType.Draw:
                return(Compiler.BlockBuilder.CompileDraw(Function, VariableScopeStack, e as AstDraw));

            case AstStatementType.DrawDispose:
                return(new DrawDispose(e.Source));

            case AstStatementType.Break:
                return(new Break(e.Source));

            case AstStatementType.Continue:
                return(new Continue(e.Source));

            case AstStatementType.Unchecked:
            {
                CheckCastStack.Add(false);

                try
                {
                    return(CompileStatement(((AstModifiedStatement)e).Statement));
                }
                finally
                {
                    CheckCastStack.RemoveLast();
                }
            }

            case AstStatementType.IfElse:
            {
                var s = e as AstIfElse;

                if (s.Condition is AstDefined)
                {
                    var def = s.Condition as AstDefined;

                    return(Environment.Test(def.Source, def.Condition)
                            ? s.OptionalIfBody != null
                                ? CompileStatement(s.OptionalIfBody)
                                : new NoOp(s.Source)
                            : s.OptionalElseBody != null
                                ? CompileStatement(s.OptionalElseBody)
                                : new NoOp(s.Source));
                }

                var r = new IfElse(s.Source, CompileCondition(s.Condition));

                if (s.OptionalIfBody != null)
                {
                    r.OptionalIfBody = CompileStatement(s.OptionalIfBody);
                }
                if (s.OptionalElseBody != null)
                {
                    r.OptionalElseBody = CompileStatement(s.OptionalElseBody);
                }

                return(r);
            }

            case AstStatementType.ExternScope:
            {
                var s = (AstExternScope)e;
                return(new ExternScope(s.Source,
                                       Compiler.CompileAttributes(Namescope, s.Attributes),
                                       s.Body.String,
                                       ExtensionTransform.CreateObject(s.Source, Function, TypeBuilder.Parameterize(Function.DeclaringType)),
                                       s.OptionalArguments != null
                            ? CompileArgumentList(s.OptionalArguments)
                            : ExtensionTransform.CreateArgumentList(s.Source, Function),
                                       GetUsings(s.Source)));
            }

            case AstStatementType.While:
            {
                var s = e as AstLoop;
                var r = new While(s.Source, false, CompileCondition(s.Condition));

                var vscope = new VariableScope();
                VariableScopeStack.Add(vscope);

                if (s.OptionalBody != null)
                {
                    r.OptionalBody = CompileStatement(s.OptionalBody);
                }

                if (s.OptionalBody == null || (!s.OptionalBody.IsInvalid && ((s.OptionalBody is AstScope && (s.OptionalBody as AstScope).IsClosed) || !(s.OptionalBody is AstScope))))
                {
                    VariableScopeStack.Remove(vscope);
                    CurrentVariableScope.Scopes.Add(vscope);
                }

                return(r);
            }

            case AstStatementType.DoWhile:
            {
                var s      = e as AstLoop;
                var r      = new While(s.Source, true, CompileCondition(s.Condition));
                var vscope = new VariableScope();
                VariableScopeStack.Add(vscope);

                if (s.OptionalBody != null)
                {
                    r.OptionalBody = CompileStatement(s.OptionalBody);
                }

                if (s.OptionalBody == null || (!s.OptionalBody.IsInvalid && ((s.OptionalBody is AstScope && (s.OptionalBody as AstScope).IsClosed) || !(s.OptionalBody is AstScope))))
                {
                    VariableScopeStack.Remove(vscope);
                    CurrentVariableScope.Scopes.Add(vscope);
                }

                return(r);
            }

            case AstStatementType.For:
            {
                var s      = e as AstFor;
                var r      = new For(s.Source);
                var vscope = new VariableScope();
                VariableScopeStack.Add(vscope);

                if (s.OptionalInitializer != null)
                {
                    r.OptionalInitializer = CompileStatement(s.OptionalInitializer);
                }
                if (s.OptionalCondition != null)
                {
                    r.OptionalCondition = CompileCondition(s.OptionalCondition);
                }
                if (s.OptionalBody != null)
                {
                    r.OptionalBody = CompileStatement(s.OptionalBody);
                }
                if (s.OptionalIncrement != null)
                {
                    r.OptionalIncrement = CompileExpression(s.OptionalIncrement);
                }

                if (s.OptionalBody == null ||
                    (!s.OptionalBody.IsInvalid && ((s.OptionalBody is AstScope && (s.OptionalBody as AstScope).IsClosed) ||
                                                   !(s.OptionalBody is AstScope))))
                {
                    VariableScopeStack.Remove(vscope);
                    CurrentVariableScope.Scopes.Add(vscope);
                }

                return(r);
            }

            case AstStatementType.Foreach:
            {
                var       s          = e as AstForeach;
                var       scope      = new Scope(s.Source);
                var       collection = CompileExpression(s.Collection);
                Statement result;

                var vscope = new VariableScope();
                VariableScopeStack.Add(vscope);
                VerifyVariableName(s.ElementName.Source, s.ElementName.Symbol);

                if (collection.ReturnType.IsArray ||
                    collection.ReturnType == Essentials.String)
                {
                    var loop = new For(s.Source)
                    {
                        OptionalBody = scope
                    };
                    var collectionVar = new Variable(s.Collection.Source, Function, Namescope.GetUniqueIdentifier("array"), collection.ReturnType);

                    if (collection is LoadLocal)
                    {
                        collectionVar = (collection as LoadLocal).Variable;
                    }
                    else
                    {
                        vscope.Variables.Add(collectionVar.Name, collectionVar);
                    }

                    var indexInitializer  = new Constant(s.Collection.Source, Essentials.Int, 0);
                    var lengthInitializer = CompileImplicitCast(s.Collection.Source, Essentials.Int,
                                                                CompileExpression(
                                                                    new AstMember(
                                                                        new AstIdentifier(s.Collection.Source, collectionVar.Name),
                                                                        new AstIdentifier(s.Collection.Source, "Length"))));

                    var indexVar  = new Variable(s.Collection.Source, Function, Namescope.GetUniqueIdentifier("index"), Essentials.Int);
                    var lengthVar = new Variable(s.Collection.Source, Function, Namescope.GetUniqueIdentifier("length"), Essentials.Int);

                    if (collection is LoadLocal)
                    {
                        indexVar.OptionalValue   = indexInitializer;
                        lengthVar.OptionalValue  = lengthInitializer;
                        loop.OptionalInitializer = new VariableDeclaration(indexVar, lengthVar);
                    }
                    else
                    {
                        loop.OptionalInitializer = new SequenceOp(
                            new StoreLocal(s.Collection.Source, collectionVar, collection),
                            new StoreLocal(s.Collection.Source, indexVar, indexInitializer),
                            new StoreLocal(s.Collection.Source, lengthVar, lengthInitializer));
                    }

                    vscope.Variables.Add(indexVar.Name, indexVar);
                    vscope.Variables.Add(lengthVar.Name, lengthVar);

                    loop.OptionalCondition = CompileCondition(
                        new AstBinary(AstBinaryType.LessThan,
                                      new AstIdentifier(s.Collection.Source, indexVar.Name),
                                      s.Collection.Source,
                                      new AstIdentifier(s.Collection.Source, lengthVar.Name)));

                    loop.OptionalIncrement = new FixOp(s.Collection.Source, FixOpType.IncreaseBefore,
                                                       new LoadLocal(s.Collection.Source, indexVar));

                    var elementType = s.ElementType.ExpressionType == AstExpressionType.Var
                            ? collection.ReturnType.IsArray
                                    ? collection.ReturnType.ElementType
                                    : Essentials.Char
                            : NameResolver.GetType(Namescope, s.ElementType);

                    var elementVar = new Variable(s.ElementName.Source, Function, s.ElementName.Symbol, elementType, VariableType.Iterator,
                                                  CompileImplicitCast(s.ElementName.Source, elementType,
                                                                      CompileExpression(
                                                                          new AstCall(AstCallType.LookUp,
                                                                                      new AstIdentifier(s.ElementName.Source, collectionVar.Name),
                                                                                      new AstIdentifier(s.ElementName.Source, indexVar.Name)))));

                    scope.Statements.Add(new VariableDeclaration(elementVar));
                    vscope.Variables.Add(elementVar.Name, elementVar);
                    result = loop;
                }
                else
                {
                    // TODO: Verify that collection implements IEnumerable<T>

                    var loop = new While(s.Source)
                    {
                        OptionalBody = scope
                    };
                    var enumeratorInitializer = ILFactory.CallMethod(s.Collection.Source, collection.Address, "GetEnumerator");
                    var enumeratorVar         = new Variable(s.Collection.Source, Function, Namescope.GetUniqueIdentifier("enum"), enumeratorInitializer.ReturnType, VariableType.Default, enumeratorInitializer);

                    vscope.Variables.Add(enumeratorVar.Name, enumeratorVar);

                    loop.Condition = CompileImplicitCast(s.Collection.Source, Essentials.Bool,
                                                         ILFactory.CallMethod(s.Collection.Source,
                                                                              new LoadLocal(s.Collection.Source, enumeratorVar).Address,
                                                                              "MoveNext"));

                    var elementInitializer = CompileExpression(new AstMember(
                                                                   new AstIdentifier(s.ElementName.Source, enumeratorVar.Name),
                                                                   new AstIdentifier(s.ElementName.Source, "Current")));

                    var elementType = s.ElementType.ExpressionType == AstExpressionType.Var
                                ? elementInitializer.ReturnType
                                : NameResolver.GetType(Namescope, s.ElementType);
                    var elementVar = new Variable(s.Source, Function, s.ElementName.Symbol, elementType, VariableType.Iterator,
                                                  CompileImplicitCast(s.ElementName.Source, elementType, elementInitializer));

                    var hasDispose = false;
                    foreach (var m in enumeratorVar.ValueType.Methods)
                    {
                        if (m.Name == "Dispose" && m.Parameters.Length == 0)
                        {
                            hasDispose = true;
                            break;
                        }
                    }

                    // Optimization: avoid casting to IDisposable when Dispose() method is found
                    var dispose = hasDispose
                            ? ILFactory.CallMethod(s.Collection.Source,
                                                   new LoadLocal(s.Collection.Source, enumeratorVar).Address,
                                                   "Dispose")
                            : ILFactory.CallMethod(s.Collection.Source,
                                                   new CastOp(s.Collection.Source, Essentials.IDisposable,
                                                              new LoadLocal(s.Collection.Source, enumeratorVar)).Address,
                                                   "Dispose");

                    scope.Statements.Add(new VariableDeclaration(elementVar));
                    vscope.Variables.Add(elementVar.Name, elementVar);
                    result = new Scope(s.Source,
                                       new VariableDeclaration(enumeratorVar),
                                       new TryCatchFinally(s.Source,
                                                           new Scope(s.Source, loop),
                                                           new Scope(s.Source, dispose)));
                }

                if (s.OptionalBody != null)
                {
                    var body = CompileStatement(s.OptionalBody);

                    if (body is Scope)
                    {
                        scope.Statements.AddRange((body as Scope).Statements);
                    }
                    else
                    {
                        scope.Statements.Add(body);
                    }
                }

                if (s.OptionalBody == null ||
                    !s.OptionalBody.IsInvalid && ((s.OptionalBody is AstScope && (s.OptionalBody as AstScope).IsClosed) ||
                                                  !(s.OptionalBody is AstScope)))
                {
                    VariableScopeStack.Remove(vscope);
                    CurrentVariableScope.Scopes.Add(vscope);
                }

                return(result);
            }

            case AstStatementType.Return:
                return(new Return(e.Source));

            case AstStatementType.ReturnValue:
            {
                var s = e as AstValueStatement;

                var returnValue = CompileExpression(s.Value);

                var returnType = Lambdas.Count == 0
                        ? Function.ReturnType
                        : Lambdas.Peek().DelegateType.ReturnType;

                return(new Return(s.Source, CompileImplicitCast(s.Source, returnType, returnValue)));
            }

            case AstStatementType.TryCatchFinally:
            {
                var   s            = e as AstTryCatchFinally;
                var   tryScope     = CompileScope(s.TryScope);
                var   catchBlocks  = new List <CatchBlock>();
                Scope finallyScope = null;

                foreach (var c in s.CatchBlocks)
                {
                    var exceptionType =
                        c.OptionalType != null?
                        NameResolver.GetType(Namescope, c.OptionalType) :
                            Essentials.Exception;

                    var vscope = new VariableScope();
                    VariableScopeStack.Add(vscope);

                    VerifyVariableName(c.Name.Source, c.Name.Symbol);
                    var exceptionVar = new Variable(c.Name.Source, Function, c.Name.Symbol, exceptionType, VariableType.Exception);
                    vscope.Variables.Add(exceptionVar.Name, exceptionVar);

                    var catchBody = CompileScope(c.Body);

                    if (c.Body == null || !c.Body.IsInvalid && c.Body.IsClosed)
                    {
                        VariableScopeStack.Remove(vscope);
                        CurrentVariableScope.Scopes.Add(vscope);
                    }

                    catchBlocks.Add(new CatchBlock(c.Name.Source, exceptionVar, catchBody));
                }

                if (s.OptionalFinallyScope != null)
                {
                    finallyScope = CompileScope(s.OptionalFinallyScope);
                }

                return(new TryCatchFinally(s.Source, tryScope, finallyScope, catchBlocks.ToArray()));
            }

            case AstStatementType.Lock:
            {
                var s            = e as AstLock;
                var scope        = new Scope(s.Source);
                var tryScope     = new Scope(s.Source);
                var finallyScope = new Scope(s.Source);
                var obj          = CompileExpression(s.Object);

                switch (obj.ExpressionType)
                {
                case ExpressionType.LoadLocal:
                case ExpressionType.LoadArgument:
                case ExpressionType.LoadField:
                case ExpressionType.This:
                case ExpressionType.Base:
                    if (!obj.ReturnType.IsReferenceType)
                    {
                        Log.Error(obj.Source, ErrorCode.E0000, "Only reference types can be used in 'lock'");
                    }
                    break;

                default:
                    Log.Error(obj.Source, ErrorCode.E0000, "Only variables can occur inside 'lock' initializer");
                    break;
                }

                if (s.OptionalBody != null)
                {
                    tryScope.Statements.Add(CompileStatement(s.OptionalBody));
                }

                scope.Statements.Add(ILFactory.CallMethod(obj.Source, Essentials.Monitor, "Enter", obj));
                finallyScope.Statements.Add(ILFactory.CallMethod(obj.Source, Essentials.Monitor, "Exit", obj));
                scope.Statements.Add(new TryCatchFinally(s.Source, tryScope, finallyScope));
                return(scope);
            }

            case AstStatementType.Using:
            {
                var s       = e as AstUsing;
                var scope   = new Scope(s.Source);
                var objects = new List <Expression>();
                var vscope  = new VariableScope();
                VariableScopeStack.Add(vscope);
                var init = CompileStatement(s.Initializer);

                for (int i = 0; i < 1; i++)
                {
                    switch (init.StatementType)
                    {
                    case StatementType.VariableDeclaration:
                    {
                        scope.Statements.Add(init);
                        for (var var = ((VariableDeclaration)init).Variable;
                             var != null;
                             var = var.Next)
                        {
                            objects.Add(new LoadLocal(var.Source, var));
                        }
                        continue;
                    }

                    case StatementType.Expression:
                    {
                        if (AddObjects(objects, (Expression)init))
                        {
                            continue;
                        }
                        break;
                    }
                    }

                    // TODO: Actually some expressions are valid as well in C#. Read spec and implement later
                    Log.Error(init.Source, ErrorCode.E0000, "Only variable declarations, fields and/or local variables can occur inside 'using' initializer");
                }

                var tryScope     = new Scope(s.Source);
                var finallyScope = new Scope(s.Source);

                if (s.OptionalBody != null)
                {
                    tryScope.Statements.Add(CompileStatement(s.OptionalBody));
                }

                foreach (var dispose in Enumerable.Reverse(objects))
                {
                    var idisposable = CompileImplicitCast(dispose.Source, Essentials.IDisposable, dispose);
                    finallyScope.Statements.Add(ILFactory.CallMethod(dispose.Source, idisposable, "Dispose"));
                }

                scope.Statements.Add(new TryCatchFinally(s.Source, tryScope, finallyScope));

                if (s.OptionalBody == null ||
                    (!s.OptionalBody.IsInvalid && ((s.OptionalBody is AstScope && (s.OptionalBody as AstScope).IsClosed) ||
                                                   !(s.OptionalBody is AstScope))))
                {
                    VariableScopeStack.Remove(vscope);
                    CurrentVariableScope.Scopes.Add(vscope);
                }

                return(scope);
            }

            case AstStatementType.ThrowValue:
            {
                var s = e as AstValueStatement;
                return(new Throw(s.Source, CompileExpression(s.Value)));
            }

            case AstStatementType.Throw:
            {
                for (int i = VariableScopeStack.Count - 1; i >= 0; i--)
                {
                    foreach (var v in VariableScopeStack[i].Variables.Values)
                    {
                        if (v.IsException)
                        {
                            return(new Throw(e.Source, new LoadLocal(e.Source, v), true));
                        }
                    }
                }

                return(Error(e.Source, ErrorCode.E0000, "Cannot rethrow outside of catch block"));
            }

            case AstStatementType.Switch:
            {
                var s = e as AstSwitch;
                var c = CompileExpression(s.Condition);

                if (!c.ReturnType.IsIntegralType)
                {
                    c = TryCompileImplicitCast(s.Source, Essentials.Int, c) ??
                        Error(s.Condition.Source, ErrorCode.E3415, "A switch expression must be of enum or integral type");
                }

                var cases = new List <SwitchCase>();

                foreach (var a in s.Cases)
                {
                    var handler         = CompileScope(a.Scope);
                    var values          = new List <Constant>();
                    var includesDefault = false;

                    foreach (var v in a.Values)
                    {
                        if (v == null)
                        {
                            includesDefault = true;
                            continue;
                        }

                        var sym      = CompileImplicitCast(v.Source, c.ReturnType, CompileExpression(v));
                        var constSym = Compiler.ConstantFolder.TryMakeConstant(sym);

                        if (constSym != null)
                        {
                            values.Add(constSym);
                        }
                        else if (sym.IsInvalid)
                        {
                            values.Add(new Constant(sym.Source, DataType.Invalid, -1));
                        }
                        else
                        {
                            Log.Error(v.Source, ErrorCode.E3410, "Case-expression must be constant");
                        }
                    }

                    cases.Add(new SwitchCase(values.ToArray(), includesDefault, handler));
                }

                return(new Switch(s.Source, c, cases.ToArray()));
            }

            case AstStatementType.Assert:
            {
                if (!Environment.Debug)
                {
                    return(new NoOp(e.Source, "Stripped assert"));
                }

                var s     = e as AstValueStatement;
                var value = CompileExpression(s.Value);
                var args  = new List <Expression>
                {
                    value,
                    new Constant(s.Source, Essentials.String, value.ToString()),
                    new Constant(s.Source, Essentials.String, s.Source.File.ToString().Replace('\\', '/')),
                    new Constant(s.Source, Essentials.Int, s.Source.Line),
                };
                var locals = new List <StoreLocal>();

                switch (value.ExpressionType)
                {
                case ExpressionType.CallUnOp:
                {
                    var o = value as CallUnOp;
                    args.Add(CreateAssertIndirection(ref o.Operand, locals, Namescope));
                    break;
                }

                case ExpressionType.CallBinOp:
                {
                    var o = value as CallBinOp;
                    args.Add(CreateAssertIndirection(ref o.Left, locals, Namescope));
                    args.Add(CreateAssertIndirection(ref o.Right, locals, Namescope));
                    break;
                }

                case ExpressionType.BranchOp:
                {
                    var o = value as BranchOp;
                    args.Add(CreateAssertIndirection(ref o.Left, locals, Namescope));
                    args.Add(CreateAssertIndirection(ref o.Right, locals, Namescope));
                    break;
                }

                case ExpressionType.CallMethod:
                {
                    var o = value as CallMethod;
                    for (int i = 0; i < o.Arguments.Length; i++)
                    {
                        args.Add(CreateAssertIndirection(ref o.Arguments[i], locals, Namescope));
                    }
                    break;
                }
                }

                var result = ILFactory.CallMethod(s.Source, "Uno.Diagnostics.Debug", "Assert", args.ToArray());

                while (locals.Count > 0)
                {
                    result = new SequenceOp(locals.RemoveLast(), result);
                }

                return(result);
            }

            case AstStatementType.DebugLog:
            {
                if (!Environment.Debug)
                {
                    return(new NoOp(e.Source, "Stripped debug_log"));
                }
                var s       = (AstValueStatement)e;
                var message = CompileExpression(s.Value);
                return(ILFactory.CallMethod(s.Source, "Uno.Diagnostics.Log", "Debug", message));
            }

            case AstStatementType.BuildError:
                return(CreateBuildError(e.Source, true));

            case AstStatementType.BuildWarning:
                return(CreateBuildError(e.Source, false));

            case AstStatementType.BuildErrorMessage:
            {
                var s = (AstValueStatement)e;
                return(CreateBuildError(e.Source, true, s.Value));
            }

            case AstStatementType.BuildWarningMessage:
            {
                var s = (AstValueStatement)e;
                return(CreateBuildError(e.Source, false, s.Value));
            }
            }

            Log.Error(e.Source, ErrorCode.I3411, "Unknown statement type <" + e.StatementType + ">");
            return(Expression.Invalid);
        }
        public PartialExpression ResolveExpression(AstExpression e, int?typeParamCount)
        {
            switch (e.ExpressionType)
            {
            default:
                return(new PartialValue(CompileExpression(e)));

            case AstExpressionType.Global:
                return(new PartialNamespace(e.Source, Compiler.Data.IL));

            case AstExpressionType.Void:
                return(new PartialType(e.Source, DataType.Void));

            case AstExpressionType.This:
                return(new PartialThis(e.Source));

            case AstExpressionType.Identifier:
                return(ResolveIdentifier(e as AstIdentifier, typeParamCount));

            case AstExpressionType.Member:
                return(ResolveMember(e as AstMember, typeParamCount));

            case AstExpressionType.LookUp:
                return(ResolveLookUp(e as AstCall));

            case AstExpressionType.BuiltinType:
                return(new PartialType(e.Source,
                                       Essentials.BuiltinTypes[(int)((AstBuiltinType)e).BuiltinType]));

            case AstExpressionType.Parameterizer:
            {
                var s = e as AstParameterizer;

                var args = new DataType[s.Arguments.Count];
                for (int i = 0; i < args.Length; i++)
                {
                    args[i] = NameResolver.GetType(Namescope, s.Arguments[i]);
                }

                var b = ResolveExpression(s.Base, s.Arguments.Count);

                var mg = b as PartialMethodGroup;
                if (mg != null)
                {
                    var methods = new Method[mg.Methods.Count];

                    for (int i = 0, l = mg.Methods.Count; i < l; i++)
                    {
                        methods[i] = TypeBuilder.Parameterize(s.Source, mg.Methods[i], args);
                    }

                    return(new PartialMethodGroup(s.Source, mg.Object, mg.IsQualified, methods));
                }

                var eg = b as PartialExtensionGroup;
                if (eg != null)
                {
                    var methods = new Method[eg.Methods.Count];

                    for (int i = 0, l = eg.Methods.Count; i < l; i++)
                    {
                        methods[i] = TypeBuilder.Parameterize(s.Source, eg.Methods[i], args);
                    }

                    return(new PartialExtensionGroup(s.Source, eg.Object, methods));
                }

                var dt = b as PartialType;
                return(dt != null && dt.Type.IsGenericDefinition
                            ? new PartialType(s.Source, TypeBuilder.Parameterize(s.Source, dt.Type, args)) :
                       !b.IsInvalid
                            ? PartialError(s.Source, ErrorCode.E2041, b.Quote() + " is not a generic method or type definition")
                            : PartialExpression.Invalid);
            }
            }
        }