A collection of various things from the Asterisk server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

o_brainfuck.lua 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. local look_for_closing_brace = function(context, idx)
  2. if context.matching_indices[idx] ~= nil then
  3. return context.matching_indices[idx]
  4. end
  5. local orig_idx = idx
  6. local layer = 1
  7. while layer ~= 0 do
  8. idx = idx + 1
  9. if context.program[idx] == nil then
  10. return -1
  11. end
  12. if context.program[idx] == 7 then
  13. layer = layer + 1
  14. end
  15. if context.program[idx] == 8 then
  16. layer = layer - 1
  17. end
  18. end
  19. context.matching_indices[orig_idx] = idx
  20. return idx
  21. end
  22. local init_tape_at_head = function(context)
  23. if context.tape[context.head_pos] == nil then
  24. context.tape[context.head_pos] = context.initial_tape_func(context.head_pos)
  25. end
  26. end
  27. local loop_jump = function(context)
  28. init_tape_at_head(context)
  29. if context.tape[context.head_pos] ~= 0 then
  30. context.ip = context.jumpstack_left[#context.jumpstack_left] + 1
  31. else
  32. local idx = #context.jumpstack_left
  33. context.jumpstack_left[idx] = nil
  34. context.jumpstack_right[idx] = nil
  35. context.ip = context.ip + 1
  36. end
  37. end
  38. local do_open_bracket = function(context)
  39. context.jumpstack_left[#context.jumpstack_left + 1] = context.ip
  40. context.jumpstack_right[#context.jumpstack_left] = look_for_closing_brace(context, context.ip)
  41. context.ip = context.jumpstack_right[#context.jumpstack_left]
  42. loop_jump(context)
  43. end
  44. local do_close_bracket = function(context)
  45. if context.jumpstack_right[#context.jumpstack_left] == context.ip then
  46. loop_jump(context)
  47. else
  48. context.retval = {kind = "error", value = "unexpected right bracket"}
  49. end
  50. end
  51. local instr_table =
  52. {
  53. [1] = function(context)
  54. context.head_pos = context.head_pos - 1
  55. context.ip = context.ip + 1
  56. end,
  57. [2] = function(context)
  58. context.head_pos = context.head_pos + 1
  59. context.ip = context.ip + 1
  60. end,
  61. [3] = function(context)
  62. init_tape_at_head(context)
  63. context.tape[context.head_pos] = context.tape[context.head_pos] + 1
  64. context.ip = context.ip + 1
  65. end,
  66. [4] = function(context)
  67. init_tape_at_head(context)
  68. context.tape[context.head_pos] = context.tape[context.head_pos] - 1
  69. context.ip = context.ip + 1
  70. end,
  71. [5] = function(context)
  72. init_tape_at_head(context)
  73. context.write(context.tape[context.head_pos])
  74. context.ip = context.ip + 1
  75. end,
  76. [6] = function(context)
  77. context.tape[context.head_pos] = context.read()
  78. context.ip = context.ip + 1
  79. end,
  80. [7] = do_open_bracket,
  81. [8] = do_close_bracket,
  82. [9] = function(context)
  83. context.debugfn(context.head_pos, context.ip, context.tape)
  84. context.ip = context.ip + 1
  85. end,
  86. }
  87. local step = function(context, app)
  88. local f = instr_table[context.program[context.ip]]
  89. if f == nil then
  90. context.retval = {kind = "return", value = "success"}
  91. else
  92. f(context)
  93. end
  94. end
  95. function new_brainfuck_context(log, program, write, read, debugfn, initial_tape_func)
  96. local context =
  97. {
  98. program = program,
  99. write = write,
  100. read = read,
  101. debugfn = debugfn,
  102. log = log,
  103. initial_tape_func = initial_tape_func,
  104. head_pos = 0,
  105. tape = {},
  106. ip = 1,
  107. jumpstack_left = {},
  108. jumpstack_right = {},
  109. matching_indices = {},
  110. retval = nil,
  111. }
  112. context.step = step
  113. return context
  114. end
  115. return { new_brainfuck_context = new_brainfuck_context }
  116. --[[
  117. --str = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."
  118. --str = "+[-]..."
  119. --str = ".+.>.+.<.-.>.-."
  120. str = "+[+]"
  121. char_table =
  122. {
  123. [">"] = 1,
  124. ["<"] = 2,
  125. ["+"] = 3,
  126. ["-"] = 4,
  127. ["."] = 5,
  128. [","] = 6,
  129. ["["] = 7,
  130. ["]"] = 8,
  131. }
  132. prog = {}
  133. for i = 1,#str do
  134. prog[#prog + 1] = char_table[string.sub(str, i, i)]
  135. end
  136. out = ""
  137. unmangled = ""
  138. context = new_brainfuck_context(prog, function(v)
  139. out = out .. " " .. tostring(v)
  140. unmangled = unmangled .. string.char(v)
  141. end, function() return 0 end, function() return 0 end)
  142. count = 0
  143. while context.retval == nil and count < 1000000 do
  144. context:step()
  145. count = count + 1
  146. end
  147. tab = context.retval
  148. if tab.kind == "return" then
  149. print(out)
  150. print(unmangled)
  151. elseif tab.kind == "error" then
  152. print("error: " .. tab.value)
  153. end
  154. --]]