Guest User

Untitled

a guest
Jul 18th, 2018
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.88 KB | None | 0 0
  1. from llvm import *
  2. from llvm.core import *
  3.  
  4. m = Module.new('lisp')
  5. main = m.add_function(Type.function(Type.int(), []), "main")
  6. main_block = main.append_basic_block('entry')
  7. b = Builder.new(main_block)
  8.  
  9. class ReferenceNotFound(Exception):
  10. pass
  11.  
  12. class Env(object):
  13. def __init__(self,parent=None):
  14. self.parent = parent
  15. self.locals = {}
  16.  
  17. def set(self,k,v):
  18. self.locals[k] = v
  19.  
  20. def get(self,k):
  21. try:
  22. return self.locals[k]
  23. except KeyError:
  24. if self.parent:
  25. return self.parent.get(k)
  26. else:
  27. raise ReferenceNotFound
  28.  
  29.  
  30. def prim_add():
  31. f = m.add_function(Type.function(Type.int(), [Type.int(), Type.int()]), 'prim_add')
  32. block = f.append_basic_block('entry')
  33. builder = Builder.new(block)
  34. tmp = builder.add(f.args[0], f.args[1], 'tmp')
  35. builder.ret(tmp)
  36. return f
  37.  
  38. def prim_sub():
  39. f = m.add_function(Type.function(Type.int(), [Type.int(), Type.int()]), 'prim_sub')
  40. block = f.append_basic_block('entry')
  41. builder = Builder.new(block)
  42. tmp = builder.sub(f.args[0], f.args[1], 'tmp')
  43. builder.ret(tmp)
  44. return f
  45.  
  46. primitives = {
  47. '+': prim_add(),
  48. '-': prim_sub()
  49. }
  50.  
  51. def immediate(sexp):
  52. if type(sexp) == int:
  53. return True
  54. else:
  55. return False
  56.  
  57. def immediate_rep(sexp, builder):
  58. if type(sexp) == int:
  59. return ConstantInt.int(Type.int(), sexp)
  60.  
  61. def prim_call(sexp):
  62. if type(sexp) == list and len(sexp) > 0 and type(sexp[0]) == str and sexp[0] in primitives:
  63. return True
  64. else:
  65. return False
  66.  
  67. def prim_op(op, args, builder):
  68. return builder.call(primitives[op], args)
  69.  
  70. def define(args, builder, env):
  71. name = args[0]
  72. value = compile(args[1], builder, env)
  73. env.set(name, value)
  74.  
  75. lambda_counter = 0
  76.  
  77. def lambdaf(args,builder,env):
  78. arglist = args[0]
  79. body = args[1]
  80.  
  81. argtypes = [Type.int() for a in arglist]
  82.  
  83. f_env = Env(env)
  84.  
  85. f = m.add_function(Type.function(Type.int(), argtypes), 'f%d' % lambda_counter)
  86. for arg,name in zip(f.args, arglist):
  87. arg.name = name
  88. f_env.set(name, arg)
  89.  
  90. block = f.append_basic_block('entry')
  91. f_builder = Builder.new(block)
  92.  
  93. last = compile_block(body, f_builder, f_env)
  94. f_builder.ret(last)
  95.  
  96. return f
  97.  
  98.  
  99. special_forms = {
  100. 'def': define,
  101. 'lambda': lambdaf
  102. }
  103.  
  104. def special(sexp):
  105. return type(sexp) == list and type(sexp[0]) == str and sexp[0] in special_forms
  106.  
  107. def special_op(sexp, builder, env):
  108. return special_forms[sexp[0]](sexp[1:], builder, env)
  109.  
  110. def variable(sexp):
  111. if type(sexp) == str:
  112. return True
  113. else:
  114. return False
  115.  
  116. def variable_ref(sexp, env):
  117. #return m.get_global_variable_named(sexp).initializer
  118. return env.get(sexp)
  119.  
  120.  
  121. def call(sexp):
  122. return type(sexp) == list and type(sexp[0]) == str
  123.  
  124. def call_op(name, args, builder, env):
  125. #f = m.get_function_named(name)
  126. f = env.get(name)
  127. return builder.call(f, args)
  128.  
  129. def compile(sexp, builder, env):
  130. if immediate(sexp):
  131. return immediate_rep(sexp, builder)
  132. elif special(sexp):
  133. return special_op(sexp, builder, env)
  134. elif prim_call(sexp):
  135. args = [compile(arg, builder, env) for arg in sexp[1:]]
  136. return prim_op(sexp[0], args, builder)
  137. elif variable(sexp):
  138. return variable_ref(sexp, env)
  139. elif call(sexp):
  140. args = [compile(arg, builder, env) for arg in sexp[1:]]
  141. return call_op(sexp[0], args, builder, env)
  142.  
  143.  
  144. def compile_block(sexps, builder, env):
  145. statements = [compile(sexp, builder, env) for sexp in sexps]
  146. return statements[-1]
  147.  
  148. if __name__ == "__main__":
  149.  
  150. raw = [['def', 'x', 43],
  151. ['def', 'y', 11],
  152. ['def', 'z', ['+', 'y', 3]],
  153. ['def', 'calculate',
  154. ['lambda', ['a', 'b'],
  155. [['+', ['-', 'a', 38], 'b']]]],
  156. ['calculate', 'x', 'z']]
  157.  
  158.  
  159. last = compile_block(raw, b, Env())
  160. b.ret(last)
  161. print m
Add Comment
Please, Sign In to add comment