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);
 }
Example #6
0
 public override void Visit(VoidExpression node)
 {
     unfinishedClone = new VoidExpression(GetCloneOf(node.Expression));
     base.Visit(node);
 }
Example #7
0
 public override void Visit(VoidExpression node)
 {
     Visit((UnaryExpression)node);
 }
Example #8
0
 public override void Visit(VoidExpression node)
 {
     UpdateType(node, TypeCalculator.GetType(node));
 }
Example #9
0
 public override void Visit(VoidExpression node)
 {
     AssignToImplicitReturn(node);
 }
Example #10
0
        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);
        }
 protected internal virtual void PostWalk(VoidExpression node)
 {
 }
 // VoidExpression
 protected internal virtual bool Walk(VoidExpression node)
 {
     return(true);
 }