public void Visit(NotOperator not)
        {
            not.Right.Accept(this);
            var rightOperand = tacs.Last().Result;

            tacs.Add(Tac.Not(rightOperand, MakeNewTemp()));
        }
        public void Visit(NegateOperator negate)
        {
            negate.Right.Accept(this);
            var rightOperand = tacs.Last().Result;

            tacs.Add(Tac.Negate(rightOperand, MakeNewTemp()));
        }
        public void Visit(Program program)
        {
            // the init op code sets up the call stack, to read command line arguments
            var main = program.Definitions.Single(d => d.Name == "main");

            tacs.Add(Tac.Init(main.Formals.Count));
            // call main
            tacs.Add(Tac.BeginCall(main.Name, main.Formals.Count, "t0"));
            for (int i = 0; i < main.Formals.Count; i++)
            {
                tacs.Add(Tac.Param($"arg{i}"));
            }
            tacs.Add(Tac.Call("main", "t0"));
            // call print
            tacs.Add(Tac.BeginCall("print", 1, "t1"));
            tacs.Add(Tac.Param("t0"));
            tacs.Add(Tac.Call("print", "t1"));
            tacs.Add(Tac.Halt());

            // declare print function
            tacs.Add(Tac.BeginFunc("print", 1));
            tacs.Add(Tac.PrintVariable("arg0"));
            tacs.Add(Tac.EndFunc("print"));

            foreach (var definition in program.Definitions)
            {
                definition.Accept(this);
            }
        }
 public void Visit(Body body)
 {
     foreach (var print in body.Prints)
     {
         print.Accept(this);
     }
     body.Expr.Accept(this);
     tacs.Add(Tac.Return(tacs.Last().Result));
 }
        public void Visit(TimesOperator times)
        {
            times.Left.Accept(this);
            var leftOperand = tacs.Last().Result;

            times.Right.Accept(this);
            var rightOperand = tacs.Last().Result;

            tacs.Add(Tac.Times(leftOperand, rightOperand, MakeNewTemp()));
        }
        public void Visit(MinusOperator minus)
        {
            minus.Left.Accept(this);
            var leftOperand = tacs.Last().Result;

            minus.Right.Accept(this);
            var rightOperand = tacs.Last().Result;

            tacs.Add(Tac.Minus(leftOperand, rightOperand, MakeNewTemp()));
        }
        public void Visit(DivideOperator divide)
        {
            divide.Left.Accept(this);
            var leftOperand = tacs.Last().Result;

            divide.Right.Accept(this);
            var rightOperand = tacs.Last().Result;

            tacs.Add(Tac.Divide(leftOperand, rightOperand, MakeNewTemp()));
        }
        public void Visit(Print print)
        {
            print.Expr.Accept(this);
            var temp           = tacs.Last().Result;
            var returnVariable = MakeNewTemp();

            tacs.Add(Tac.BeginCall("print", 1, returnVariable));
            tacs.Add(Tac.Param(temp));
            tacs.Add(Tac.Call("print", returnVariable));
        }
 public void Visit(Definition definition)
 {
     // temps are local to the function so reset the counter for each func
     // (makes it easy to work out where the temp is stored in the stack frame)
     tempCounter = 0;
     Ast.SymbolTable.CurrentFunction = definition.Name;
     tacs.Add(Tac.BeginFunc(definition.Name, definition.Formals.Count));
     definition.Body.Accept(this);
     tacs.Add(Tac.EndFunc(definition.Name));
 }
        public void Visit(IfThenElse ifthenelse)
        {
            var elseLabel      = MakeNewLabel();
            var endLabel       = MakeNewLabel();
            var resultVariable = MakeNewTemp();

            ifthenelse.IfExpr.Accept(this);
            var ifoperand = tacs.Last().Result;

            tacs.Add(Tac.IfFalse(ifoperand, elseLabel));
            ifthenelse.ThenExpr.Accept(this);
            tacs.Add(Tac.Assign(tacs.Last().Result, resultVariable));
            tacs.Add(Tac.Goto(endLabel));
            tacs.Add(Tac.Label(elseLabel, resultVariable));
            ifthenelse.ElseExpr.Accept(this);
            tacs.Add(Tac.Assign(tacs.Last().Result, resultVariable));
            tacs.Add(Tac.Label(endLabel, resultVariable));
        }
        public void Visit(EqualsOperator equals)
        {
            equals.Left.Accept(this);
            var leftOperand = tacs.Last().Result;

            equals.Right.Accept(this);
            var rightOperand = tacs.Last().Result;
            var result       = MakeNewTemp();
            var label1       = MakeNewLabel();
            var label2       = MakeNewLabel();

            tacs.Add(Tac.IfEqual(leftOperand, rightOperand, label1));
            tacs.Add(Tac.Assign("0", result));
            tacs.Add(Tac.Goto(label2));
            tacs.Add(Tac.Label(label1, result));
            tacs.Add(Tac.Assign("1", result));
            tacs.Add(Tac.Label(label2, result));
        }
        public void Visit(LessThanOperator lessThan)
        {
            lessThan.Left.Accept(this);
            var leftOperand = tacs.Last().Result;

            lessThan.Right.Accept(this);
            var rightOperand = tacs.Last().Result;
            var result       = MakeNewTemp();
            var label1       = MakeNewLabel();
            var label2       = MakeNewLabel();

            tacs.Add(Tac.IfLessThan(leftOperand, rightOperand, label1));
            tacs.Add(Tac.Assign("0", result));
            tacs.Add(Tac.Goto(label2));
            tacs.Add(Tac.Label(label1, result));
            tacs.Add(Tac.Assign("1", result));
            tacs.Add(Tac.Label(label2, result));
        }
        public void Visit(FunctionCall functionCall)
        {
            var args = new List <string>();

            foreach (var actual in functionCall.Actuals)
            {
                actual.Expr.Accept(this);
                args.Add(tacs.Last().Result);
            }

            var returnValue = MakeNewTemp();

            tacs.Add(Tac.BeginCall(functionCall.Name, functionCall.Actuals.Count, returnValue));
            foreach (var arg in args)
            {
                tacs.Add(Tac.Param(arg));
            }
            tacs.Add(Tac.Call(functionCall.Name, returnValue));
        }
        public void Visit(OrOperator or)
        {
            var trueLabel = MakeNewLabel();
            var endLabel  = MakeNewLabel();

            or.Left.Accept(this);
            var leftOperand = tacs.Last().Result;

            tacs.Add(Tac.IfTrue(leftOperand, trueLabel));
            or.Right.Accept(this);
            var rightOperand = tacs.Last().Result;

            tacs.Add(Tac.IfTrue(rightOperand, trueLabel));
            var resultVariable = MakeNewTemp();

            tacs.Add(Tac.Assign("0", resultVariable));
            tacs.Add(Tac.Goto(endLabel));
            tacs.Add(Tac.Label(trueLabel, resultVariable));
            tacs.Add(Tac.Assign("1", resultVariable));
            tacs.Add(Tac.Label(endLabel, resultVariable));
        }
        public void Visit(AndOperator and)
        {
            var falseLabel = MakeNewLabel();
            var endLabel   = MakeNewLabel();

            and.Left.Accept(this);
            var leftOperand = tacs.Last().Result;

            tacs.Add(Tac.IfFalse(leftOperand, falseLabel));
            and.Right.Accept(this);
            var rightOperand = tacs.Last().Result;

            tacs.Add(Tac.IfFalse(rightOperand, falseLabel));
            var resultVariable = MakeNewTemp();

            tacs.Add(Tac.Assign("1", resultVariable));
            tacs.Add(Tac.Goto(endLabel));
            tacs.Add(Tac.Label(falseLabel, resultVariable));
            tacs.Add(Tac.Assign("0", resultVariable));
            tacs.Add(Tac.Label(endLabel, resultVariable));
        }
 public void Visit(IntegerLiteral literal)
 {
     tacs.Add(Tac.Assign(literal.Value.ToString(), MakeNewTemp()));
 }
        public void Visit(BooleanLiteral booleanLiteral)
        {
            var booleanValue = booleanLiteral.Value ? "1" : "0";

            tacs.Add(Tac.Assign(booleanValue, MakeNewTemp()));
        }
        public void Visit(Identifier identifier)
        {
            var arg = $"arg{Ast.SymbolTable.ArgumentNumber(identifier.Value)}";

            tacs.Add(Tac.Assign(arg, MakeNewTemp()));
        }