fork download
  1. open System
  2.  
  3. // your code goes here
  4. type binop =
  5. | Add
  6. | Sub
  7. | Mul
  8. | Div
  9.  
  10. type unop =
  11. | Dup
  12. | Drop
  13.  
  14. type expr =
  15. | Val of int
  16. | BinOp of binop
  17. | UnOp of unop
  18.  
  19. // Starts at address #x00 #x03
  20. let duplicate =
  21. "POTA #xFF #x00\n" +
  22. "PUFA #xFF #x00\n" +
  23. "PUFA #xFF #x00\n" +
  24. "RET\n"
  25.  
  26. // Starts at address #x00 #x0E
  27. let multiply =
  28. "POTA #xFF #x00\n" + // puts multiplicand at xFF x00
  29. "PUFA #xFF #x00\n" +
  30. "PUFA #xFF #x00\n" +
  31. "POTA #xFF #x01\n" + // Counter
  32. "PUFA #xFF #x01\n" + // Grab counter
  33. "PUSH 0\n" +
  34. "EQ?\n" + // Counter == 0?
  35. "JIF #x00 #x34\n" + // This should go to RET
  36. "PUFA #xFF #x00\n" +
  37. "ADD\n" + // Accumulate value
  38. "PUFA #xFF #x01\n" +
  39. "PUSH 1\n" +
  40. "SUB\n" +
  41. "POTA #xFF #x01\n" + // Decrement counter
  42. "JMP #x00 #x1B\n" + // Return to beginning of loop
  43. "RET\n"
  44.  
  45. // Starts at address #0x00 #0x35
  46. let divide =
  47. "POTA #xFF #x00\n" + // puts multiplicand at xFF x00
  48. "PUFA #xFF #x00\n" +
  49. "PUFA #xFF #x00\n" +
  50. "POTA #xFF #x01\n" + // Counter
  51. "PUFA #xFF #x01\n" + // Grab counter
  52. "PUSH 0\n" +
  53. "EQ?\n" + // Counter == 0?
  54. "JIF #x00 #x5B\n" + // This should go to RET
  55. "PUFA #xFF #x00\n" +
  56. "SUB\n" + // Accumulate value
  57. "PUFA #xFF #x01\n" +
  58. "PUSH 1\n" +
  59. "SUB\n" +
  60. "POTA #xFF #x01\n" + // Decrement counter
  61. "JMP #x00 #x42\n" + // Return to beginning of loop
  62. "RET\n"
  63.  
  64. let stdlib =
  65. "JMP #x00 #x5C\n" + // Should point after stdlib
  66. duplicate +
  67. multiply +
  68. divide
  69.  
  70. let translate xpr out =
  71. match xpr with
  72. | Val x -> let o = sprintf "PUSH %i" x
  73. o::out
  74. | BinOp op -> match op with
  75. | Add -> "ADD"::out
  76. | Sub -> "SUB"::out
  77. | Mul -> "JSR #x00 #x0E"::out
  78. | Div -> "JSR #x00 #x35"::out
  79. | UnOp op -> match op with
  80. | Dup -> "JSR #x00 #x03"::out
  81. | Drop -> "POP"::out
  82.  
  83. let rec parse prog =
  84. match prog with
  85. | [] -> []
  86. | x::xs -> match x with
  87. | "+" -> BinOp Add::(parse xs)
  88. | "-" -> BinOp Sub::(parse xs)
  89. | "*" -> BinOp Mul::(parse xs)
  90. | "/" -> BinOp Div::(parse xs)
  91. | "dup" -> UnOp Dup::(parse xs)
  92. | "drop" -> UnOp Drop::(parse xs)
  93. | v -> let i = int v
  94. Val i::(parse xs)
  95.  
  96. let compile (prog : string) =
  97. let parsed = prog.Split [|' '|]
  98. |> Array.toList
  99. |> parse
  100. |> List.rev
  101. let initout = []
  102.  
  103. let rec compiling p out =
  104. match p with
  105. | [] -> out
  106. | x::xs -> compiling xs (translate x out)
  107.  
  108. let lines = compiling parsed initout
  109.  
  110. stdlib + List.reduce (fun x y -> x + "\n" + y) lines
  111.  
  112. let p = "4 5 + dup *"
  113.  
  114. let r = compile p
  115.  
  116. printfn "%s" r
Success #stdin #stdout 0.1s 24464KB
stdin
Standard input is empty
stdout
JMP #x00 #x5C
POTA #xFF #x00
PUFA #xFF #x00
PUFA #xFF #x00
RET
POTA #xFF #x00
PUFA #xFF #x00
PUFA #xFF #x00
POTA #xFF #x01
PUFA #xFF #x01
PUSH 0
EQ?
JIF #x00 #x34
PUFA #xFF #x00
ADD
PUFA #xFF #x01
PUSH 1
SUB
POTA #xFF #x01
JMP #x00 #x1B
RET
POTA #xFF #x00
PUFA #xFF #x00
PUFA #xFF #x00
POTA #xFF #x01
PUFA #xFF #x01
PUSH 0
EQ?
JIF #x00 #x5B
PUFA #xFF #x00
SUB
PUFA #xFF #x01
PUSH 1
SUB
POTA #xFF #x01
JMP #x00 #x42
RET
PUSH 4
PUSH 5
ADD
JSR #x00 #x03
JSR #x00 #x0E