static Statement Rewrite(VoidExpression ve) { var block = new List <Statement>(); var s = Rewrite(ve.Statement); if (s is BlockStatement) { block.AddRange(((BlockStatement)s).Statements); } else { block.Add(s); } block.Add(Ast.Return(Unspecified)); return(Rewrite(Ast.Block(block))); }
static Statement TryRewriteExpression(Expression ex) { //if (ex is BoundAssignment) //{ // var ba = (BoundAssignment)ex; // return Ast.Write(ba.Variable, ba.Value); //} if (ex is UnaryExpression && ex.NodeType == AstNodeType.Convert) { var ux = ex as UnaryExpression; return(TryRewriteExpression(ux.Operand)); } if (ex is VoidExpression) { VoidExpression ve = (VoidExpression)ex; return(Rewrite(ve.Statement)); } if (ex is CommaExpression) { var ce = ex as CommaExpression; var block = RewriteExpressions(ce.Expressions, Ast.Statement); return(Rewrite(Ast.Block(block))); } if (ex is ConditionalExpression) { var ce = ex as ConditionalExpression; if (ce.IfFalse == Unspecified || ce.IfFalse is MemberExpression && ((MemberExpression)ce.IfFalse).Member == Generator.Unspecified) { return(Ast.If(ce.Test, Rewrite(Ast.Statement(ce.IfTrue)))); } if (ce.IfTrue == Unspecified || ce.IfTrue is MemberExpression && ((MemberExpression)ce.IfTrue).Member == Generator.Unspecified) { return(Ast.If(Ast.Not(ce.Test), Rewrite(Ast.Statement(ce.IfFalse)))); } return(Ast.If(ce.Test, Rewrite(Ast.Statement(ce.IfTrue))).Else(Rewrite(Ast.Statement(ce.IfFalse)))); } return(null); }
protected internal virtual void PostWalk(VoidExpression node) { }
// VoidExpression protected internal virtual bool Walk(VoidExpression node) { return true; }
protected override void PostWalk(VoidExpression node) { node.Statement = Rewrite(node.Statement); base.PostWalk(node); }
public override void Visit(VoidExpression node) { unfinishedClone = new VoidExpression(GetCloneOf(node.Expression)); base.Visit(node); }
public override void Visit(VoidExpression node) { Visit((UnaryExpression)node); }
public override void Visit(VoidExpression node) { UpdateType(node, TypeCalculator.GetType(node)); }
public override void Visit(VoidExpression node) { AssignToImplicitReturn(node); }
private void DefineBuiltInFunctions() { #region add rootEnv.Symbols["add"] = new BuiltInFunction((env, args) => { // Check if all arguments are number expressions if (args.All(x => x is NumberExpression)) { return(new NumberExpression(args.Sum(x => (x as NumberExpression).Value))); } throw new UnexpectedArgumentTypeException("add"); }); #endregion #region sub rootEnv.Symbols["sub"] = new BuiltInFunction((env, args) => { int argCount = args.Count(); // Insufficient number of arguments if (argCount < 1) { throw new UnexpectedNumberOfArgumentsException("sub", ">= 1", argCount); } // Check if all arguments are number expressions if (args.All(x => x is NumberExpression)) { IEnumerable <int> values = args.Select(x => (x as NumberExpression).Value); return(new NumberExpression(values.First() - values.Skip(1).Sum())); } throw new UnexpectedArgumentTypeException("sub"); }); #endregion #region mul rootEnv.Symbols["mul"] = new BuiltInFunction((env, args) => { // Check if all arguments are number expressions if (args.All(x => x is NumberExpression)) { IEnumerable <int> values = args.Select(x => (x as NumberExpression).Value); int result = 1; foreach (int val in values) { result *= val; } return(new NumberExpression(result)); } throw new UnexpectedArgumentTypeException("mul"); }); #endregion #region div rootEnv.Symbols["div"] = new BuiltInFunction((env, args) => { int argCount = args.Count(); // Insufficient number of arguments if (argCount < 1) { throw new UnexpectedNumberOfArgumentsException("div", ">= 1", argCount); } // Check if all arguments are number expressions if (args.All(x => x is NumberExpression)) { IEnumerable <int> numExprs = args.Select(x => (x as NumberExpression).Value); int result = numExprs.First(); foreach (int val in numExprs.Skip(1)) { if (val == 0) { throw new FatalException("Unable to perform division by zero"); } result /= val; } return(new NumberExpression(result)); } throw new UnexpectedArgumentTypeException("div"); }); #endregion #region mod rootEnv.Symbols["mod"] = new BuiltInFunction((env, args) => { int argCount = args.Count(); // Insufficient number of arguments if (argCount < 1) { throw new UnexpectedNumberOfArgumentsException("mod", ">= 1", argCount); } // Check if all arguments are number expressions if (args.All(x => x is NumberExpression)) { IEnumerable <int> numExprs = args.Select(x => (x as NumberExpression).Value); int result = numExprs.First(); foreach (int val in numExprs.Skip(1)) { if (val == 0) { throw new FatalException("Unable to calculate the remainder after division by zero"); } result %= val; } return(new NumberExpression(result)); } throw new UnexpectedArgumentTypeException("mod"); }); #endregion #region print rootEnv.Symbols["print"] = new BuiltInFunction((env, args) => { foreach (IExpression expr in args) { PrintExpression(expr); } return(new VoidExpression()); }); #endregion #region batch rootEnv.Symbols["batch"] = new BuiltInFunction((env, args) => { // Evaluate the expressions one by one and return // the expression obtained by evaluating the last expression IExpression returnValue = new VoidExpression(); foreach (IExpression expr in args) { returnValue = expr.Evaluate(env); } return(returnValue); }, false); #endregion #region if rootEnv.Symbols["if"] = new BuiltInFunction((env, args) => { int argCount = args.Count(); // Iterate through conditions for (int i = 0, nConditions = argCount / 2; i < nConditions; i++) { // Get base index for this condition int baseIdx = i * 2; // Try to convert the condition expression to a numeric value NumberExpression condition = args.ElementAt(baseIdx).Evaluate(env) as NumberExpression; // Unable to convert the condition to a number expression if (condition == null) { throw new UnexpectedArgumentTypeException("if"); } // If the conditional evaluates to a truthy numeric value if (condition.BooleanValue) { // Return the expression supplied as the next argument return(args.ElementAt(baseIdx + 1).Evaluate(env)); } } // Final else statement if (argCount % 2 == 1) { return(args.ElementAt(argCount - 1).Evaluate(env)); } // No condition met else { return(new VoidExpression()); } }, false); #endregion #region not rootEnv.Symbols["not"] = new BuiltInFunction((env, args) => { int argCount = args.Count(); // The function must be applied to a single number expression if (argCount != 1) { throw new UnexpectedNumberOfArgumentsException("not", 1, argCount); } NumberExpression numExpr = args.ElementAt(0) as NumberExpression; // Invalid expression type if (numExpr == null) { throw new UnexpectedArgumentTypeException("not"); } // Invert the boolean value of the number expression and return it return(new NumberExpression(!numExpr.BooleanValue)); }); #endregion // Comparison functions are always performed on two consecutive expressions // This can yield unexpected results (e.g., when calling not_equal with more than two arguments) // Example: (not_equal 1 0 1) evaluates to true because no two consecutive expressions are equal AddComparisonFunction("equal", (a, b) => a == b); AddComparisonFunction("not_equal", (a, b) => a != b); AddComparisonFunction("greater", (a, b) => a > b); AddComparisonFunction("greater_or_equal", (a, b) => a >= b); AddComparisonFunction("less", (a, b) => a < b); AddComparisonFunction("less_or_equal", (a, b) => a <= b); // Logical boolean functions AddBooleanFunction("and", (nTrue, nTotal) => nTrue == nTotal); AddBooleanFunction("or", (nTrue, nTotal) => nTrue > 0); AddBooleanFunction("xor", (nTrue, nTotal) => nTrue == 1); }
// VoidExpression protected internal virtual bool Walk(VoidExpression node) { return(true); }