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); } }
public override ExpressionContext CompileUnaryExpression(Compiler compiler, Frame frame, ExpressionContext inner, Parse.UnaryExpression expression, BaseType typeHint) { throw NotSupported(expression); }
public virtual ExpressionContext Convert(ExpressionContext expression, BaseType target) { throw new NotImplementedException(String.Format("Conversion from {0} to {1} is not supported.", expression.Type, target)); }
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()); }
public ListType(BaseType of) { Of = of; }
// 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); } ); }
public SetType(BaseType of) { Of = of; }
// 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); } ); }
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; }
public OptionalType(BaseType of) { Of = of; }