+ }
+}
+
+// secondPass takes an AST and reduces the operations that only include imm
+// values so the program results in a more compact one with precalculated imms
+func secondPass(node *AST) {
+ if node.Op == arg {
+ return
+ }
+ if node.Op == imm {
+ return
+ }
+ if node.Right.Op == imm && node.Left.Op == imm {
+ switch node.Op {
+ case min:
+ node.Value = node.Left.Value - node.Right.Value
+ case plus:
+ node.Value = node.Left.Value + node.Right.Value
+ case mul:
+ node.Value = node.Left.Value * node.Right.Value
+ case div:
+ node.Value = node.Left.Value / node.Right.Value
+ }
+ node.Op = imm
+ node.Left = nil
+ node.Right = nil
+ return
+ }
+ if node.Left.Op != arg && node.Left.Op != imm {
+ secondPass(node.Left)
+ }
+ if node.Right.Op != arg && node.Right.Op != imm {
+ secondPass(node.Right)
+ }
+}
+
+func thirdPass(node *AST, variables []rune) {
+ switch node.Op {
+ case arg:
+ number, found := slices.BinarySearch(variables, rune(node.Value))
+ if found {
+ fmt.Printf("AR %d\n", number)
+ }
+ case imm:
+ fmt.Printf("IM %d\n", node.Value)
+ default:
+ switch node.Left.Op {
+ case arg:
+ number, valid := slices.BinarySearch(variables, rune(node.Left.Value))
+ if valid {
+ fmt.Printf("AR %d\n", number)
+ }
+ case imm:
+ fmt.Printf("IM %d\n", node.Left.Value)
+ default:
+ thirdPass(node.Left, variables)
+ }
+ switch node.Right.Op {
+ case arg:
+ fmt.Println("SW")
+ number, valid := slices.BinarySearch(variables, rune(node.Right.Value))
+ if valid {
+ fmt.Printf("AR %d\n", number)
+ }
+ fmt.Println("SW")
+ case imm:
+ fmt.Println("SW")
+ fmt.Printf("IM %d\n", node.Right.Value)
+ fmt.Println("SW")
+ default:
+ fmt.Println("PU")
+ thirdPass(node.Right, variables)
+ fmt.Println("SW")
+ fmt.Println("PO")
+ }
+ switch node.Op {
+ case mul:
+ fmt.Println("MU")
+ case div:
+ fmt.Println("DI")
+ case min:
+ fmt.Println("SU")
+ case plus:
+ fmt.Println("AD")
+
+ }