using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace FunctionalInterpreter { // base class for the expression node abstract class Expression { } // defines a constant integer class Int : Expression { public Int(int i) { Value = i; } public int Value { get; set; } } // defines a variable reference class Variable : Expression { public Variable(string name) { Name = name; } public string Name { get; set; } } // defines a plus expression class Plus : Expression { public Plus(Expression left, Expression right) { Left = left; Right = right; } public Expression Left { get; set; } public Expression Right { get; set; } } // defines a multiplication expression class Multiply : Expression { public Multiply(Expression left, Expression right) { Left = left; Right = right; } public Expression Left { get; set; } public Expression Right { get; set; } } abstract class Statement { } class Skip : Statement { } class Seq : Statement { public Seq(Statement s1, Statement s2) { S1 = s1; S2 = s2; } public Statement S1 { get; set; } public Statement S2 { get; set; } } class Assign : Statement { public Assign(string variable, Expression expression) { Variable = variable; Expression = expression; } public string Variable { get; set; } public Expression Expression { get; set; } } class If : Statement { public If(Expression condition, Statement @then) : this(condition, @then, new Skip()) { } public If(Expression condition, Statement @then, Statement @else) { Condition = condition; Then = @then; Else = @else; } public Expression Condition { get; set; } public Statement Then { get; set; } public Statement Else { get; set; } } class While : Statement { public While(Expression condition, Statement body) { Condition = condition; Body = body; } public Expression Condition { get; set; } public Statement Body { get; set; } } class Program { static void Main(string[] args) { Program p = new Program(); p.Run(); } delegate int HeapFunc(string variable); // returns a function that takes a heap and returns an integer Func TranslateExpression(Expression e) { if (e == null) throw new ArgumentNullException("Expression cannot be null"); if (e is Int) { // whatever the heap is, return the value return (h => ((Int)e).Value); } else if (e is Variable) { // use the heap to lookup the variable name return (h => h(((Variable)e).Name)); } else if (e is Plus) { // translate the left expression into a function var f1 = TranslateExpression(((Plus)e).Left); // translate the right exression into a function var f2 = TranslateExpression(((Plus)e).Right); // run the functions on the given heap to get integers and sum them return (h => f1(h) + f2(h)); } else if (e is Multiply) { // similar to the plus expression var f1 = TranslateExpression(((Multiply)e).Left); var f2 = TranslateExpression(((Multiply)e).Right); return (h => f1(h) * f2(h)); } else { throw new NotSupportedException("Not supported expression."); } } // returns a function that takes a heap and returns a heap. Func TranslateStatement(Statement s) { if (s == null) throw new ArgumentNullException("Expression cannot be null"); if (s is Skip) { // just return the same heap return (h => h); } else if (s is Assign) { Assign assign = (Assign)s; // translate the expression var f = TranslateExpression(assign.Expression); // the resulted heap will check if the variable is the one responsible for // if so return the result of the expression, else use the previous heap to look up. return (h) => (var => var == assign.Variable ? f(h) : h(var)); } else if (s is Seq) { Seq seq = (Seq)s; // translate the first statement var f1 = TranslateStatement(seq.S1); // translate the second statement var f2 = TranslateStatement(seq.S2); // apply the first translation on the heap, which will return a new heap // that will be applied to the second translation. return (h) => f2(f1(h)); } else if (s is If) { If @if = (If)s; // translate the condition expression var fcond = TranslateExpression(@if.Condition); // translate the then statement var fthen = TranslateStatement(@if.Then); // translate the else statement var felse = TranslateStatement(@if.Else); // apply the heap to the condition function. If the value is not zero, use // the heap returned by applying fthen, otherwise use the heap returned by // applying felse. return (h) => (fcond(h) != 0 ? fthen(h) : felse(h)); } else if (s is While) { While @while = (While)s; // translate the condition expression var fcond = TranslateExpression(@while.Condition); // translate the body statement var fbody = TranslateStatement(@while.Body); // apply the body multiple times then return the final heap. return (h) => { while (fcond(h) != 0) { h = fbody(h); } return h; }; } else { throw new NotSupportedException("Statement not supported."); } } // this is our initial heap. our heap is empty, so calling this function // sould just fail because we have no variable int InitialHeapFun(string variable) { throw new Exception("cannot find variable '" + variable + "'"); } void Run() { // sum := 0 // i := 10 // while (i) // sum := sum + i // i := i - 1 // end Statement myProgram = new Seq( new Assign("sum", new Int(0)), new Seq( new Assign("i", new Int(10)), new While(new Variable("i"), new Seq( new Assign("sum", new Plus(new Variable("sum"), new Variable("i"))), new Assign("i", new Plus(new Variable("i"), new Int(-1))) ) ) ) ); // translate the program into (heap=>heap) var f = TranslateStatement(myProgram); // run the program using our initial heap var heap = f(InitialHeapFun); // print the sum value. this outputs 55 Console.WriteLine(heap("sum")); } } }