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