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;
        }