public static void BoundTransform(AffeCompilerState state, Expression[] exprs) { Assert.AreEqual(2, exprs.Length, "Argument count to BoundTransform"); state.CastTo(exprs[0], typeof(double)).Emit(state); state.CastTo(exprs[1], typeof(double)).Emit(state); state.ILGenerator.Emit(OpCodes.Call, typeof(Math).GetMethod("Pow")); state.ILGenerator.Emit(OpCodes.Conv_R4); }
public static void abs(AffeCompilerState comp, Expression[] exp) { if (exp.Length != 1) { throw new ArgumentException("Wrong number of arguments to method."); } ILGenerator il = comp.ILGenerator; Label l = il.DefineLabel(); exp[0].Emit(comp); il.Emit(OpCodes.Dup); il.Emit(OpCodes.Ldc_R4, 0f); il.Emit(OpCodes.Bge_Un, l); il.Emit(OpCodes.Neg); il.MarkLabel(l); }
public override void Emit(AffeCompilerState state) { this.Expression.Emit(state); ILGenerator il = state.ILGenerator; // If the types are the same, why are we casting? if (this.Expression.Type == this.Type) return; // Check for boxing. if (this.Expression.Type.IsValueType && !this.Type.IsValueType) { if (!this.Type.IsAssignableFrom(this.Expression.Type)) throw new AffeException("Cannot perform the required cast to box.", this); il.Emit(OpCodes.Box, this.Expression.Type); return; } // Check for unboxing to primitives. if (this.Type.IsPrimitive && this.Expression.Type == typeof(object)) { il.Emit(OpCodes.Unbox, this.Type); if (this.Type == typeof(bool) || this.Type == typeof(sbyte)) { il.Emit(OpCodes.Ldind_I1); } else if (this.Type == typeof(byte)) { il.Emit(OpCodes.Ldind_U1); } else if (this.Type == typeof(short)) { il.Emit(OpCodes.Ldind_I2); } else if (this.Type == typeof(ushort) || this.Type == typeof(char)) { il.Emit(OpCodes.Ldind_U2); } else if (this.Type == typeof(int)) { il.Emit(OpCodes.Ldind_I4); } else if (this.Type == typeof(uint)) { il.Emit(OpCodes.Ldind_U4); } else if (this.Type == typeof(long) || this.Type == typeof(ulong)) { il.Emit(OpCodes.Ldind_I8); } else if (this.Type == typeof(float)) { il.Emit(OpCodes.Ldind_R4); } else if (this.Type == typeof(double)) { il.Emit(OpCodes.Ldind_R8); } else { throw new AffeException("Unable to unbox type.", this); } return; } // Check for unboxing. if (!this.Expression.Type.IsValueType && this.Type.IsValueType) { il.Emit(OpCodes.Unbox, this.Type); il.Emit(OpCodes.Ldobj, this.Type); return; } // Check for object assignment. if (!this.Type.IsValueType && !this.Expression.Type.IsValueType) { // If the type is assignable then it's free. if (this.Type.IsAssignableFrom(this.Expression.Type)) return; // Otherwise we must cast. il.Emit(OpCodes.Castclass, this.Type); return; } // If we got this far, the expression is a primitive. // Convert to the required type. // Bool is handled in the analysis phase by changing the tree. if (this.Type == typeof(sbyte)) { il.Emit(OpCodes.Conv_I1); } else if (this.Type == typeof(byte)) { il.Emit(OpCodes.Conv_U1); } else if (this.Type == typeof(short)) { il.Emit(OpCodes.Conv_I2); } else if (this.Type == typeof(ushort) || this.Type == typeof(char)) { il.Emit(OpCodes.Conv_U2); } else if (this.Type == typeof(int)) { il.Emit(OpCodes.Conv_I4); } else if (this.Type == typeof(uint)) { il.Emit(OpCodes.Conv_U4); } else if (this.Type == typeof(long)) { il.Emit(OpCodes.Conv_I8); } else if (this.Type == typeof(ulong)) { il.Emit(OpCodes.Conv_U8); } else if (this.Type == typeof(float)) { il.Emit(OpCodes.Conv_R4); } else if (this.Type == typeof(double)) { il.Emit(OpCodes.Conv_R8); } else { throw new AffeException("Unable to convert type.", this); } }
public override Node Analyze(AffeCompilerState state) { this.mExpression = (Expression) this.mExpression.Analyze(state); return this.AnalyzeShallow(state); }
public override Node Analyze(AffeCompilerState state) { this.Call = (CallExpression) this.Call.Analyze(state); return this; }
public override Node Analyze(AffeCompilerState state) { BindingFlags isstatic = BindingFlags.Instance; // Check for static calls. Type target = state.CheckForTypeExpression(this.Target); // If it's not a type, consider it an expression. if (target == null) { this.Target = (Expression) this.Target.Analyze(state); target = this.Target.Type; } else { isstatic = BindingFlags.Static; } Type[] types = new Type[this.Arguments.Count]; for (int i = 0; i < types.Length; i++) { this.Arguments[i] = (Expression) this.Arguments[i].Analyze(state); types[i] = this.Arguments[i].Type; } MethodInfo mi; try { mi = target.GetMethod(this.Name.Name, isstatic | BindingFlags.Public | BindingFlags.FlattenHierarchy, null, types, null); } catch (AmbiguousMatchException) { throw new AffeException("Method call is ambiguous.", this); } catch (Exception) { mi = null; } if (mi == null) throw new AffeException("Method not found on class.", this); // GetMethod will return the closest match it can, not an exact // match. This is nifty. Now we just have to cast where // appropriate. ParameterInfo[] param = mi.GetParameters(); for (int i = 0; i < this.Arguments.Count; i++) { this.Arguments[i] = state.CastTo(this.Arguments[i], param[i].ParameterType); } this.MethodInfo = mi; this.Type = mi.ReturnType; return this; }
public override Node Analyze(AffeCompilerState state) { Symbol s = state.Scope.GetSymbol(this.Name.Name); if (s == null) throw new AffeException("No such method.", this); if (s is TransformSymbol) { this.Type = ((TransformSymbol) s).ResultType; for (int i = 0; i < this.Arguments.Count; i++) { this.Arguments[i] = (Expression) this.Arguments[i].Analyze(state); } } else if (s is MethodSymbol) { MethodSymbol ms = (MethodSymbol) s; ParameterInfo[] param = ms.Method.GetParameters(); if (this.Arguments.Count != param.Length) throw new AffeException("Incorrect argument count to method.", this); for (int i = 0; i < param.Length; i++) { this.Arguments[i] = state.CastTo((Expression) this.Arguments[i].Analyze(state), param[i].ParameterType); } this.Type = ms.Method.ReturnType; } else { throw new AffeException("Not a method.", this); } return this; }
public override Node Analyze(AffeCompilerState state) { this.Condition = state.CastTo((Expression) this.Condition.Analyze(state), typeof(bool)); return base.Analyze(state); }
public override void Emit(AffeCompilerState state) { ILGenerator il = state.ILGenerator; // First check for an operator overload. if (this.mOperatorOverload != null) { this.Left.Emit(state); this.Right.Emit(state); il.Emit(OpCodes.Call, this.mOperatorOverload); return; } // Band and Bor are special cases. switch (this.Operator) { case Operator.Bor: { Label istrue = il.DefineLabel(); Label isfalse = il.DefineLabel(); this.Left.Emit(state); il.Emit(OpCodes.Brtrue, istrue); this.Right.Emit(state); il.Emit(OpCodes.Br, isfalse); il.MarkLabel(istrue); il.Emit(OpCodes.Ldc_I4_1); il.MarkLabel(isfalse); return; } case Operator.Band: { Label istrue = il.DefineLabel(); Label isfalse = il.DefineLabel(); this.Left.Emit(state); il.Emit(OpCodes.Brfalse, isfalse); this.Right.Emit(state); il.Emit(OpCodes.Br, istrue); il.MarkLabel(isfalse); il.Emit(OpCodes.Ldc_I4_0); il.MarkLabel(istrue); return; } } this.Left.Emit(state); this.Right.Emit(state); switch (this.Operator) { case Operator.Add: il.Emit(OpCodes.Add); break; case Operator.And: il.Emit(OpCodes.And); break; case Operator.Divide: il.Emit(OpCodes.Div); break; case Operator.Eq: il.Emit(OpCodes.Ceq); break; case Operator.Gt: il.Emit(OpCodes.Cgt); break; case Operator.Gte: il.Emit(OpCodes.Clt); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ceq); break; case Operator.Lt: il.Emit(OpCodes.Clt); break; case Operator.Lte: il.Emit(OpCodes.Cgt); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ceq); break; case Operator.Minus: il.Emit(OpCodes.Sub); break; case Operator.Mod: il.Emit(OpCodes.Rem); break; case Operator.Multiply: il.Emit(OpCodes.Mul); break; case Operator.Ne: il.Emit(OpCodes.Ceq); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ceq); break; case Operator.Or: il.Emit(OpCodes.Or); break; default: throw new AffeException("Unknown operator.", this); } }
public override Node Analyze(AffeCompilerState state) { this.Left = (Expression) this.Left.Analyze(state); this.Right = (Expression) this.Right.Analyze(state); // Look on the left and right types for an operator overload. MethodInfo opm = this.CheckForOperatorCall(this.Left.Type); if (opm == null) opm = this.CheckForOperatorCall(this.Right.Type); if (opm != null) { // There is an operator overload. No further analysis is required. this.mOperatorOverload = opm; this.Type = opm.ReturnType; return this; } if (!this.Left.Type.IsValueType) { if (this.Right.Type.IsValueType) throw new AffeException("Cannot compare reference and value types.", this); if (this.Operator != Operator.Eq && this.Operator != Operator.Ne) throw new AffeException("Cannot apply that operator to object references.", this); } else if (!AffeCompilerState.IsNumeric(this.Left.Type) || !AffeCompilerState.IsNumeric(this.Right.Type)) throw new AffeException("Cannot operate on non-numeric values.", this); Type opType; if (this.Operator == Operator.And || this.Operator == Operator.Or) { opType = typeof(int); } else if (this.Operator == Operator.Bor || this.Operator == Operator.Band) { opType = typeof(bool); } else { opType = AffeCompilerState.FindCompatibleType(this.Left.Type, this.Right.Type); // Division forces a cast to floating-point. if (this.Operator == Operator.Divide && opType != typeof(float) && opType != typeof(double)) opType = typeof(float); } this.Left = state.CastTo(this.Left, opType); this.Right = state.CastTo(this.Right, opType); if (this.Operator == Operator.Eq || this.Operator == Operator.Gt || this.Operator == Operator.Gte || this.Operator == Operator.Lt || this.Operator == Operator.Lte || this.Operator == Operator.Ne || this.Operator == Operator.Bor || this.Operator == Operator.Band) { this.Type = typeof(bool); } else { this.Type = opType; } return this; }
public override void EmitForInvocation(AffeCompilerState state) { throw new InvalidOperationException("Cannot invoke on null."); }
public override void Emit(AffeCompilerState state) { state.ILGenerator.Emit(OpCodes.Ldnull); }
public virtual void Emit(AffeCompilerState state) { }
public virtual Node Analyze(AffeCompilerState state) { return this; }
public abstract void EmitStore(AffeCompilerState state, Expression expr);
public override Node Analyze(AffeCompilerState state) { this.Body = (Block) this.Body.Analyze(state); return this; }
public override Node Analyze(AffeCompilerState state) { this.Rvalue = (Expression) this.Rvalue.Analyze(state); Type dtype = null; TypeSymbol ts = state.Scope.GetSymbol(this.Type.Name) as TypeSymbol; if (ts == null) throw new AffeException("Not a type.", this.Type); if (ts.Type == typeof(void)) { // Void TypeSymbol means this is our inferencing type. dtype = this.Rvalue.Type; } else { dtype = ts.Type; } string name = ((IdentifierExpression) this.Lvalue).Identifier.Name; if (state.Scope.GetSymbol(name) != null) throw new AffeException("Identifier previously declared.", this.Lvalue); VariableSymbol vs = new VariableSymbol(name, dtype); vs.Local = state.ILGenerator.DeclareLocal(dtype); state.Scope.AddSymbol(vs); this.Rvalue = state.CastTo(this.Rvalue, dtype); return this; }
public override void Emit(AffeCompilerState state) { if (this.mBoolean) state.ILGenerator.Emit(OpCodes.Ldc_I4_1); else state.ILGenerator.Emit(OpCodes.Ldc_I4_0); }
public override void Emit(AffeCompilerState state) { ILGenerator il = state.ILGenerator; Label start = il.DefineLabel(); Label end = il.DefineLabel(); state.PushLoopState(new LoopState(start, end)); il.MarkLabel(start); this.Condition.Emit(state); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Beq, end); this.Body.Emit(state); il.Emit(OpCodes.Br, start); il.MarkLabel(end); state.PopLoopState(); }
public override Node Analyze(AffeCompilerState state) { TypeSymbol ts = state.Scope.GetSymbol(this.Type.Name) as TypeSymbol; if (ts == null) throw new AffeException("Not a type.", this.Type); if (ts.Type == typeof(void)) { // Void TypeSymbol means this is our inferencing type. throw new AffeException("Persistent variables cannot be type-inferenced.", this); } Type dtype = ts.Type; string name = this.Name.Name; if (state.Scope.GetSymbol(name) != null) throw new AffeException("Identifier previously declared.", this.Name); VariableSymbol vs = new VariableSymbol(name, dtype); vs.Local = state.ILGenerator.DeclareLocal(dtype); state.Scope.AddSymbol(vs); state.MakePersistent(vs); return this; }
public override void Emit(AffeCompilerState state) { Symbol s = state.Scope.GetSymbol(this.Name.Name); if (s == null) // Should never happen if the analysis was run. throw new AffeException("Symbol not found.", this); ILGenerator il = state.ILGenerator; if (s is MethodSymbol) { MethodInfo mi = ((MethodSymbol) s).Method; if (!mi.IsStatic) il.Emit(OpCodes.Ldarg_0); foreach (Expression exp in this.Arguments) exp.Emit(state); il.Emit(mi.IsStatic ? OpCodes.Call : OpCodes.Callvirt, mi); } else if (s is TransformSymbol) { ((TransformSymbol) s).Method.Invoke(null, new object[] { state, this.Arguments.ToArray() }); } else { // Should never happen if the analysis was run. throw new AffeException("Not a method.", this); } }
public override void Emit(AffeCompilerState state) { state.ILGenerator.Emit(OpCodes.Leave, state.ReturnLabel); }
public override void Emit(AffeCompilerState state) { MethodInfo mi = this.mMethodInfo; ILGenerator il = state.ILGenerator; // If it's a static call then we don't need to emit the target. if (!mi.IsStatic) this.Target.EmitForInvocation(state); foreach (Expression ex in this.Arguments) ex.Emit(state); if (mi.IsStatic) il.Emit(OpCodes.Call, mi); else il.Emit(OpCodes.Callvirt, mi); }
public override void Emit(AffeCompilerState state) { if (this.mString == null) state.ILGenerator.Emit(OpCodes.Ldnull); else state.ILGenerator.Emit(OpCodes.Ldstr, this.mString); }
public override void Emit(AffeCompilerState state) { this.mCall.Emit(state); if (this.mCall.Type != typeof(void)) state.ILGenerator.Emit(OpCodes.Pop); }
public override Node Analyze(AffeCompilerState state) { this.Conditional = (Expression) this.Conditional.Analyze(state); this.Conditional = state.CastTo(this.Conditional, typeof(bool)); this.IfTrue = (Expression) this.IfTrue.Analyze(state); this.IfFalse = (Expression) this.IfFalse.Analyze(state); Type t = AffeCompilerState.FindCompatibleType(this.IfTrue.Type, this.IfFalse.Type); this.IfTrue = state.CastTo(this.IfTrue, t); this.IfFalse = state.CastTo(this.IfFalse, t); this.Type = t; return this; }
public Node AnalyzeShallow(AffeCompilerState state) { if (this.Type == null) { if (this.TypeIdentifier == null) throw new AffeException("One of Type and TypeIdentifier must not be null.", this); TypeSymbol s = state.Scope.GetSymbol(this.TypeIdentifier.Name) as TypeSymbol; if (s == null) throw new AffeException("Destination type could not be resolved.", this.TypeIdentifier); if (s.Type == null) throw new AffeException("Destination type must not be the inferencing type.", this.TypeIdentifier); this.Type = s.Type; } if (this.mExpression.Type == this.Type) return this.mExpression; if (this.Type == typeof(bool)) { // If this is a reference type then test if it's not null. if (!this.Expression.Type.IsValueType) return new OperatorExpression(Operator.Ne, this.Expression, new NullExpression()); // If we're casting to bool then we are essentially testing if // this.Expression != 0. This fails for non-numeric types. return new OperatorExpression(Operator.Ne, this.Expression, new IntegerExpression(0)).Analyze(state); } return this; }
public override void Emit(AffeCompilerState state) { ILGenerator il = state.ILGenerator; Label istrue = il.DefineLabel(); Label isfalse = il.DefineLabel(); this.Conditional.Emit(state); il.Emit(OpCodes.Brtrue, istrue); this.IfFalse.Emit(state); il.Emit(OpCodes.Br, isfalse); il.MarkLabel(istrue); this.IfTrue.Emit(state); il.MarkLabel(isfalse); }
public override void Emit(AffeCompilerState state) { state.ILGenerator.Emit(OpCodes.Br, state.GetLoopState(0).BeginLabel); }
public override Node Analyze(AffeCompilerState state) { this.Expression = (Expression) this.Expression.Analyze(state); if (!AffeCompilerState.IsNumeric(this.Expression.Type)) throw new AffeException("Cannot operate on non-numeric values.", this); switch (this.Operator) { case Operator.Neg: this.Type = this.Expression.Type; break; case Operator.Not: this.Expression = state.CastTo(this.Expression, typeof(bool)); this.Type = typeof(bool); break; default: throw new AffeException("Unknown operator.", this); } return this; }
public override void Emit(AffeCompilerState state) { this.Expression.Emit(state); switch (this.Operator) { case Operator.Neg: state.ILGenerator.Emit(OpCodes.Neg); break; case Operator.Not: state.ILGenerator.Emit(OpCodes.Ldc_I4_0); state.ILGenerator.Emit(OpCodes.Ceq); break; default: throw new AffeException("Unknown operator.", this); } }
public override void EmitStore(AffeCompilerState state, Expression expr) { this.Target.Emit(state); state.ILGenerator.Emit(OpCodes.Ldstr, this.Member.Name); expr.Emit(state); state.ILGenerator.Emit(OpCodes.Call, PerformWriteInvokeInfo); }