nullrun.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #!/usr/bin/env python
  2. #
  3. # NULLRUN -- NULL Interpreter in Python (2005-01-18)
  4. # Copyright (c) 2005, Kang Seonghoon <tokigun@gmail.com>.
  5. #
  6. # This library is free software; you can redistribute it and/or
  7. # modify it under the terms of the GNU Lesser General Public
  8. # License as published by the Free Software Foundation; either
  9. # version 2.1 of the License, or (at your option) any later version.
  10. #
  11. # This library is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. # Lesser General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU Lesser General Public
  17. # License along with this library; if not, write to the Free Software
  18. # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  19. #
  20. from sys import stdin, stdout, argv, exit
  21. try:
  22. from primes import list as plist
  23. except ImportError:
  24. # first 100 primes (default)
  25. plist = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
  26. 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139,
  27. 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223,
  28. 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293,
  29. 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383,
  30. 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
  31. 467, 479, 487, 491, 499, 503, 509, 521, 523, 541]
  32. def sprp(n, a):
  33. if n < 2 or n & 1 == 0: return False
  34. d = n - 1
  35. while d & 1 == 0:
  36. d >>= 1
  37. if pow(a, d, n) + 1 == n: return True
  38. return pow(a, d, n) == 1
  39. def isprime(n):
  40. if n < 2: return False
  41. elif n < 4: return True
  42. elif not sprp(n, 2): return False
  43. elif n < 2047: return True
  44. elif not sprp(n, 3): return False
  45. elif n < 1373653: return True
  46. elif not sprp(n, 5): return False
  47. elif n < 25326001: return True
  48. elif n == 3215031751 or not sprp(n, 7): return False
  49. elif n < 118670087467: return True
  50. elif not sprp(n, 11): return False
  51. elif n < 2152302898747: return True
  52. elif not sprp(n, 13): return False
  53. elif n < 3474749660383: return True
  54. elif not sprp(n, 17): return False
  55. elif n < 341550071728321: return True
  56. else: raise ValueError
  57. def factor_g(include_builtin_list = True):
  58. if include_builtin_list:
  59. for x in plist: yield x
  60. k = plist[-1] + 7
  61. if k % 6 == 2:
  62. yield k-5
  63. k -= 2
  64. while True:
  65. yield k-1
  66. yield k+1
  67. k += 6
  68. def factor(n):
  69. if n < 2: return n
  70. for i in factor_g():
  71. if n % i == 0: return i
  72. def nprime(n):
  73. if n <= plist[-1]:
  74. try: return plist.index(n) + 1
  75. except: return -1
  76. else:
  77. k = len(plist) + 1
  78. for i in factor_g(False):
  79. if i >= n: break
  80. try:
  81. if isprime(i):
  82. plist.append(i)
  83. k += 1
  84. except:
  85. return -1
  86. if isprime(n):
  87. plist.append(n)
  88. return k
  89. else:
  90. return -1
  91. def interpret(prog):
  92. q = [[], [], []]; qp = 0
  93. x = long(prog); y = 1
  94. while x > 1:
  95. n = factor(x); x /= n; y *= n
  96. n = nprime(n) % 14
  97. if n == 0:
  98. break
  99. elif n == 1:
  100. qp = (qp + 1) % 3
  101. elif n == 2:
  102. qp = (qp - 1) % 3
  103. elif n == 3:
  104. stdout.write(len(q[qp]) and chr(q[qp][-1]) or '\0')
  105. elif n == 4:
  106. tmp = ord(stdin.read(1))
  107. if len(q[qp]): q[qp][-1] = tmp
  108. else: q[qp].append(tmp)
  109. elif n == 5:
  110. if len(q[qp]):
  111. y -= q[qp][-1]
  112. if y < 0: y = 0
  113. elif n == 6:
  114. if len(q[qp]): y += q[qp][-1]
  115. elif n == 7:
  116. if len(q[qp]): q[qp][-1] = (q[qp][-1] + y) & 255
  117. else: q[qp].append(y & 255)
  118. elif n == 8:
  119. if len(q[qp]): q[(qp+1)%3].insert(0, q[qp].pop())
  120. else: q[(qp+1)%3].append(0)
  121. elif n == 9:
  122. if len(q[qp]): q[(qp-1)%3].insert(0, q[qp].pop())
  123. else: q[(qp-1)%3].append(0)
  124. elif n == 10:
  125. try: q[qp].pop()
  126. except: pass
  127. elif n == 11:
  128. q[qp].insert(0, y & 255)
  129. elif n == 12:
  130. if len(q[qp]) == 0 or q[qp][-1] == 0:
  131. n = factor(x); x /= n; y *= n
  132. elif n == 13:
  133. x, y = y, x
  134. def main(argv):
  135. if len(argv) != 2:
  136. print "NULLRUN, interpreter of NULL programming language"
  137. print "Kang Seonghoon (Tokigun) @ TokigunStudio 2005"
  138. print
  139. print "Usage: python %s <filename>" % argv[0]
  140. print "Source file can be Python expression. (e.g. 2*3*5**8)"
  141. print "You can use Python-style comment in each line of code."
  142. print
  143. print "Size of the prime database (primes.py) is %d." % len(plist)
  144. return 0
  145. try:
  146. code = file(argv[1]).read()
  147. except:
  148. print "Error: can't read file \"%s\"." % argv[1]
  149. return 1
  150. rcode = ''
  151. for line in code.splitlines():
  152. pos = line.find('#')
  153. if pos >= 0: line = line[:pos]
  154. rcode += line + ' '
  155. code = eval(rcode, {}, {})
  156. interpret(code)
  157. return 0
  158. if __name__ == '__main__': exit(main(argv))