1 #!/usr/bin/env python 2 3 """ 4 Generate C code from object layouts and other deduced information. 5 6 Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 You should have received a copy of the GNU General Public License along with 19 this program. If not, see <http://www.gnu.org/licenses/>. 20 """ 21 22 from common import CommonOutput 23 from encoders import encode_bound_reference, encode_function_pointer, \ 24 encode_instantiator_pointer, \ 25 encode_literal_constant, encode_literal_constant_member, \ 26 encode_literal_constant_value, encode_literal_reference, \ 27 encode_path, \ 28 encode_predefined_reference, encode_symbol, \ 29 encode_type_attribute 30 from os import listdir 31 from os.path import isdir, join, split 32 from referencing import Reference 33 34 def copy(source, target): 35 36 "Copy a text file from 'source' to 'target'." 37 38 if isdir(target): 39 target = join(target, split(source)[-1]) 40 infile = open(source) 41 outfile = open(target, "w") 42 try: 43 outfile.write(infile.read()) 44 finally: 45 outfile.close() 46 infile.close() 47 48 class Generator(CommonOutput): 49 50 "A code generator." 51 52 function_type = "__builtins__.core.function" 53 54 table_name_prefixes = { 55 "<class>" : "Class", 56 "<module>" : "Module", 57 "<instance>" : "Instance" 58 } 59 60 structure_size_prefixes = { 61 "<class>" : "c", 62 "<module>" : "m", 63 "<instance>" : "i" 64 } 65 66 predefined_constant_members = ( 67 ("__builtins__.bool", "False"), 68 ("__builtins__.bool", "True"), 69 ("__builtins__.none", "None"), 70 ("__builtins__.notimplemented", "NotImplemented"), 71 ) 72 73 def __init__(self, importer, optimiser, output): 74 self.importer = importer 75 self.optimiser = optimiser 76 self.output = output 77 78 def to_output(self): 79 80 "Write the generated code." 81 82 self.check_output() 83 self.write_structures() 84 self.copy_templates() 85 86 def copy_templates(self): 87 88 "Copy template files to the generated output directory." 89 90 templates = join(split(__file__)[0], "templates") 91 92 for filename in listdir(templates): 93 copy(join(templates, filename), self.output) 94 95 def write_structures(self): 96 97 "Write structures used by the program." 98 99 f_consts = open(join(self.output, "progconsts.h"), "w") 100 f_defs = open(join(self.output, "progtypes.c"), "w") 101 f_decls = open(join(self.output, "progtypes.h"), "w") 102 f_signatures = open(join(self.output, "main.h"), "w") 103 f_code = open(join(self.output, "main.c"), "w") 104 105 try: 106 # Output boilerplate. 107 108 print >>f_consts, """\ 109 #ifndef __PROGCONSTS_H__ 110 #define __PROGCONSTS_H__ 111 """ 112 print >>f_decls, """\ 113 #ifndef __PROGTYPES_H__ 114 #define __PROGTYPES_H__ 115 116 #include "progconsts.h" 117 #include "types.h" 118 """ 119 print >>f_defs, """\ 120 #include "progtypes.h" 121 #include "progops.h" 122 #include "main.h" 123 """ 124 print >>f_signatures, """\ 125 #ifndef __MAIN_H__ 126 #define __MAIN_H__ 127 128 #include "types.h" 129 """ 130 print >>f_code, """\ 131 #include <string.h> 132 #include "types.h" 133 #include "ops.h" 134 #include "progconsts.h" 135 #include "progtypes.h" 136 #include "progops.h" 137 #include "main.h" 138 """ 139 140 # Generate structure size data. 141 142 size_tables = {} 143 144 for kind in ["<class>", "<module>", "<instance>"]: 145 size_tables[kind] = {} 146 147 for ref, structure in self.optimiser.structures.items(): 148 size_tables[ref.get_kind()][ref.get_origin()] = len(structure) 149 150 size_tables = size_tables.items() 151 size_tables.sort() 152 153 for kind, sizes in size_tables: 154 self.write_size_constants(f_consts, self.structure_size_prefixes[kind], sizes, 0) 155 156 # Generate parameter table size data. 157 158 min_sizes = {} 159 max_sizes = {} 160 161 for path, parameters in self.optimiser.parameters.items(): 162 argmin, argmax = self.get_argument_limits(path) 163 min_sizes[path] = argmin 164 max_sizes[path] = argmax 165 166 # Record instantiator limits. 167 168 if path.endswith(".__init__"): 169 path = path[:-len(".__init__")] 170 171 self.write_size_constants(f_consts, "pmin", min_sizes, 0) 172 self.write_size_constants(f_consts, "pmax", max_sizes, 0) 173 174 # Generate parameter codes. 175 176 self.write_code_constants(f_consts, self.optimiser.all_paramnames, self.optimiser.arg_locations, "pcode", "ppos") 177 178 # Generate attribute codes. 179 180 self.write_code_constants(f_consts, self.optimiser.all_attrnames, self.optimiser.locations, "code", "pos") 181 182 # Generate table and structure data. 183 184 function_instance_attrs = None 185 objects = self.optimiser.attr_table.items() 186 objects.sort() 187 188 for ref, indexes in objects: 189 attrnames = self.get_attribute_names(indexes) 190 191 kind = ref.get_kind() 192 path = ref.get_origin() 193 table_name = encode_tablename(self.table_name_prefixes[kind], path) 194 structure_size = encode_size(self.structure_size_prefixes[kind], path) 195 196 # Generate structures for classes and modules. 197 198 if kind != "<instance>": 199 structure = [] 200 attrs = self.get_static_attributes(kind, path, attrnames) 201 202 # Set a special instantiator on the class. 203 204 if kind == "<class>": 205 attrs["__fn__"] = path 206 attrs["__args__"] = encode_size("pmin", path) 207 208 # Write instantiator declarations based on the 209 # applicable initialiser. 210 211 init_ref = attrs["__init__"] 212 213 # Signature: __attr __new_<name>(__attr[]); 214 215 print >>f_signatures, "__attr %s(__attr[]);" % encode_instantiator_pointer(path) 216 217 # Write instantiator definitions. 218 219 self.write_instantiator(f_code, path, init_ref) 220 221 # Write parameter table. 222 223 self.make_parameter_table(f_decls, f_defs, path, init_ref.get_origin()) 224 225 self.populate_structure(Reference(kind, path), attrs, kind, structure) 226 227 if kind == "<class>": 228 self.write_instance_structure(f_decls, path, structure_size) 229 230 self.write_structure(f_decls, f_defs, path, table_name, structure_size, structure, 231 kind == "<class>" and path) 232 233 # Record function instance details for function generation below. 234 235 else: 236 attrs = self.get_instance_attributes(path, attrnames) 237 if path == self.function_type: 238 function_instance_attrs = attrs 239 240 # Write a table for all objects. 241 242 table = [] 243 self.populate_table(Reference(kind, path), table) 244 self.write_table(f_decls, f_defs, table_name, structure_size, table) 245 246 # Generate function instances. 247 248 functions = set() 249 250 for ref in self.importer.objects.values(): 251 if ref.has_kind("<function>"): 252 functions.add(ref.get_origin()) 253 254 functions = list(functions) 255 functions.sort() 256 257 for path in functions: 258 cls = self.function_type 259 table_name = encode_tablename("Instance", cls) 260 structure_size = encode_size(self.structure_size_prefixes["<instance>"], cls) 261 262 # Set a special callable attribute on the instance. 263 264 function_instance_attrs["__fn__"] = path 265 function_instance_attrs["__args__"] = encode_size("pmin", path) 266 267 # Produce two structures where a method is involved. 268 269 ref = self.importer.get_object(path) 270 parent_ref = self.importer.get_object(ref.parent()) 271 parent_kind = parent_ref and parent_ref.get_kind() 272 273 # Populate and write each structure. 274 275 if parent_kind == "<class>": 276 277 # A bound version of a method. 278 279 structure = self.populate_function(path, function_instance_attrs, False) 280 self.write_structure(f_decls, f_defs, encode_bound_reference(path), table_name, structure_size, structure) 281 282 # An unbound version of a method. 283 284 structure = self.populate_function(path, function_instance_attrs, True) 285 self.write_structure(f_decls, f_defs, path, table_name, structure_size, structure) 286 287 else: 288 # A normal function. 289 290 structure = self.populate_function(path, function_instance_attrs, False) 291 self.write_structure(f_decls, f_defs, path, table_name, structure_size, structure) 292 293 # Write function declarations. 294 # Signature: __attr <name>(__attr[]); 295 296 print >>f_signatures, "__attr %s(__attr args[]);" % encode_function_pointer(path) 297 298 # Write parameter table. 299 300 self.make_parameter_table(f_decls, f_defs, path, path) 301 302 # Generate predefined constants. 303 304 for path, name in self.predefined_constant_members: 305 self.make_predefined_constant(f_decls, f_defs, path, name) 306 307 # Generate literal constants. 308 309 for value, n in self.optimiser.constants.items(): 310 self.make_literal_constant(f_decls, f_defs, n, value) 311 312 # Output more boilerplate. 313 314 print >>f_consts, """\ 315 316 #endif /* __PROGCONSTS_H__ */""" 317 318 print >>f_decls, """\ 319 320 #define __FUNCTION_TYPE %s 321 #define __FUNCTION_INSTANCE_SIZE %s 322 323 #endif /* __PROGTYPES_H__ */""" % ( 324 encode_path(self.function_type), 325 encode_size(self.structure_size_prefixes["<instance>"], self.function_type) 326 ) 327 328 print >>f_signatures, """\ 329 330 #endif /* __MAIN_H__ */""" 331 332 finally: 333 f_consts.close() 334 f_defs.close() 335 f_decls.close() 336 f_signatures.close() 337 f_code.close() 338 339 def make_literal_constant(self, f_decls, f_defs, n, value): 340 341 """ 342 Write literal constant details to 'f_decls' (to declare a structure) and 343 to 'f_defs' (to define the contents) for the constant with the number 344 'n' with the given literal 'value'. 345 """ 346 347 const_path = encode_literal_constant(n) 348 structure_name = encode_literal_reference(n) 349 350 # NOTE: This makes assumptions about the __builtins__ structure. 351 352 typename = value.__class__.__name__ 353 ref = Reference("<instance>", "__builtins__.%s.%s" % (typename, typename)) 354 355 self.make_constant(f_decls, f_defs, ref, const_path, structure_name, value) 356 357 def make_predefined_constant(self, f_decls, f_defs, path, name): 358 359 """ 360 Write predefined constant details to 'f_decls' (to declare a structure) 361 and to 'f_defs' (to define the contents) for the constant located in 362 'path' with the given 'name'. 363 """ 364 365 # Determine the details of the constant. 366 367 attr_path = "%s.%s" % (path, name) 368 structure_name = encode_predefined_reference(attr_path) 369 ref = self.importer.get_object(attr_path) 370 371 self.make_constant(f_decls, f_defs, ref, attr_path, structure_name) 372 373 def make_constant(self, f_decls, f_defs, ref, const_path, structure_name, data=None): 374 375 """ 376 Write constant details to 'f_decls' (to declare a structure) and to 377 'f_defs' (to define the contents) for the constant described by 'ref' 378 having the given 'path' and 'structure_name' (for the constant structure 379 itself). 380 """ 381 382 # Obtain the attributes. 383 384 cls = ref.get_origin() 385 indexes = self.optimiser.attr_table[ref] 386 attrnames = self.get_attribute_names(indexes) 387 attrs = self.get_instance_attributes(cls, attrnames) 388 389 # Set the data, if provided. 390 391 if data is not None: 392 attrs["__data__"] = data 393 394 # Define the structure details. An object is created for the constant, 395 # but an attribute is provided, referring to the object, for access to 396 # the constant in the program. 397 398 structure = [] 399 table_name = encode_tablename("Instance", cls) 400 structure_size = encode_size(self.structure_size_prefixes["<instance>"], cls) 401 self.populate_structure(ref, attrs, ref.get_kind(), structure) 402 self.write_structure(f_decls, f_defs, structure_name, table_name, structure_size, structure) 403 404 # Define a macro for the constant. 405 406 attr_name = encode_path(const_path) 407 print >>f_decls, "#define %s ((__attr) {&%s, &%s})" % (attr_name, structure_name, structure_name) 408 409 def make_parameter_table(self, f_decls, f_defs, path, function_path): 410 411 """ 412 Write parameter table details to 'f_decls' (to declare a table) and to 413 'f_defs' (to define the contents) for the function with the given 414 'path', using 'function_path' to obtain the parameter details. The 415 latter two arguments may differ when describing an instantiator using 416 the details of an initialiser. 417 """ 418 419 table = [] 420 table_name = encode_tablename("Function", path) 421 structure_size = encode_size("pmax", path) 422 self.populate_parameter_table(function_path, table) 423 self.write_parameter_table(f_decls, f_defs, table_name, structure_size, table) 424 425 def write_size_constants(self, f_consts, size_prefix, sizes, padding): 426 427 """ 428 Write size constants to 'f_consts' for the given 'size_prefix', using 429 the 'sizes' dictionary to populate the definition, adding the given 430 'padding' to the basic sizes. 431 """ 432 433 print >>f_consts, "enum %s {" % encode_size(size_prefix) 434 first = True 435 for path, size in sizes.items(): 436 if not first: 437 print >>f_consts, "," 438 else: 439 first = False 440 f_consts.write(" %s = %d" % (encode_size(size_prefix, path), size + padding)) 441 print >>f_consts, "\n };" 442 443 def write_code_constants(self, f_consts, attrnames, locations, code_prefix, pos_prefix): 444 445 """ 446 Write code constants to 'f_consts' for the given 'attrnames' and 447 attribute 'locations'. 448 """ 449 450 print >>f_consts, "enum %s {" % encode_symbol(code_prefix) 451 first = True 452 for i, attrname in enumerate(attrnames): 453 if not first: 454 print >>f_consts, "," 455 else: 456 first = False 457 f_consts.write(" %s = %d" % (encode_symbol(code_prefix, attrname), i)) 458 print >>f_consts, "\n };" 459 460 print >>f_consts, "enum %s {" % encode_symbol(pos_prefix) 461 first = True 462 for i, attrnames in enumerate(locations): 463 for attrname in attrnames: 464 if not first: 465 print >>f_consts, "," 466 else: 467 first = False 468 f_consts.write(" %s = %d" % (encode_symbol(pos_prefix, attrname), i)) 469 print >>f_consts, "\n };" 470 471 def write_table(self, f_decls, f_defs, table_name, structure_size, table): 472 473 """ 474 Write the declarations to 'f_decls' and definitions to 'f_defs' for 475 the object having the given 'table_name' and the given 'structure_size', 476 with 'table' details used to populate the definition. 477 """ 478 479 print >>f_decls, "extern const __table %s;\n" % table_name 480 481 # Write the corresponding definition. 482 483 print >>f_defs, "const __table %s = {\n %s,\n {\n %s\n }\n };\n" % ( 484 table_name, structure_size, 485 ",\n ".join(table)) 486 487 def write_parameter_table(self, f_decls, f_defs, table_name, structure_size, table): 488 489 """ 490 Write the declarations to 'f_decls' and definitions to 'f_defs' for 491 the object having the given 'table_name' and the given 'structure_size', 492 with 'table' details used to populate the definition. 493 """ 494 495 print >>f_decls, "extern const __ptable %s;\n" % table_name 496 497 # Write the corresponding definition. 498 499 print >>f_defs, "const __ptable %s = {\n %s,\n {\n %s\n }\n };\n" % ( 500 table_name, structure_size, 501 ",\n ".join([("{%s, %s}" % t) for t in table])) 502 503 def write_instance_structure(self, f_decls, path, structure_size): 504 505 """ 506 Write a declaration to 'f_decls' for the object having the given 'path' 507 and the given 'structure_size'. 508 """ 509 510 # Write an instance-specific type definition for instances of classes. 511 # See: templates/types.h 512 513 print >>f_decls, """\ 514 typedef struct { 515 const __table * table; 516 unsigned int pos; 517 __attr attrs[%s]; 518 } %s; 519 """ % (structure_size, encode_symbol("obj", path)) 520 521 def write_structure(self, f_decls, f_defs, structure_name, table_name, structure_size, structure, path=None): 522 523 """ 524 Write the declarations to 'f_decls' and definitions to 'f_defs' for 525 the object having the given 'structure_name', the given 'table_name', 526 and the given 'structure_size', with 'structure' details used to 527 populate the definition. 528 """ 529 530 if f_decls: 531 print >>f_decls, "extern __obj %s;\n" % encode_path(structure_name) 532 533 is_class = path and self.importer.get_object(path).has_kind("<class>") 534 pos = is_class and encode_symbol("pos", encode_type_attribute(path)) or "0" 535 536 print >>f_defs, """\ 537 __obj %s = { 538 &%s, 539 %s, 540 { 541 %s 542 }}; 543 """ % ( 544 encode_path(structure_name), table_name, pos, 545 ",\n ".join(structure)) 546 547 def get_argument_limits(self, path): 548 549 """ 550 Return the argument minimum and maximum for the callable at 'path', 551 adding an argument position for a universal context. 552 """ 553 554 parameters = self.importer.function_parameters[path] 555 defaults = self.importer.function_defaults.get(path) 556 num_parameters = len(parameters) + 1 557 return num_parameters - (defaults and len(defaults) or 0), num_parameters 558 559 def get_attribute_names(self, indexes): 560 561 """ 562 Given a list of attribute table 'indexes', return a list of attribute 563 names. 564 """ 565 566 all_attrnames = self.optimiser.all_attrnames 567 attrnames = [] 568 for i in indexes: 569 if i is None: 570 attrnames.append(None) 571 else: 572 attrnames.append(all_attrnames[i]) 573 return attrnames 574 575 def get_static_attributes(self, kind, name, attrnames): 576 577 """ 578 Return a mapping of attribute names to paths for attributes belonging 579 to objects of the given 'kind' (being "<class>" or "<module>") with 580 the given 'name' and supporting the given 'attrnames'. 581 """ 582 583 attrs = {} 584 585 for attrname in attrnames: 586 if attrname is None: 587 continue 588 if kind == "<class>": 589 path = self.importer.all_class_attrs[name][attrname] 590 elif kind == "<module>": 591 path = "%s.%s" % (name, attrname) 592 else: 593 continue 594 595 # The module may be hidden. 596 597 attr = self.importer.get_object(path) 598 if not attr: 599 module = self.importer.hidden.get(path) 600 if module: 601 attr = Reference(module.name, "<module>") 602 attrs[attrname] = attr 603 604 return attrs 605 606 def get_instance_attributes(self, name, attrnames): 607 608 """ 609 Return a mapping of attribute names to references for attributes 610 belonging to instances of the class with the given 'name', where the 611 given 'attrnames' are supported. 612 """ 613 614 consts = self.importer.all_instance_attr_constants[name] 615 attrs = {} 616 for attrname in attrnames: 617 if attrname is None: 618 continue 619 const = consts.get(attrname) 620 attrs[attrname] = const or Reference("<var>", "%s.%s" % (name, attrname)) 621 return attrs 622 623 def populate_table(self, key, table): 624 625 """ 626 Traverse the attributes in the determined order for the structure having 627 the given 'key', adding entries to the attribute 'table'. 628 """ 629 630 for attrname in self.optimiser.structures[key]: 631 632 # Handle gaps in the structure. 633 634 if attrname is None: 635 table.append("0") 636 else: 637 table.append(encode_symbol("code", attrname)) 638 639 def populate_parameter_table(self, key, table): 640 641 """ 642 Traverse the parameters in the determined order for the structure having 643 the given 'key', adding entries to the attribute 'table'. 644 """ 645 646 for value in self.optimiser.parameters[key]: 647 648 # Handle gaps in the structure. 649 650 if value is None: 651 table.append(("0", "0")) 652 else: 653 name, pos = value 654 table.append((encode_symbol("pcode", name), pos)) 655 656 def populate_function(self, path, function_instance_attrs, unbound=False): 657 658 """ 659 Populate a structure for the function with the given 'path'. The given 660 'attrs' provide the instance attributes, and if 'unbound' is set to a 661 true value, an unbound method structure is produced (as opposed to a 662 callable bound method structure). 663 """ 664 665 cls = self.function_type 666 structure = [] 667 self.populate_structure(Reference("<instance>", cls), function_instance_attrs, "<instance>", structure, unbound) 668 669 # Append default members. 670 671 self.append_defaults(path, structure) 672 return structure 673 674 def populate_structure(self, ref, attrs, kind, structure, unbound=False): 675 676 """ 677 Traverse the attributes in the determined order for the structure having 678 the given 'ref' whose members are provided by the 'attrs' mapping, in a 679 structure of the given 'kind', adding entries to the object 'structure'. 680 If 'unbound' is set to a true value, an unbound method function pointer 681 will be employed, with a reference to the bound method incorporated into 682 the special __fn__ attribute. 683 """ 684 685 origin = ref.get_origin() 686 687 for attrname in self.optimiser.structures[ref]: 688 689 # Handle gaps in the structure. 690 691 if attrname is None: 692 structure.append("{0, 0}") 693 694 # Handle non-constant and constant members. 695 696 else: 697 attr = attrs[attrname] 698 699 # Special function pointer member. 700 701 if attrname == "__fn__": 702 703 # Provide bound method references and the unbound function 704 # pointer if populating methods in a class. 705 706 bound_attr = None 707 708 # Classes offer instantiators. 709 710 if kind == "<class>": 711 attr = encode_instantiator_pointer(attr) 712 713 # Methods offers references to bound versions and an unbound 714 # method function. 715 716 elif unbound: 717 bound_attr = encode_bound_reference(attr) 718 attr = "__unbound_method" 719 720 # Other functions just offer function pointers. 721 722 else: 723 attr = encode_function_pointer(attr) 724 725 structure.append("{%s, .fn=%s}" % (bound_attr and ".b=&%s" % bound_attr or "0", attr)) 726 continue 727 728 # Special argument specification member. 729 730 elif attrname == "__args__": 731 structure.append("{.min=%s, .ptable=&%s}" % (attr, encode_tablename("Function", origin))) 732 continue 733 734 # Special internal data member. 735 736 elif attrname == "__data__": 737 structure.append("{0, .%s=%s}" % (encode_literal_constant_member(attr), 738 encode_literal_constant_value(attr))) 739 continue 740 741 structure.append(self.encode_member(origin, attrname, attr, kind)) 742 743 def encode_member(self, path, name, ref, structure_type): 744 745 """ 746 Encode within the structure provided by 'path', the member whose 'name' 747 provides 'ref', within the given 'structure_type'. 748 """ 749 750 kind = ref.get_kind() 751 origin = ref.get_origin() 752 753 # References to constant literals. 754 755 if kind == "<instance>": 756 attr_path = "%s.%s" % (path, name) 757 758 # Obtain a constant value directly assigned to the attribute. 759 760 if self.optimiser.constant_numbers.has_key(attr_path): 761 constant_number = self.optimiser.constant_numbers[attr_path] 762 constant_value = "const%d" % constant_number 763 return "{&%s, &%s} /* %s */" % (constant_value, constant_value, name) 764 765 # Predefined constant references. 766 767 if (path, name) in self.predefined_constant_members: 768 attr_path = encode_predefined_reference("%s.%s" % (path, name)) 769 return "{&%s, &%s} /* %s */" % (attr_path, attr_path, name) 770 771 # General undetermined members. 772 773 if kind in ("<var>", "<instance>"): 774 return "{0, 0} /* %s */" % name 775 776 # Set the context depending on the kind of attribute. 777 # For methods: {&<path>, &<attr>} 778 # For other attributes: {&<attr>, &<attr>} 779 780 else: 781 context = (kind == "<function>" and structure_type == "<class>" and \ 782 "&%s" % encode_path(path) or "0") or \ 783 kind == "<instance>" and "&%s" % encode_path(origin) or "0" 784 return "{%s, &%s}" % (context, encode_path(origin)) 785 786 def append_defaults(self, path, structure): 787 788 """ 789 For the given 'path', append default parameter members to the given 790 'structure'. 791 """ 792 793 for name, default in self.importer.function_defaults.get(path): 794 structure.append(self.encode_member(path, name, default, "<instance>")) 795 796 def write_instantiator(self, f_code, path, init_ref): 797 798 """ 799 Write an instantiator to 'f_code' for instances of the class with the 800 given 'path', with 'init_ref' as the initialiser function reference. 801 802 NOTE: This also needs to initialise any __fn__ and __args__ members 803 NOTE: where __call__ is provided by the class. 804 """ 805 806 parameters = self.importer.function_parameters[init_ref.get_origin()] 807 808 print >>f_code, """\ 809 __attr %s(__attr __args[]) 810 { 811 __args[0] = __new(&%s, &%s, sizeof(%s)); 812 %s 813 return __args[0]; 814 } 815 """ % ( 816 encode_instantiator_pointer(path), 817 encode_tablename("Instance", path), encode_path(path), encode_symbol("obj", path), 818 encode_function_pointer(init_ref.get_origin()) 819 ) 820 821 def encode_size(table_type, path=None): 822 return "__%ssize%s" % (table_type, path and "_%s" % encode_path(path) or "") 823 824 def encode_tablename(table_type, path): 825 return "__%sTable_%s" % (table_type, encode_path(path)) 826 827 # vim: tabstop=4 expandtab shiftwidth=4