예제 #1
0
파일: NaryType.cs 프로젝트: Ancestry/DotQL
        public override ExpressionContext CompileBinaryExpression(Compiler compiler, Frame frame, ExpressionContext left, Parse.BinaryExpression expression, BaseType typeHint)
        {
            switch (expression.Operator)
            {
                case Parse.Operator.Dereference:
                    return CompileDereference(compiler, frame, left, expression, typeHint);

                default: return base.CompileBinaryExpression(compiler, frame, left, expression, typeHint);
            }
        }
예제 #2
0
파일: VoidType.cs 프로젝트: Ancestry/DotQL
 public override ExpressionContext CompileUnaryExpression(Compiler compiler, Frame frame, ExpressionContext inner, Parse.UnaryExpression expression, BaseType typeHint)
 {
     throw NotSupported(expression);
 }
예제 #3
0
파일: BaseType.cs 프로젝트: Ancestry/DotQL
 public virtual ExpressionContext Convert(ExpressionContext expression, BaseType target)
 {
     throw new NotImplementedException(String.Format("Conversion from {0} to {1} is not supported.", expression.Type, target));
 }
예제 #4
0
파일: BaseType.cs 프로젝트: Ancestry/DotQL
 public virtual ExpressionContext CompileExtractExpression(Compiler compiler, Frame frame, ExpressionContext left, Parse.ExtractExpression expression, BaseType typeHint)
 {
     throw new CompilerException(expression, CompilerException.Codes.OperatorNotSupported, Parse.Keywords.Extract, GetType());
 }
예제 #5
0
파일: ListType.cs 프로젝트: Ancestry/DotQL
 public ListType(BaseType of)
 {
     Of = of;
 }
예제 #6
0
        // Restriction
        public override ExpressionContext CompileExtractExpression(Compiler compiler, Frame frame, ExpressionContext left, Parse.ExtractExpression expression, BaseType typeHint)
        {
            var local = compiler.AddFrame(frame, expression);
            var alreadyOptional = left.Type is OptionalType;
            var memberNative = left.Type.GetNative(compiler.Emitter);
            var resultType = alreadyOptional ? left.Type : new OptionalType(left.Type);
            var resultNative = resultType.GetNative(compiler.Emitter);

            // Register value symbol
            LocalBuilder valueLocal = null;
            var localSymbol = new Object();
            local.Add(expression.Condition, Name.FromComponents(Parse.ReservedWords.Value), localSymbol);
            compiler.ContextsBySymbol.Add
            (
                localSymbol,
                new ExpressionContext
                (
                    null,
                    left.Type,
                    left.Characteristics,
                    m => { m.IL.Emit(OpCodes.Ldloc, valueLocal); }
                )
            );

            var condition = compiler.CompileExpression(local, expression.Condition, SystemTypes.Boolean);
            if (!(condition.Type is BooleanType))
                throw new CompilerException(expression.Condition, CompilerException.Codes.IncorrectType, condition.Type, "Boolean");

            return
                new ExpressionContext
                (
                    expression,
                    resultType,
                    Compiler.MergeCharacteristics(left.Characteristics, condition.Characteristics),
                    m =>
                    {
                        var nullLabel = m.IL.DefineLabel();
                        var endLabel = m.IL.DefineLabel();

                        // Register value argument
                        valueLocal = m.DeclareLocal(expression, memberNative, Parse.ReservedWords.Value);
                        left.EmitGet(m);
                        m.IL.Emit(OpCodes.Stloc, valueLocal);

                        condition.EmitGet(m);
                        m.IL.Emit(OpCodes.Brfalse, nullLabel);

                        // Passed condition
                        if (!alreadyOptional && memberNative.IsValueType)
                        {
                            var optionalLocal = m.DeclareLocal(expression, resultNative, Parse.ReservedWords.Value);
                            m.IL.Emit(OpCodes.Ldloca, optionalLocal);
                            m.IL.Emit(OpCodes.Ldloc, valueLocal);
                            m.IL.Emit(OpCodes.Call, resultNative.GetConstructor(new System.Type[] { left.Type.GetNative(compiler.Emitter) }));
                            m.IL.Emit(OpCodes.Ldloc, optionalLocal);
                        }
                        else
                            m.IL.Emit(OpCodes.Ldloc, valueLocal);
                        m.IL.Emit(OpCodes.Br, endLabel);

                        // Failed condition
                        m.IL.MarkLabel(nullLabel);
                        if (!alreadyOptional && memberNative.IsValueType)
                        {
                            var optionalLocal = m.DeclareLocal(expression, resultNative, Parse.ReservedWords.Value);
                            m.IL.Emit(OpCodes.Ldloca, optionalLocal);
                            m.IL.Emit(OpCodes.Initobj, resultNative);
                            m.IL.Emit(OpCodes.Ldloc, optionalLocal);
                        }
                        else if (alreadyOptional && memberNative.IsValueType)
                        {
                            m.IL.Emit(OpCodes.Ldloca, valueLocal);
                            m.IL.Emit(OpCodes.Initobj, resultNative);
                            m.IL.Emit(OpCodes.Ldloc, valueLocal);
                        }
                        else
                            m.IL.Emit(OpCodes.Ldnull);

                        m.IL.MarkLabel(endLabel);
                    }
                );
        }
예제 #7
0
파일: SetType.cs 프로젝트: Ancestry/DotQL
 public SetType(BaseType of)
 {
     Of = of;
 }
예제 #8
0
파일: NaryType.cs 프로젝트: Ancestry/DotQL
        // Restriction
        public override ExpressionContext CompileExtractExpression(Compiler compiler, Frame frame, ExpressionContext left, Parse.ExtractExpression expression, BaseType typeHint)
        {
            var memberType = ((NaryType)left.Type).Of;
            var memberNative = left.NativeType ?? memberType.GetNative(compiler.Emitter);

            var local = compiler.AddFrame(frame, expression);

            // Prepare index and value symbols
            var indexSymbol = PrepareValueIndexContext(compiler, left, expression.Condition, memberType, memberNative, local);

            // Compile condition
            var condition = compiler.CompileExpression(local, expression.Condition, SystemTypes.Boolean);
            if (!(condition.Type is BooleanType))
                throw new CompilerException(expression.Condition, CompilerException.Codes.IncorrectType, condition.Type, "Boolean");

            var indexReferenced = compiler.References.ContainsKey(indexSymbol);

            return
                new ExpressionContext
                (
                    expression,
                    left.Type,
                    Compiler.MergeCharacteristics(left.Characteristics, condition.Characteristics),
                    m =>
                    {
                        // Create a new private method for the condition
                        var typeBuilder = (TypeBuilder)m.Builder.DeclaringType;
                        var innerMethod =
                            new MethodContext
                            (
                                typeBuilder.DefineMethod
                                (
                                    "Where" + expression.GetHashCode(),
                                    MethodAttributes.Private | MethodAttributes.Static,
                                    typeof(bool),	// return type
                                    indexReferenced ? new System.Type[] { memberNative, typeof(int) } : new System.Type[] { memberNative }	// param types
                                )
                            );
                        condition.EmitGet(innerMethod);
                        innerMethod.IL.Emit(OpCodes.Ret);

                        left.EmitGet(m);

                        // TODO: Force ordering to left if Set and index is referenced

                        // Instantiate a delegate pointing to the new method
                        m.IL.Emit(OpCodes.Ldnull);				// instance
                        m.IL.Emit(OpCodes.Ldftn, innerMethod.Builder);	// method
                        var funcType =
                            indexReferenced
                                ? System.Linq.Expressions.Expression.GetFuncType(memberNative, typeof(int), typeof(bool))
                                : System.Linq.Expressions.Expression.GetFuncType(memberNative, typeof(bool));
                        m.IL.Emit
                        (
                            OpCodes.Newobj,
                            funcType.GetConstructor(new[] { typeof(object), typeof(IntPtr) })
                        );

                        funcType = indexReferenced ? typeof(Func<ReflectionUtility.T, int, bool>) : typeof(Func<ReflectionUtility.T, bool>);
                        var where = typeof(System.Linq.Enumerable).GetMethodExt("Where", new System.Type[] { typeof(IEnumerable<ReflectionUtility.T>), funcType });
                        where = where.MakeGenericMethod(memberNative);

                        m.IL.EmitCall(OpCodes.Call, where, null);
                    }
                );
        }
예제 #9
0
파일: NaryType.cs 프로젝트: Ancestry/DotQL
        private static object PrepareValueIndexContext(Compiler compiler, ExpressionContext left, Parse.Statement statement, BaseType memberType, System.Type memberNative, Frame local)
        {
            // Register value argument
            var valueSymbol = new Object();
            local.Add(statement, Name.FromComponents(Parse.ReservedWords.Value), valueSymbol);
            compiler.ContextsBySymbol.Add
            (
                valueSymbol,
                new ExpressionContext
                (
                    null,
                    memberType,
                    left.Characteristics,
                    m => { m.IL.Emit(OpCodes.Ldarg_0); }
                )
            );

            // Register index argument
            var indexSymbol = new Object();
            local.Add(statement, Name.FromComponents(Parse.ReservedWords.Index), indexSymbol);
            compiler.ContextsBySymbol.Add
            (
                indexSymbol,
                new ExpressionContext
                (
                    null,
                    SystemTypes.Int32,
                    Characteristic.Default,
                    m => { m.IL.Emit(OpCodes.Ldarg_1); }
                )
            );

            // If the members are tuples, declare locals for each field
            if (memberType is TupleType)
            {
                var tupleType = (TupleType)memberType;
                foreach (var attribute in tupleType.Attributes)
                {
                    local.Add(attribute.Key.ToID(), attribute);
                    compiler.ContextsBySymbol.Add
                    (
                        attribute,
                        new ExpressionContext
                        (
                            null,
                            attribute.Value,
                            Characteristic.Default,
                            m =>
                            {
                                m.IL.Emit(OpCodes.Ldarg_0);	// value
                                m.IL.Emit(OpCodes.Ldfld, memberNative.GetField(attribute.Key.ToString()));
                            }
                        )
                    );
                }

                // TODO: Add references
            }
            return indexSymbol;
        }
예제 #10
0
 public OptionalType(BaseType of)
 {
     Of = of;
 }