PageRenderTime 35ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/DLR_Main/Languages/Ruby/Tests/Compat/gen_singleton_graph.py

https://bitbucket.org/mdavid/dlr
Python | 250 lines | 207 code | 17 blank | 26 comment | 10 complexity | 790342dc2fb661e3ce2002d4a90e133c MD5 | raw file
  1. # ****************************************************************************
  2. #
  3. # Copyright (c) Microsoft Corporation.
  4. #
  5. # This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. # copy of the license can be found in the License.html file at the root of this distribution. If
  7. # you cannot locate the Apache License, Version 2.0, please send an email to
  8. # ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. # by the terms of the Apache License, Version 2.0.
  10. #
  11. # You must not remove this notice, or any other, from this software.
  12. #
  13. #
  14. # ****************************************************************************
  15. # Try to generate the test which represents the user-defined class, Class, Object, Module and
  16. # their Singleton classes (and their Singleton classes)... We also re-open such classes with
  17. # new members
  18. #
  19. # We verify by calling the methods through the class name and its' instance. We also call methods
  20. # which access instance/class variables (this part is ugly, not sure how I can/should simplify it)
  21. from compat_common import *
  22. # globals
  23. entities = []
  24. count = 0
  25. class Entity:
  26. def __init__(self, name, body, depends=None):
  27. self.name = name
  28. self.body = body
  29. self.set_dependency(depends)
  30. self.updated = False
  31. def __str__(self):
  32. return self.name
  33. def set_dependency(self, d):
  34. self.depend_on = d
  35. def get_id(self):
  36. if "##" in self.body:
  37. start = self.body.find("##")
  38. end = self.body.find("\n", start)
  39. return int(self.body[start + 2 : end])
  40. else:
  41. return None
  42. def create_singleton_class(self):
  43. global entities
  44. s_name = "S_" + self.name
  45. if s_name.startswith("S_" * 4): return
  46. # exit if already created
  47. for t in entities:
  48. if t.name == s_name: return
  49. new_entity = Entity(s_name, "%s = class << %s\n%s\n self\nend\n" % (s_name, self.name, get_body()))
  50. # they are predefined classes, not necessary to be defined again
  51. if self.name not in ["Object", "Module", "Class"]:
  52. new_entity.set_dependency(self)
  53. entities.append(new_entity)
  54. def update_body(self, ids):
  55. if self.name in 'xyz' or self.updated:
  56. return
  57. eol1 = self.body.find('\n')
  58. methods = " def read_icheck();\n"
  59. for y in ids:
  60. methods += ' puts "iv%s"; puts @iv%s rescue puts "inner_error"\n' % (y, y)
  61. methods += ' puts "sv%s"; puts @@sv%s rescue puts "inner_error"\n' % (y, y)
  62. methods += " end\n def self.read_scheck();\n"
  63. for y in ids:
  64. methods += ' puts "iv%s"; puts @iv%s rescue puts "inner_error"\n' % (y, y)
  65. methods += ' puts "sv%s"; puts @@sv%s rescue puts "inner_error"\n' % (y, y)
  66. methods += " end\n"
  67. self.body = self.body[:eol1+1] + methods + self.body[eol1+1:]
  68. self.updated = True
  69. #
  70. # create all entities
  71. #
  72. def get_body():
  73. global count
  74. count += 1
  75. return '''
  76. ##%s
  77. CONST%s = -%s
  78. @iv%s = %s # class instance variable
  79. @@sv%s = %s0
  80. def initialize; @iv%s = -%s0; end # instance variable; intentionally they have the same name
  81. def im%s; %s00; end
  82. def self.sm%s; -%s00; end
  83. ''' % ( (count,) * 13 )
  84. def get_definition(name, is_module=False):
  85. return '%s %s\n%s\nend' % (is_module and "module" or "class", name, get_body())
  86. module_m = Entity("M", get_definition("M", is_module=True))
  87. class_b = Entity("B", get_definition("B"))
  88. class_c = Entity("C", get_definition("C < B"), class_b)
  89. class_d = Entity("D", get_definition("D < B\n include M"), class_b)
  90. c_x = Entity("x", "x = C.new\n", class_c)
  91. c_y = Entity("y", "y = C.new\n", class_c)
  92. c_z = Entity("z", "z = D.new\n", class_d)
  93. class_object = Entity("Object", get_definition("Object"))
  94. class_module = Entity("Module", get_definition("Module"))
  95. class_class = Entity("Class", get_definition("Class"))
  96. entities = [class_b, class_c, module_m, class_d, c_y, c_z, class_object, class_module, class_class ]
  97. for e in entities: e.create_singleton_class()
  98. entities.append(c_x)
  99. # add explicitly re-opened classes
  100. entities.extend([Entity(e.name + "_open", get_definition(e.name), e)
  101. for e in entities
  102. if e.name.startswith("S_")])
  103. # Module, S_Module, B,
  104. # | |
  105. # S_S_Module C
  106. # / \
  107. # y S_C
  108. # / \
  109. # S_y S_S_C
  110. entities_dict = dict([(e.name, e) for e in entities])
  111. def names_to_entities(s):
  112. return [entities_dict[x] for x in s.split()]
  113. def generate_entity_sequence():
  114. #yield (entities, str(entities_dict.keys())) # too slow
  115. # hand-picked sequences
  116. for x in [
  117. # need update
  118. 'B C S_C y S_B S_S_B S_S_C x S_Class S_Object Object Class S_S_Object S_S_Class',
  119. 'S_Object B Object S_Class Class C x S_C S_S_C y S_Module Module S_y S_S_y',
  120. 'B C x y S_y S_S_y S_S_S_y S_B S_S_B S_S_S_B S_C S_S_C S_S_S_C Object S_Object S_S_Object S_S_S_Object Class S_Class S_S_Class S_S_S_Class Module S_Module S_S_Module S_S_S_Module',
  121. 'S_Object S_Class S_Module S_S_Object S_S_S_Object S_S_Class S_S_S_Class S_S_Module Class Object Module S_S_S_Module B C y S_y S_S_y S_S_S_y S_B S_S_B S_S_S_B S_C S_S_C S_S_S_C x',
  122. ]:
  123. yield (names_to_entities(x), x)
  124. import random
  125. for x in range(5):
  126. sample = random.sample(entities, 4)
  127. #print [z.name for z in sample]
  128. # remove those be depended by other in sample
  129. for y in sample:
  130. current = y
  131. while current.depend_on:
  132. if current.depend_on in sample:
  133. sample.remove(current.depend_on)
  134. current = current.depend_on
  135. #print [z.name for z in sample]
  136. # made a seqence
  137. sample_clone = []
  138. for y in sample:
  139. current = y
  140. sample_clone.insert(0, y)
  141. while current.depend_on:
  142. if current.depend_on in sample_clone:
  143. sample_clone.remove(current.depend_on)
  144. sample_clone.insert(0, current.depend_on)
  145. current = current.depend_on
  146. if class_d in sample_clone:
  147. if module_m in sample_clone:
  148. sample_clone.remove(module_m)
  149. sample_clone.insert(0, module_m)
  150. #print [z.name for z in sample_clone]
  151. yield (sample_clone, str([z.name for z in sample_clone]))
  152. # the function we use to check, added to each file
  153. def get_header(ids):
  154. header = 'def check_each(x, l)\n'
  155. for y in ids:
  156. header += ' puts "#{l}.CONST%s"; puts x::CONST%s rescue puts "error"\n' % (y, y)
  157. header += ' puts "#{l}.im%s"; puts x.im%s rescue puts "error"\n' % (y, y)
  158. header += ' puts "#{l}.sm%s"; puts x.sm%s rescue puts "error"\n' % (y, y)
  159. header += ' puts "read_icheck"; x.read_icheck rescue puts "error"\n'
  160. header += ' puts "read_scheck"; x.read_scheck rescue puts "error"\n'
  161. header += "end\n"
  162. header += '''
  163. def check(vars, names)
  164. puts '=========================================='
  165. cnt = 0
  166. vars.each do |x|
  167. puts "--------------#{cnt}, #{names[cnt]}---------------"
  168. cnt += 1
  169. '''
  170. header += " check_each(x, 'Class')\n"
  171. header += " begin; y = x.new \n"
  172. header += " rescue; puts 'fail to new'\n"
  173. header += " else; check_each(y, 'Instance')\n"
  174. header += " end\n end\nend\n"
  175. return header
  176. fc = FileCreator("test_singleton_graph", 1)
  177. # give me a names_to_entities
  178. for (seq, scenario) in generate_entity_sequence():
  179. vars = []
  180. lines = "# %s \n" % scenario
  181. all_ids = []
  182. for e in seq:
  183. if hasattr(e, "get_id"):
  184. idx = e.get_id()
  185. if idx:
  186. all_ids.append(idx)
  187. lines += get_header(all_ids)
  188. for e in seq:
  189. if not e.name.endswith("_open"):
  190. vars.append(e.name)
  191. temp = ', '.join(vars)
  192. e.update_body(all_ids)
  193. lines += e.body
  194. lines += '\nputs "after adding %s"\n' % e.name
  195. lines += 'puts "now vars: %s"\n' % temp
  196. lines += 'check [%s], %s\n' % (temp, vars)
  197. fc.save_block(lines)
  198. fc.close()
  199. fc.print_file_list()