public override void EmitStore(AffeCompilerState state, Expression expr) { if (!this.CanWrite) throw new AffeException("Target is read-only.", this); PropertyInfo pi = this.mMemberInfo as PropertyInfo; FieldInfo fi = this.mMemberInfo as FieldInfo; bool stc = (pi != null) ? pi.GetGetMethod().IsStatic : fi.IsStatic; if (!stc) this.Target.Emit(state); expr.Emit(state); if (pi != null) state.ILGenerator.Emit(stc ? OpCodes.Call : OpCodes.Callvirt, pi.GetSetMethod()); else state.ILGenerator.Emit(stc ? OpCodes.Stsfld : OpCodes.Stfld, fi); }
public DataInvokationExpression(Expression target, Identifier member) { this.Target = target; this.Member = member; }
public Expression CastTo(Expression e, Type type) { if (e.Type == type) return e; if (type == typeof(void)) throw new AffeException("Cannot cast to void.", e); if (e.Type == typeof(void)) throw new AffeException("Cannot cast from void.", e); if (e is FloatExpression && type == typeof(string)) return new StringExpression(((FloatExpression) e).Float.ToString()); // More checking during the compile run. return (Expression) new CastExpression(e, type).AnalyzeShallow(this); }
public Assignment(Lvalue lvalue, Expression rvalue) { this.Lvalue = lvalue; this.Rvalue = rvalue; }
public CastExpression(Expression expression, Identifier type) { this.Expression = expression; this.TypeIdentifier = type; }
public WhileLoop(Expression condition, Block body) : base(body) { this.Condition = condition; }
public CallInvokationExpression(Expression target, Identifier name, IEnumerable<Expression> arguments) { this.Target = target; this.Name = name; if (arguments == null) throw new ArgumentNullException("arguments"); this.mArguments = new List<Expression>(arguments); }
public override void EmitStore(AffeCompilerState state, Expression expr) { MethodInfo setter = null; if (this.mIndexer != null) setter = this.mIndexer.GetSetMethod(); if (setter == null || !setter.IsStatic) this.Expression.Emit(state); foreach (Expression e in this.Index) e.Emit(state); expr.Emit(state); if (this.mIndexer != null) { if (setter == null) throw new AffeException("Indexer is read-only.", this); state.ILGenerator.Emit(setter.IsStatic ? OpCodes.Call : OpCodes.Callvirt, setter); } else { //state.ILGenerator.Emit(OpCodes.Stelem, this.Type); EmitStelem(state.ILGenerator, this.Type); } }
public LateBoundCallInvokationExpression(Expression target, Identifier name, IEnumerable<Expression> arguments) : base(target, name, arguments) { }
public IndexedExpression(Expression expression, List<Expression> index) { this.Expression = expression; this.mIndex = index; }
public IndexedExpression(Expression expression, IEnumerable<Expression> index) { this.Expression = expression; this.mIndex = new List<Expression>(index); }
public IfElse(Expression condition, Block ifstatements, Block elsestatements) : base(condition, ifstatements) { this.ElseStatements = elsestatements; }
public If(Expression condition, Block ifstatements) { this.Condition = condition; this.IfStatements = ifstatements; }
public override void EmitStore(AffeCompilerState state, Expression expr) { string target = this.Identifier.Name; Symbol s = state.Scope.GetSymbol(target); if (s == null) { // This should never happen if the analysis was run. throw new AffeException("Unknown symbol.", this); } if (!(s is VariableSymbol) && !(s is FieldSymbol)) throw new AffeException("Assignment target is not a variable or field.", this); if (s is FieldSymbol) { FieldInfo fi = ((FieldSymbol) s).Field; if (fi.IsInitOnly) throw new AffeException("Cannot assign to a read-only field.", this); if (!fi.IsStatic) state.ILGenerator.Emit(OpCodes.Ldarg_0); } expr.Emit(state); if (s is VariableSymbol) { state.ILGenerator.Emit(OpCodes.Stloc, ((VariableSymbol) s).Local); } else { FieldInfo fi = ((FieldSymbol) s).Field; state.ILGenerator.Emit(fi.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fi); } }
public UnaryExpression(Operator @operator, Expression expression) { this.mOperator = @operator; this.Expression = expression; }
public LateBoundDataInvokationExpression(Expression target, Identifier member) : base(target, member) { }
public VariableDeclaration(Identifier type, Identifier lvalue, Expression rvalue) : base(new IdentifierExpression(lvalue), rvalue) { this.Type = type; }
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); }
public override Node Analyze(AffeCompilerState state) { this.Condition = state.CastTo((Expression) this.Condition.Analyze(state), typeof(bool)); return base.Analyze(state); }
public abstract void EmitStore(AffeCompilerState state, Expression expr);
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 OperatorExpression(Operator @operator, Expression left, Expression right) { this.mOperator = @operator; this.Left = left; this.Right = right; }
public CastExpression(Expression expression, Type type) { this.Expression = expression; this.Type = type; }
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 Node Analyze(AffeCompilerState state) { this.mExpression = (Expression) this.mExpression.Analyze(state); return this.AnalyzeShallow(state); }
public TernaryConditionalExpression(Expression conditional, Expression iftrue, Expression iffalse) { this.Conditional = conditional; this.IfTrue = iftrue; this.IfFalse = iffalse; }
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 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; }
internal Type CheckForTypeExpression(Expression e) { if (e is IdentifierExpression) { TypeSymbol ts = this.mScope.GetSymbol(((IdentifierExpression) e) .Identifier.Name) as TypeSymbol; if (ts != null && ts.Type != typeof(void)) { // Setting the expression type means we don't have to // check for a TypeSymbol later, since the expression // is not actualy emitted for static calls. e.Type = ts.Type; return ts.Type; } } return null; }
public override Node Analyze(AffeCompilerState state) { this.Rvalue = (Expression) this.Rvalue.Analyze(state); this.Lvalue = (Lvalue) this.Lvalue.Analyze(state); this.Rvalue = state.CastTo(this.Rvalue, this.Lvalue.Type); return this; }