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