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