func main() {
//a := &AST{Op: imm, N: 5
//b := &AST{Op: plus, A: a, B: &AST{Op: arg, N: 0}}
- input := "[ a b ] (a*a) + (5*5)"
+ input := "[ a b ] ((a*b) + (5*5))-3"
+ //input := "[ a b ] (a*a) + (5*5)"
variables, program := extractVariables(input)
firstPass(variables, program, &Tree)
fmt.Println(Tree)
secondPass(&Tree)
+ slices.Sort(variables)
+ thirdPass(&Tree, variables)
printer(&Tree)
}
}
}
+// firstPass Is a function that makes the first pass of the compiler,
+// it converts the variable and program into an AST
func firstPass(variables, program []rune, node *AST) {
pass := node
switch program[0] {
}
} else if slices.Contains(variables, program[0]) {
//var zeroOp op
- if node.Op != 2 && node.Op != 3 && node.Op != 4 && node.Op != 5 {
+ if node.Op != plus && node.Op != min && node.Op != mul && node.Op != div {
node.Left = &AST{Op: arg, Value: int(program[0])}
//a := &AST{Op: imm, N: 5
} else {
return
}
+
+// 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
}
}
+func thirdPass(node *AST, variables []rune) {
+ /////////////////////////////////////////THINKING SPACE/////////////////////
+ //
+ // If I am a imm I just load to R0
+ // If I am an arg I just load to R0
+ //
+ //
+ // If I am an operator then I put my answer to my father on R0
+ // If my left child is a imm or arg just call it and then SW
+ // If my right child is a imm or arg just call it then SW then operate
+ // If my left is an operand then call it(not sure about this one)
+ // If my right is an operand PU then call it then SW then PO then SW
+ // If i am an operand at the end always just operate AD MU DI SU
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ 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")
+ }
+
+ //need to think about which kind of child nodes make me want to PU & PO
+ switch node.Op {
+ case mul:
+ fmt.Println("MU")
+ case div:
+ fmt.Println("DI")
+ case min:
+ fmt.Println("SU")
+ case plus:
+ fmt.Println("AD")
+
+ }
+
+ }
+
+}
+
// extractVariables receives the original program string and converts it in
// two rune slices, the first containing the variables and a second containing
// the trimmed program
--- /dev/null
+function simulate(asm, args) {
+ var r0 = undefined;
+ var r1 = undefined;
+ var stack = [];
+ asm.forEach(function (instruct) {
+ var match = instruct.match(/(IM|AR)\s+(\d+)/) || [0, instruct, 0];
+ var ins = match[1];
+ var n = match[2] | 0;
+
+ if (ins == "IM") {
+ r0 = n;
+ } else if (ins == "AR") {
+ r0 = args[n];
+ } else if (ins == "SW") {
+ var tmp = r0;
+ r0 = r1;
+ r1 = tmp;
+ } else if (ins == "PU") {
+ stack.push(r0);
+ } else if (ins == "PO") {
+ r0 = stack.pop();
+ } else if (ins == "AD") {
+ r0 += r1;
+ } else if (ins == "SU") {
+ r0 -= r1;
+ } else if (ins == "MU") {
+ r0 *= r1;
+ } else if (ins == "DI") {
+ r0 /= r1;
+ }
+ });
+ return r0;
+}
+
+asm = [
+ "AR 0",
+ "SW",
+ "AR 1",
+ "SW",
+ "MU",
+ "SW",
+ "IM 25",
+ "SW",
+ "AD",
+ "SW",
+ "IM 3",
+ "SW",
+ "SU",
+];
+
+var total = simulate(asm, [4, 5]);
+console.log(total);