PageRenderTime 50ms CodeModel.GetById 33ms app.highlight 14ms RepoModel.GetById 1ms 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 | 16 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
 16# Try to generate the test which represents the user-defined class, Class, Object, Module and 
 17# their Singleton classes (and their Singleton classes)... We also re-open such classes with 
 18# new members
 19#
 20# We verify by calling the methods through the class name and its' instance. We also call methods
 21# which access instance/class variables (this part is ugly, not sure how I can/should simplify it)
 22
 23from compat_common import *
 24
 25# globals 
 26entities = []
 27count = 0
 28
 29class Entity:
 30    def __init__(self, name, body, depends=None):
 31        self.name = name
 32        self.body = body
 33        self.set_dependency(depends)
 34        self.updated = False
 35            
 36    def __str__(self):
 37        return self.name
 38            
 39    def set_dependency(self, d):
 40        self.depend_on = d
 41    
 42    def get_id(self):
 43        if "##" in self.body:
 44            start = self.body.find("##")
 45            end = self.body.find("\n", start)
 46            return int(self.body[start + 2 : end])
 47        else:
 48            return None
 49                    
 50    def create_singleton_class(self):
 51        global entities
 52
 53        s_name = "S_" + self.name 
 54        if s_name.startswith("S_" * 4): return
 55        
 56        # exit if already created
 57        for t in entities:
 58            if t.name == s_name: return 
 59            
 60        new_entity = Entity(s_name, "%s = class << %s\n%s\n    self\nend\n" % (s_name, self.name, get_body()))
 61        
 62        # they are predefined classes, not necessary to be defined again
 63        if self.name not in ["Object", "Module", "Class"]: 
 64            new_entity.set_dependency(self)
 65            
 66        entities.append(new_entity)
 67
 68    def update_body(self, ids):
 69        if self.name in 'xyz' or self.updated: 
 70            return 
 71            
 72        eol1 = self.body.find('\n')
 73        
 74        methods = "    def read_icheck();\n"
 75        for y in ids:    
 76            methods += '        puts "iv%s"; puts @iv%s rescue puts "inner_error"\n' % (y, y)
 77            methods += '        puts "sv%s"; puts @@sv%s rescue puts "inner_error"\n' % (y, y)
 78        methods += "    end\n    def self.read_scheck();\n"
 79        for y in ids:    
 80            methods += '        puts "iv%s"; puts @iv%s rescue puts "inner_error"\n' % (y, y)
 81            methods += '        puts "sv%s"; puts @@sv%s rescue puts "inner_error"\n' % (y, y)
 82        methods += "    end\n"
 83            
 84        self.body = self.body[:eol1+1] + methods + self.body[eol1+1:]
 85        self.updated = True
 86#
 87# create all entities 
 88#
 89def get_body():
 90    global count    
 91    count += 1    
 92    return '''
 93    ##%s
 94    CONST%s = -%s 
 95    @iv%s = %s   # class instance variable
 96    @@sv%s = %s0
 97    
 98    def initialize; @iv%s = -%s0; end  # instance variable; intentionally they have the same name
 99    def im%s; %s00; end
100    def self.sm%s; -%s00; end
101''' % ( (count,) * 13 )    
102
103def get_definition(name, is_module=False): 
104    return '%s %s\n%s\nend' % (is_module and "module" or "class", name, get_body())
105
106module_m = Entity("M", get_definition("M", is_module=True))
107class_b  = Entity("B", get_definition("B"))
108class_c  = Entity("C", get_definition("C < B"), class_b)
109class_d  = Entity("D", get_definition("D < B\n    include M"), class_b)
110
111c_x = Entity("x", "x = C.new\n", class_c)
112c_y = Entity("y", "y = C.new\n", class_c)
113c_z = Entity("z", "z = D.new\n", class_d)
114
115class_object = Entity("Object", get_definition("Object")) 
116class_module = Entity("Module", get_definition("Module")) 
117class_class = Entity("Class", get_definition("Class")) 
118
119entities = [class_b, class_c, module_m, class_d, c_y, c_z, class_object, class_module, class_class ]
120for e in entities: e.create_singleton_class()
121entities.append(c_x)
122
123# add explicitly re-opened classes
124entities.extend([Entity(e.name + "_open", get_definition(e.name), e) 
125                 for e in entities 
126                 if e.name.startswith("S_")])
127
128#    Module,  S_Module,      B, 
129#                |           |
130#            S_S_Module      C
131#                           / \ 
132#                          y   S_C
133#                         /      \
134#                       S_y     S_S_C
135
136entities_dict = dict([(e.name, e) for e in entities])
137def names_to_entities(s):
138    return [entities_dict[x] for x in s.split()]
139
140def generate_entity_sequence():
141    #yield (entities, str(entities_dict.keys())) # too slow
142    
143    # hand-picked sequences
144    for x in [
145        # need update
146        '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',
147        'S_Object B Object S_Class Class C x S_C S_S_C y S_Module Module S_y S_S_y',
148        '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',
149        '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',
150    ]:
151        yield (names_to_entities(x), x) 
152        
153    import random
154    
155    for x in range(5): 
156        sample = random.sample(entities, 4)
157
158        #print [z.name for z in sample]
159        
160        # remove those be depended by other in sample
161        for y in sample:
162            current = y
163            while current.depend_on:
164                if current.depend_on in sample:
165                    sample.remove(current.depend_on)
166                current = current.depend_on
167        
168        #print [z.name for z in sample]
169        
170        # made a seqence
171        sample_clone = []
172        for y in sample:
173            current = y 
174            sample_clone.insert(0, y)
175            while current.depend_on:
176                if current.depend_on in sample_clone:
177                    sample_clone.remove(current.depend_on)
178                sample_clone.insert(0, current.depend_on)
179                current = current.depend_on
180        
181        if class_d in sample_clone:
182            if module_m in sample_clone:
183                sample_clone.remove(module_m)
184            sample_clone.insert(0, module_m)
185            
186        #print [z.name for z in sample_clone]
187        
188        yield (sample_clone, str([z.name for z in sample_clone]))
189        
190# the function we use to check, added to each file
191
192def get_header(ids):
193    header = 'def check_each(x, l)\n'
194    for y in ids:    
195        header += '    puts "#{l}.CONST%s"; puts x::CONST%s rescue puts "error"\n' % (y, y)
196        header += '    puts "#{l}.im%s"; puts x.im%s rescue puts "error"\n' % (y, y)
197        header += '    puts "#{l}.sm%s"; puts x.sm%s rescue puts "error"\n' % (y, y)
198        
199    header += '    puts "read_icheck"; x.read_icheck rescue puts "error"\n' 
200    header += '    puts "read_scheck"; x.read_scheck rescue puts "error"\n' 
201    header += "end\n"
202
203    header += '''
204def check(vars, names)
205    puts '=========================================='
206    cnt = 0
207    vars.each do |x|
208        puts "--------------#{cnt}, #{names[cnt]}---------------"
209        cnt += 1
210'''
211    header += "        check_each(x, 'Class')\n"
212    header += "        begin; y = x.new \n"
213    header += "        rescue; puts 'fail to new'\n"
214    header += "        else; check_each(y, 'Instance')\n"
215    header += "        end\n    end\nend\n"
216    return header
217
218fc = FileCreator("test_singleton_graph", 1)
219
220# give me a names_to_entities
221for (seq, scenario) in generate_entity_sequence():
222    vars = []
223    lines = "# %s \n" % scenario
224    
225    all_ids = []
226    for e in seq:
227        if hasattr(e, "get_id"):
228            idx = e.get_id()
229            if idx: 
230                all_ids.append(idx)
231    
232    lines += get_header(all_ids)    
233    
234    for e in seq:
235        if not e.name.endswith("_open"):
236            vars.append(e.name)
237    
238        temp = ', '.join(vars)
239
240        e.update_body(all_ids)
241        lines += e.body
242        
243        lines += '\nputs "after adding %s"\n' % e.name
244        lines += 'puts "now vars: %s"\n' % temp
245        lines += 'check [%s], %s\n' % (temp, vars)
246    
247    fc.save_block(lines)
248       
249fc.close()
250fc.print_file_list()