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 # NOTE: These must be synchronised with the library. 56 57 predefined_constant_members = ( 58 ("__builtins__.boolean", "False"), 59 ("__builtins__.boolean", "True"), 60 ("__builtins__.none", "None"), 61 ("__builtins__.notimplemented", "NotImplemented"), 62 ) 63 64 def __init__(self, importer, optimiser, output): 65 self.importer = importer 66 self.optimiser = optimiser 67 self.output = output 68 69 def to_output(self): 70 71 "Write the generated code." 72 73 self.check_output() 74 self.write_structures() 75 self.copy_templates() 76 77 def copy_templates(self): 78 79 "Copy template files to the generated output directory." 80 81 templates = join(split(__file__)[0], "templates") 82 83 for filename in listdir(templates): 84 copy(join(templates, filename), self.output) 85 86 def write_structures(self): 87 88 "Write structures used by the program." 89 90 f_consts = open(join(self.output, "progconsts.h"), "w") 91 f_defs = open(join(self.output, "progtypes.c"), "w") 92 f_decls = open(join(self.output, "progtypes.h"), "w") 93 f_signatures = open(join(self.output, "main.h"), "w") 94 f_code = open(join(self.output, "main.c"), "w") 95 96 try: 97 # Output boilerplate. 98 99 print >>f_consts, """\ 100 #ifndef __PROGCONSTS_H__ 101 #define __PROGCONSTS_H__ 102 """ 103 print >>f_decls, """\ 104 #ifndef __PROGTYPES_H__ 105 #define __PROGTYPES_H__ 106 107 #include "progconsts.h" 108 #include "types.h" 109 """ 110 print >>f_defs, """\ 111 #include "progtypes.h" 112 #include "progops.h" 113 #include "main.h" 114 """ 115 print >>f_signatures, """\ 116 #ifndef __MAIN_H__ 117 #define __MAIN_H__ 118 119 #include "types.h" 120 """ 121 print >>f_code, """\ 122 #include <string.h> 123 #include "types.h" 124 #include "ops.h" 125 #include "progconsts.h" 126 #include "progtypes.h" 127 #include "progops.h" 128 #include "main.h" 129 """ 130 131 # Generate structure size data. 132 133 size_tables = {} 134 135 for kind in ["<class>", "<module>", "<instance>"]: 136 size_tables[kind] = {} 137 138 for ref, structure in self.optimiser.structures.items(): 139 size_tables[ref.get_kind()][ref.get_origin()] = len(structure) 140 141 size_tables = size_tables.items() 142 size_tables.sort() 143 144 for kind, sizes in size_tables: 145 self.write_size_constants(f_consts, kind, sizes, 0) 146 147 # Generate parameter table size data. 148 149 min_sizes = {} 150 max_sizes = {} 151 152 for path, parameters in self.optimiser.parameters.items(): 153 argmin, argmax = self.get_argument_limits(path) 154 min_sizes[path] = argmin 155 max_sizes[path] = argmax 156 157 # Record instantiator limits. 158 159 if path.endswith(".__init__"): 160 path = path[:-len(".__init__")] 161 162 self.write_size_constants(f_consts, "pmin", min_sizes, 0) 163 self.write_size_constants(f_consts, "pmax", max_sizes, 0) 164 165 # Generate parameter codes. 166 167 self.write_code_constants(f_consts, self.optimiser.all_paramnames, self.optimiser.arg_locations, "pcode", "ppos") 168 169 # Generate attribute codes. 170 171 self.write_code_constants(f_consts, self.optimiser.all_attrnames, self.optimiser.locations, "code", "pos") 172 173 # Generate table and structure data. 174 175 function_instance_attrs = None 176 objects = self.optimiser.attr_table.items() 177 objects.sort() 178 179 for ref, indexes in objects: 180 attrnames = self.get_attribute_names(indexes) 181 182 kind = ref.get_kind() 183 path = ref.get_origin() 184 table_name = encode_tablename(kind, path) 185 structure_size = encode_size(kind, path) 186 187 # Generate structures for classes and modules. 188 189 if kind != "<instance>": 190 structure = [] 191 attrs = self.get_static_attributes(kind, path, attrnames) 192 193 # Set a special instantiator on the class. 194 195 if kind == "<class>": 196 attrs["__fn__"] = path 197 attrs["__args__"] = encode_size("pmin", path) 198 199 # Write instantiator declarations based on the 200 # applicable initialiser. 201 202 init_ref = attrs["__init__"] 203 204 # Signature: __attr __new_<name>(__attr[]); 205 206 print >>f_signatures, "__attr %s(__attr[]);" % encode_instantiator_pointer(path) 207 208 # Write instantiator definitions. 209 210 self.write_instantiator(f_code, path, init_ref) 211 212 # Write parameter table. 213 214 self.make_parameter_table(f_decls, f_defs, path, init_ref.get_origin()) 215 216 self.populate_structure(Reference(kind, path), attrs, kind, structure) 217 218 if kind == "<class>": 219 self.write_instance_structure(f_decls, path, structure_size) 220 221 self.write_structure(f_decls, f_defs, path, table_name, structure_size, structure, 222 kind == "<class>" and path) 223 224 # Record function instance details for function generation below. 225 226 else: 227 attrs = self.get_instance_attributes(path, attrnames) 228 if path == self.function_type: 229 function_instance_attrs = attrs 230 231 # Write a table for all objects. 232 233 table = [] 234 self.populate_table(Reference(kind, path), table) 235 self.write_table(f_decls, f_defs, table_name, structure_size, table) 236 237 # Generate function instances. 238 239 functions = set() 240 241 for ref in self.importer.objects.values(): 242 if ref.has_kind("<function>"): 243 functions.add(ref.get_origin()) 244 245 functions = list(functions) 246 functions.sort() 247 248 for path in functions: 249 cls = self.function_type 250 table_name = encode_tablename("<instance>", cls) 251 structure_size = encode_size("<instance>", cls) 252 253 # Set a special callable attribute on the instance. 254 255 function_instance_attrs["__fn__"] = path 256 function_instance_attrs["__args__"] = encode_size("pmin", path) 257 258 # Produce two structures where a method is involved. 259 260 ref = self.importer.get_object(path) 261 parent_ref = self.importer.get_object(ref.parent()) 262 parent_kind = parent_ref and parent_ref.get_kind() 263 264 # Populate and write each structure. 265 266 if parent_kind == "<class>": 267 268 # A bound version of a method. 269 270 structure = self.populate_function(path, function_instance_attrs, False) 271 self.write_structure(f_decls, f_defs, encode_bound_reference(path), table_name, structure_size, structure) 272 273 # An unbound version of a method. 274 275 structure = self.populate_function(path, function_instance_attrs, True) 276 self.write_structure(f_decls, f_defs, path, table_name, structure_size, structure) 277 278 else: 279 # A normal function. 280 281 structure = self.populate_function(path, function_instance_attrs, False) 282 self.write_structure(f_decls, f_defs, path, table_name, structure_size, structure) 283 284 # Functions with defaults need to declare instance structures. 285 286 if self.importer.function_defaults.get(path): 287 self.write_instance_structure(f_decls, path, structure_size) 288 289 # Write function declarations. 290 # Signature: __attr <name>(__attr[]); 291 292 print >>f_signatures, "__attr %s(__attr args[]);" % encode_function_pointer(path) 293 294 # Write parameter table. 295 296 self.make_parameter_table(f_decls, f_defs, path, path) 297 298 # Generate predefined constants. 299 300 for path, name in self.predefined_constant_members: 301 self.make_predefined_constant(f_decls, f_defs, path, name) 302 303 # Generate literal constants. 304 305 for value, n in self.optimiser.constants.items(): 306 self.make_literal_constant(f_decls, f_defs, n, value) 307 308 # Finish the main source file. 309 310 self.write_main_program(f_code, f_signatures) 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("<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("<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: {&<parent>, &<attr>} 778 # For other attributes: {&<attr>, &<attr>} 779 780 else: 781 if kind == "<function>" and structure_type == "<class>": 782 parent = origin.rsplit(".", 1)[0] 783 context = "&%s" % encode_path(parent) 784 elif kind == "<instance>": 785 context = "&%s" % encode_path(origin) 786 else: 787 context = "0" 788 return "{%s, &%s}" % (context, encode_path(origin)) 789 790 def append_defaults(self, path, structure): 791 792 """ 793 For the given 'path', append default parameter members to the given 794 'structure'. 795 """ 796 797 for name, default in self.importer.function_defaults.get(path): 798 structure.append(self.encode_member(path, name, default, "<instance>")) 799 800 def write_instantiator(self, f_code, path, init_ref): 801 802 """ 803 Write an instantiator to 'f_code' for instances of the class with the 804 given 'path', with 'init_ref' as the initialiser function reference. 805 806 NOTE: This also needs to initialise any __fn__ and __args__ members 807 NOTE: where __call__ is provided by the class. 808 """ 809 810 parameters = self.importer.function_parameters[init_ref.get_origin()] 811 812 print >>f_code, """\ 813 __attr %s(__attr __args[]) 814 { 815 __args[0] = __new(&%s, &%s, sizeof(%s)); 816 %s(__args); 817 return __args[0]; 818 } 819 """ % ( 820 encode_instantiator_pointer(path), 821 encode_tablename("<instance>", path), 822 encode_path(path), 823 encode_symbol("obj", path), 824 encode_function_pointer(init_ref.get_origin()) 825 ) 826 827 def write_main_program(self, f_code, f_signatures): 828 829 """ 830 Write the main program to 'f_code', invoking the program's modules. Also 831 write declarations for module main functions to 'f_signatures'. 832 """ 833 834 print >>f_code, """\ 835 int main(int argc, char *argv[]) 836 {""" 837 838 for name in self.importer.modules.keys(): 839 function_name = "__main_%s" % encode_path(name) 840 print >>f_signatures, "void %s();" % function_name 841 842 # Emit the main module's function last. 843 844 if name != "__main__": 845 print >>f_code, """\ 846 %s();""" % function_name 847 848 print >>f_code, """\ 849 __main___main__(); 850 return 0; 851 } 852 """ 853 854 # vim: tabstop=4 expandtab shiftwidth=4