1 #!/usr/bin/env python 2 3 """ 4 Generate RSVP code from simplified nodes. 5 6 Copyright (C) 2007 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 simplify.simplified import * 23 import rsvp 24 25 # Classes. 26 27 class Generator(Visitor): 28 29 "An RSVP code generator." 30 31 def __init__(self): 32 33 "Initialise the visitor." 34 35 Visitor.__init__(self) 36 self.assemblers = [] 37 self.current_assemblers = [] 38 39 # Satisfy visitor issues. 40 41 self.visitor = self 42 43 def get_code(self): 44 return rsvp.get_image(*self.assemblers) 45 46 def assembler(self): 47 return self.current_assemblers[-1] 48 49 def process(self, module): 50 51 """ 52 Process the given 'module', creating RSVP assemblers to store code and 53 data. 54 """ 55 56 self.module = module 57 58 main = rsvp.RSVPAssembler(1) 59 self.current_assemblers.append(main) 60 61 # Store constants. 62 63 for name, const in module.simplifier.constants.items(): 64 main.label("const$%s$%s" % (self.module.name, name)) 65 main.add(const.value) 66 67 # Reserve the namespace. 68 69 for name in module.namespace.keys(): 70 main.label("global$%s$%s" % (self.module.name, name)) 71 main.add(None) 72 73 # Generate subprograms. 74 75 for subprogram in module.simplifier.subprograms: 76 if not subprogram.internal: 77 78 # Generate specific subprograms. 79 80 for specialisation in subprogram.specialisations(): 81 self.process_subprogram(specialisation) 82 83 # Generate the initialisation. 84 85 self.dispatch(module) 86 87 # Remember the assembler used. 88 89 self.current_assemblers.pop() 90 self.assemblers.append(main) 91 92 def default(self, node, *args): 93 if hasattr(node, "code"): 94 self.dispatches(node.code) 95 96 def visitInvoke(self, invoke): 97 98 "Process the given 'invoke' node." 99 100 sub = self.assembler() 101 102 # NOTE: Generate arguments in a way compatible with subprogram 103 # NOTE: consumption as parameters. 104 105 for subprogram in invoke.invocations: 106 107 # NOTE: Generate switch table. 108 109 # Reserve the namespace. 110 111 params = subprogram.paramtypes.keys() 112 nparams = len(params) 113 if not invoke.share_locals: 114 sub.add("NSF", nparams) 115 116 sub.add("JAS", subprogram.full_name()) 117 118 if not invoke.share_locals: 119 sub.add("PSF") # previous stack frame 120 121 visitInvokeFunction = visitInvoke 122 visitInvokeRef = visitInvoke 123 124 def visitModule(self, module): 125 126 "Process the given 'module'." 127 128 self.dispatches(module.code) 129 130 def visitSubprogram(self, subprogram): 131 132 "Process the 'subprogram'." 133 134 if subprogram.internal: 135 self.process_subprogram(subprogram) 136 137 def process_subprogram(self, subprogram): 138 139 sub = rsvp.RSVPAssembler(1) 140 self.current_assemblers.append(sub) 141 142 sub.label("sub$%s$%s" % (self.module.name, subprogram.full_name())) 143 144 locals = subprogram.namespace.keys() 145 params = subprogram.paramtypes.keys() 146 nparams = len(params) 147 non_params = len(locals) - nparams 148 149 if non_params > 0: 150 sub.add("ESF", non_params) # extend stack frame for locals 151 152 # Produce the standard end of subprogram return. 153 154 sub.add("RAC") # return 155 156 self.current_assemblers.pop() 157 self.assemblers.append(sub) 158 159 # Convenience functions. 160 161 def generate(module): 162 generator = Generator() 163 generator.process(module) 164 return generator.get_code() 165 166 # vim: tabstop=4 expandtab shiftwidth=4