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 # Write function declarations. 283 # Signature: __attr <name>(__attr[]); 284 285 print >>f_signatures, "__attr %s(__attr args[]);" % encode_function_pointer(path) 286 287 # Write parameter table. 288 289 self.make_parameter_table(f_decls, f_defs, path, path) 290 291 # Generate predefined constants. 292 293 for path, name in self.predefined_constant_members: 294 self.make_predefined_constant(f_decls, f_defs, path, name) 295 296 # Generate literal constants. 297 298 for value, n in self.optimiser.constants.items(): 299 self.make_literal_constant(f_decls, f_defs, n, value) 300 301 # Finish the main source file. 302 303 self.write_main_program(f_code, f_signatures) 304 305 # Output more boilerplate. 306 307 print >>f_consts, """\ 308 309 #endif /* __PROGCONSTS_H__ */""" 310 311 print >>f_decls, """\ 312 313 #define __FUNCTION_TYPE %s 314 #define __FUNCTION_INSTANCE_SIZE %s 315 316 #endif /* __PROGTYPES_H__ */""" % ( 317 encode_path(self.function_type), 318 encode_size("<instance>", self.function_type) 319 ) 320 321 print >>f_signatures, """\ 322 323 #endif /* __MAIN_H__ */""" 324 325 finally: 326 f_consts.close() 327 f_defs.close() 328 f_decls.close() 329 f_signatures.close() 330 f_code.close() 331 332 def make_literal_constant(self, f_decls, f_defs, n, value): 333 334 """ 335 Write literal constant details to 'f_decls' (to declare a structure) and 336 to 'f_defs' (to define the contents) for the constant with the number 337 'n' with the given literal 'value'. 338 """ 339 340 const_path = encode_literal_constant(n) 341 structure_name = encode_literal_reference(n) 342 343 # NOTE: This makes assumptions about the __builtins__ structure. 344 345 typename = value.__class__.__name__ 346 ref = Reference("<instance>", "__builtins__.%s.%s" % (typename, typename)) 347 348 self.make_constant(f_decls, f_defs, ref, const_path, structure_name, value) 349 350 def make_predefined_constant(self, f_decls, f_defs, path, name): 351 352 """ 353 Write predefined constant details to 'f_decls' (to declare a structure) 354 and to 'f_defs' (to define the contents) for the constant located in 355 'path' with the given 'name'. 356 """ 357 358 # Determine the details of the constant. 359 360 attr_path = "%s.%s" % (path, name) 361 structure_name = encode_predefined_reference(attr_path) 362 ref = self.importer.get_object(attr_path) 363 364 self.make_constant(f_decls, f_defs, ref, attr_path, structure_name) 365 366 def make_constant(self, f_decls, f_defs, ref, const_path, structure_name, data=None): 367 368 """ 369 Write constant details to 'f_decls' (to declare a structure) and to 370 'f_defs' (to define the contents) for the constant described by 'ref' 371 having the given 'path' and 'structure_name' (for the constant structure 372 itself). 373 """ 374 375 # Obtain the attributes. 376 377 cls = ref.get_origin() 378 indexes = self.optimiser.attr_table[ref] 379 attrnames = self.get_attribute_names(indexes) 380 attrs = self.get_instance_attributes(cls, attrnames) 381 382 # Set the data, if provided. 383 384 if data is not None: 385 attrs["__data__"] = data 386 387 # Define the structure details. An object is created for the constant, 388 # but an attribute is provided, referring to the object, for access to 389 # the constant in the program. 390 391 structure = [] 392 table_name = encode_tablename("<instance>", cls) 393 structure_size = encode_size("<instance>", cls) 394 self.populate_structure(ref, attrs, ref.get_kind(), structure) 395 self.write_structure(f_decls, f_defs, structure_name, table_name, structure_size, structure) 396 397 # Define a macro for the constant. 398 399 attr_name = encode_path(const_path) 400 print >>f_decls, "#define %s ((__attr) {&%s, &%s})" % (attr_name, structure_name, structure_name) 401 402 def make_parameter_table(self, f_decls, f_defs, path, function_path): 403 404 """ 405 Write parameter table details to 'f_decls' (to declare a table) and to 406 'f_defs' (to define the contents) for the function with the given 407 'path', using 'function_path' to obtain the parameter details. The 408 latter two arguments may differ when describing an instantiator using 409 the details of an initialiser. 410 """ 411 412 table = [] 413 table_name = encode_tablename("<function>", path) 414 structure_size = encode_size("pmax", path) 415 self.populate_parameter_table(function_path, table) 416 self.write_parameter_table(f_decls, f_defs, table_name, structure_size, table) 417 418 def write_size_constants(self, f_consts, size_prefix, sizes, padding): 419 420 """ 421 Write size constants to 'f_consts' for the given 'size_prefix', using 422 the 'sizes' dictionary to populate the definition, adding the given 423 'padding' to the basic sizes. 424 """ 425 426 print >>f_consts, "enum %s {" % encode_size(size_prefix) 427 first = True 428 for path, size in sizes.items(): 429 if not first: 430 print >>f_consts, "," 431 else: 432 first = False 433 f_consts.write(" %s = %d" % (encode_size(size_prefix, path), size + padding)) 434 print >>f_consts, "\n };" 435 436 def write_code_constants(self, f_consts, attrnames, locations, code_prefix, pos_prefix): 437 438 """ 439 Write code constants to 'f_consts' for the given 'attrnames' and 440 attribute 'locations'. 441 """ 442 443 print >>f_consts, "enum %s {" % encode_symbol(code_prefix) 444 first = True 445 for i, attrname in enumerate(attrnames): 446 if not first: 447 print >>f_consts, "," 448 else: 449 first = False 450 f_consts.write(" %s = %d" % (encode_symbol(code_prefix, attrname), i)) 451 print >>f_consts, "\n };" 452 453 print >>f_consts, "enum %s {" % encode_symbol(pos_prefix) 454 first = True 455 for i, attrnames in enumerate(locations): 456 for attrname in attrnames: 457 if not first: 458 print >>f_consts, "," 459 else: 460 first = False 461 f_consts.write(" %s = %d" % (encode_symbol(pos_prefix, attrname), i)) 462 print >>f_consts, "\n };" 463 464 def write_table(self, f_decls, f_defs, table_name, structure_size, table): 465 466 """ 467 Write the declarations to 'f_decls' and definitions to 'f_defs' for 468 the object having the given 'table_name' and the given 'structure_size', 469 with 'table' details used to populate the definition. 470 """ 471 472 print >>f_decls, "extern const __table %s;\n" % table_name 473 474 # Write the corresponding definition. 475 476 print >>f_defs, "const __table %s = {\n %s,\n {\n %s\n }\n };\n" % ( 477 table_name, structure_size, 478 ",\n ".join(table)) 479 480 def write_parameter_table(self, f_decls, f_defs, table_name, structure_size, table): 481 482 """ 483 Write the declarations to 'f_decls' and definitions to 'f_defs' for 484 the object having the given 'table_name' and the given 'structure_size', 485 with 'table' details used to populate the definition. 486 """ 487 488 print >>f_decls, "extern const __ptable %s;\n" % table_name 489 490 # Write the corresponding definition. 491 492 print >>f_defs, "const __ptable %s = {\n %s,\n {\n %s\n }\n };\n" % ( 493 table_name, structure_size, 494 ",\n ".join([("{%s, %s}" % t) for t in table])) 495 496 def write_instance_structure(self, f_decls, path, structure_size): 497 498 """ 499 Write a declaration to 'f_decls' for the object having the given 'path' 500 and the given 'structure_size'. 501 """ 502 503 # Write an instance-specific type definition for instances of classes. 504 # See: templates/types.h 505 506 print >>f_decls, """\ 507 typedef struct { 508 const __table * table; 509 unsigned int pos; 510 __attr attrs[%s]; 511 } %s; 512 """ % (structure_size, encode_symbol("obj", path)) 513 514 def write_structure(self, f_decls, f_defs, structure_name, table_name, structure_size, structure, path=None): 515 516 """ 517 Write the declarations to 'f_decls' and definitions to 'f_defs' for 518 the object having the given 'structure_name', the given 'table_name', 519 and the given 'structure_size', with 'structure' details used to 520 populate the definition. 521 """ 522 523 if f_decls: 524 print >>f_decls, "extern __obj %s;\n" % encode_path(structure_name) 525 526 is_class = path and self.importer.get_object(path).has_kind("<class>") 527 pos = is_class and encode_symbol("pos", encode_type_attribute(path)) or "0" 528 529 print >>f_defs, """\ 530 __obj %s = { 531 &%s, 532 %s, 533 { 534 %s 535 }}; 536 """ % ( 537 encode_path(structure_name), table_name, pos, 538 ",\n ".join(structure)) 539 540 def get_argument_limits(self, path): 541 542 """ 543 Return the argument minimum and maximum for the callable at 'path', 544 adding an argument position for a universal context. 545 """ 546 547 parameters = self.importer.function_parameters[path] 548 defaults = self.importer.function_defaults.get(path) 549 num_parameters = len(parameters) + 1 550 return num_parameters - (defaults and len(defaults) or 0), num_parameters 551 552 def get_attribute_names(self, indexes): 553 554 """ 555 Given a list of attribute table 'indexes', return a list of attribute 556 names. 557 """ 558 559 all_attrnames = self.optimiser.all_attrnames 560 attrnames = [] 561 for i in indexes: 562 if i is None: 563 attrnames.append(None) 564 else: 565 attrnames.append(all_attrnames[i]) 566 return attrnames 567 568 def get_static_attributes(self, kind, name, attrnames): 569 570 """ 571 Return a mapping of attribute names to paths for attributes belonging 572 to objects of the given 'kind' (being "<class>" or "<module>") with 573 the given 'name' and supporting the given 'attrnames'. 574 """ 575 576 attrs = {} 577 578 for attrname in attrnames: 579 if attrname is None: 580 continue 581 if kind == "<class>": 582 path = self.importer.all_class_attrs[name][attrname] 583 elif kind == "<module>": 584 path = "%s.%s" % (name, attrname) 585 else: 586 continue 587 588 # The module may be hidden. 589 590 attr = self.importer.get_object(path) 591 if not attr: 592 module = self.importer.hidden.get(path) 593 if module: 594 attr = Reference(module.name, "<module>") 595 attrs[attrname] = attr 596 597 return attrs 598 599 def get_instance_attributes(self, name, attrnames): 600 601 """ 602 Return a mapping of attribute names to references for attributes 603 belonging to instances of the class with the given 'name', where the 604 given 'attrnames' are supported. 605 """ 606 607 consts = self.importer.all_instance_attr_constants[name] 608 attrs = {} 609 for attrname in attrnames: 610 if attrname is None: 611 continue 612 const = consts.get(attrname) 613 attrs[attrname] = const or Reference("<var>", "%s.%s" % (name, attrname)) 614 return attrs 615 616 def populate_table(self, key, table): 617 618 """ 619 Traverse the attributes in the determined order for the structure having 620 the given 'key', adding entries to the attribute 'table'. 621 """ 622 623 for attrname in self.optimiser.structures[key]: 624 625 # Handle gaps in the structure. 626 627 if attrname is None: 628 table.append("0") 629 else: 630 table.append(encode_symbol("code", attrname)) 631 632 def populate_parameter_table(self, key, table): 633 634 """ 635 Traverse the parameters in the determined order for the structure having 636 the given 'key', adding entries to the attribute 'table'. 637 """ 638 639 for value in self.optimiser.parameters[key]: 640 641 # Handle gaps in the structure. 642 643 if value is None: 644 table.append(("0", "0")) 645 else: 646 name, pos = value 647 table.append((encode_symbol("pcode", name), pos)) 648 649 def populate_function(self, path, function_instance_attrs, unbound=False): 650 651 """ 652 Populate a structure for the function with the given 'path'. The given 653 'attrs' provide the instance attributes, and if 'unbound' is set to a 654 true value, an unbound method structure is produced (as opposed to a 655 callable bound method structure). 656 """ 657 658 cls = self.function_type 659 structure = [] 660 self.populate_structure(Reference("<instance>", cls), function_instance_attrs, "<instance>", structure, unbound) 661 662 # Append default members. 663 664 self.append_defaults(path, structure) 665 return structure 666 667 def populate_structure(self, ref, attrs, kind, structure, unbound=False): 668 669 """ 670 Traverse the attributes in the determined order for the structure having 671 the given 'ref' whose members are provided by the 'attrs' mapping, in a 672 structure of the given 'kind', adding entries to the object 'structure'. 673 If 'unbound' is set to a true value, an unbound method function pointer 674 will be employed, with a reference to the bound method incorporated into 675 the special __fn__ attribute. 676 """ 677 678 origin = ref.get_origin() 679 680 for attrname in self.optimiser.structures[ref]: 681 682 # Handle gaps in the structure. 683 684 if attrname is None: 685 structure.append("{0, 0}") 686 687 # Handle non-constant and constant members. 688 689 else: 690 attr = attrs[attrname] 691 692 # Special function pointer member. 693 694 if attrname == "__fn__": 695 696 # Provide bound method references and the unbound function 697 # pointer if populating methods in a class. 698 699 bound_attr = None 700 701 # Classes offer instantiators. 702 703 if kind == "<class>": 704 attr = encode_instantiator_pointer(attr) 705 706 # Methods offers references to bound versions and an unbound 707 # method function. 708 709 elif unbound: 710 bound_attr = encode_bound_reference(attr) 711 attr = "__unbound_method" 712 713 # Other functions just offer function pointers. 714 715 else: 716 attr = encode_function_pointer(attr) 717 718 structure.append("{%s, .fn=%s}" % (bound_attr and ".b=&%s" % bound_attr or "0", attr)) 719 continue 720 721 # Special argument specification member. 722 723 elif attrname == "__args__": 724 structure.append("{.min=%s, .ptable=&%s}" % (attr, encode_tablename("<function>", origin))) 725 continue 726 727 # Special internal data member. 728 729 elif attrname == "__data__": 730 structure.append("{0, .%s=%s}" % (encode_literal_constant_member(attr), 731 encode_literal_constant_value(attr))) 732 continue 733 734 structure.append(self.encode_member(origin, attrname, attr, kind)) 735 736 def encode_member(self, path, name, ref, structure_type): 737 738 """ 739 Encode within the structure provided by 'path', the member whose 'name' 740 provides 'ref', within the given 'structure_type'. 741 """ 742 743 kind = ref.get_kind() 744 origin = ref.get_origin() 745 746 # References to constant literals. 747 748 if kind == "<instance>": 749 attr_path = "%s.%s" % (path, name) 750 751 # Obtain a constant value directly assigned to the attribute. 752 753 if self.optimiser.constant_numbers.has_key(attr_path): 754 constant_number = self.optimiser.constant_numbers[attr_path] 755 constant_value = "const%d" % constant_number 756 return "{&%s, &%s} /* %s */" % (constant_value, constant_value, name) 757 758 # Predefined constant references. 759 760 if (path, name) in self.predefined_constant_members: 761 attr_path = encode_predefined_reference("%s.%s" % (path, name)) 762 return "{&%s, &%s} /* %s */" % (attr_path, attr_path, name) 763 764 # General undetermined members. 765 766 if kind in ("<var>", "<instance>"): 767 return "{0, 0} /* %s */" % name 768 769 # Set the context depending on the kind of attribute. 770 # For methods: {&<parent>, &<attr>} 771 # For other attributes: {&<attr>, &<attr>} 772 773 else: 774 if kind == "<function>" and structure_type == "<class>": 775 parent = origin.rsplit(".", 1)[0] 776 context = "&%s" % encode_path(parent) 777 elif kind == "<instance>": 778 context = "&%s" % encode_path(origin) 779 else: 780 context = "0" 781 return "{%s, &%s}" % (context, encode_path(origin)) 782 783 def append_defaults(self, path, structure): 784 785 """ 786 For the given 'path', append default parameter members to the given 787 'structure'. 788 """ 789 790 for name, default in self.importer.function_defaults.get(path): 791 structure.append(self.encode_member(path, name, default, "<instance>")) 792 793 def write_instantiator(self, f_code, path, init_ref): 794 795 """ 796 Write an instantiator to 'f_code' for instances of the class with the 797 given 'path', with 'init_ref' as the initialiser function reference. 798 799 NOTE: This also needs to initialise any __fn__ and __args__ members 800 NOTE: where __call__ is provided by the class. 801 """ 802 803 parameters = self.importer.function_parameters[init_ref.get_origin()] 804 805 print >>f_code, """\ 806 __attr %s(__attr __args[]) 807 { 808 __args[0] = __new(&%s, &%s, sizeof(%s)); 809 %s(__args); 810 return __args[0]; 811 } 812 """ % ( 813 encode_instantiator_pointer(path), 814 encode_tablename("<instance>", path), 815 encode_path(path), 816 encode_symbol("obj", path), 817 encode_function_pointer(init_ref.get_origin()) 818 ) 819 820 def write_main_program(self, f_code, f_signatures): 821 822 """ 823 Write the main program to 'f_code', invoking the program's modules. Also 824 write declarations for module main functions to 'f_signatures'. 825 """ 826 827 print >>f_code, """\ 828 int main(int argc, char *argv[]) 829 {""" 830 831 for name in self.importer.modules.keys(): 832 function_name = "__main_%s" % encode_path(name) 833 print >>f_signatures, "void %s();" % function_name 834 835 # Emit the main module's function last. 836 837 if name != "__main__": 838 print >>f_code, """\ 839 %s();""" % function_name 840 841 print >>f_code, """\ 842 __main___main__(); 843 return 0; 844 } 845 """ 846 847 # vim: tabstop=4 expandtab shiftwidth=4