Commit 3279cb03 authored by Jack Jansen's avatar Jack Jansen

Turned the suite compiler into an object.

parent 18c9b139
...@@ -467,17 +467,16 @@ def compileaete(aete, resinfo, fname, output=None, basepkgname=None, ...@@ -467,17 +467,16 @@ def compileaete(aete, resinfo, fname, output=None, basepkgname=None,
allprecompinfo = [] allprecompinfo = []
allsuites = [] allsuites = []
for suite in suites: for suite in suites:
code, suite, pathname, modname, precompinfo = precompilesuite(suite, basepackage, compiler = SuiteCompiler(suite, basepackage, output, edit_modnames, verbose)
output=output, edit_modnames=edit_modnames, verbose=verbose) code, modname, precompinfo = compiler.precompilesuite()
if not code: if not code:
continue continue
allprecompinfo = allprecompinfo + precompinfo allprecompinfo = allprecompinfo + precompinfo
suiteinfo = suite, pathname, modname suiteinfo = suite, pathname, modname
suitelist.append((code, modname)) suitelist.append((code, modname))
allsuites.append(suiteinfo) allsuites.append(compiler)
for suiteinfo in allsuites: for compiler in allsuites:
compilesuite(suiteinfo, major, minor, language, script, fname, basepackage, compiler.compilesuite(major, minor, language, script, fname, allprecompinfo)
allprecompinfo, interact=(edit_modnames is None), verbose=verbose)
initfilename = os.path.join(output, '__init__.py') initfilename = os.path.join(output, '__init__.py')
fp = open(initfilename, 'w') fp = open(initfilename, 'w')
MacOS.SetCreatorAndType(initfilename, 'Pyth', 'TEXT') MacOS.SetCreatorAndType(initfilename, 'Pyth', 'TEXT')
...@@ -541,46 +540,62 @@ def compileaete(aete, resinfo, fname, output=None, basepkgname=None, ...@@ -541,46 +540,62 @@ def compileaete(aete, resinfo, fname, output=None, basepkgname=None,
fp.write("\t_moduleName = '%s'\n\n"%packagename) fp.write("\t_moduleName = '%s'\n\n"%packagename)
fp.close() fp.close()
def precompilesuite(suite, basepackage=None, edit_modnames=None, output=None, class SuiteCompiler:
verbose=None): def __init__(self, suite, basepackage, output, edit_modnames, verbose):
self.suite = suite
self.basepackage = basepackage
self.edit_modnames = edit_modnames
self.output = output
self.verbose = verbose
# Set by precompilesuite
self.pathname = None
self.modname = None
# Set by compilesuite
self.fp = None
self.basemodule = None
self.enumsneeded = {}
def precompilesuite(self):
"""Parse a single suite without generating the output. This step is needed """Parse a single suite without generating the output. This step is needed
so we can resolve recursive references by suites to enums/comps/etc declared so we can resolve recursive references by suites to enums/comps/etc declared
in other suites""" in other suites"""
[name, desc, code, level, version, events, classes, comps, enums] = suite [name, desc, code, level, version, events, classes, comps, enums] = self.suite
modname = identify(name) modname = identify(name)
if len(modname) > 28: if len(modname) > 28:
modname = modname[:27] modname = modname[:27]
if edit_modnames is None: if self.edit_modnames is None:
pathname = EasyDialogs.AskFileForSave(message='Python output file', self.pathname = EasyDialogs.AskFileForSave(message='Python output file',
savedFileName=modname+'.py') savedFileName=modname+'.py')
else: else:
for old, new in edit_modnames: for old, new in self.edit_modnames:
if old == modname: if old == modname:
modname = new modname = new
if modname: if modname:
pathname = os.path.join(output, modname + '.py') self.pathname = os.path.join(self.output, modname + '.py')
else: else:
pathname = None self.pathname = None
if not pathname: if not self.pathname:
return None, None, None, None, None return None, None, None
modname = os.path.splitext(os.path.split(pathname)[1])[0] self.modname = os.path.splitext(os.path.split(self.pathname)[1])[0]
if basepackage and basepackage._code_to_module.has_key(code): if self.basepackage and self.basepackage._code_to_module.has_key(code):
# We are an extension of a baseclass (usually an application extending # We are an extension of a baseclass (usually an application extending
# Standard_Suite or so). Import everything from our base module # Standard_Suite or so). Import everything from our base module
basemodule = basepackage._code_to_module[code] basemodule = self.basepackage._code_to_module[code]
else: else:
# We are not an extension. # We are not an extension.
basemodule = None basemodule = None
enumsneeded = {} self.enumsneeded = {}
for event in events: for event in events:
findenumsinevent(event, enumsneeded) self.findenumsinevent(event)
objc = ObjectCompiler(None, basemodule, interact=(edit_modnames is None), objc = ObjectCompiler(None, basemodule, interact=(self.edit_modnames is None),
verbose=verbose) verbose=self.verbose)
for cls in classes: for cls in classes:
objc.compileclass(cls) objc.compileclass(cls)
for cls in classes: for cls in classes:
...@@ -590,19 +605,18 @@ def precompilesuite(suite, basepackage=None, edit_modnames=None, output=None, ...@@ -590,19 +605,18 @@ def precompilesuite(suite, basepackage=None, edit_modnames=None, output=None,
for enum in enums: for enum in enums:
objc.compileenumeration(enum) objc.compileenumeration(enum)
for enum in enumsneeded.keys(): for enum in self.enumsneeded.keys():
objc.checkforenum(enum) objc.checkforenum(enum)
objc.dumpindex() objc.dumpindex()
precompinfo = objc.getprecompinfo(modname) precompinfo = objc.getprecompinfo(self.modname)
return code, suite, pathname, modname, precompinfo return code, self.modname, precompinfo
def compilesuite((suite, pathname, modname), major, minor, language, script, def compilesuite(self, major, minor, language, script, fname, precompinfo):
fname, basepackage, precompinfo, interact=1, verbose=None):
"""Generate code for a single suite""" """Generate code for a single suite"""
[name, desc, code, level, version, events, classes, comps, enums] = suite [name, desc, code, level, version, events, classes, comps, enums] = self.suite
# Sort various lists, so re-generated source is easier compared # Sort various lists, so re-generated source is easier compared
def class_sorter(k1, k2): def class_sorter(k1, k2):
"""Sort classes by code, and make sure main class sorts before synonyms""" """Sort classes by code, and make sure main class sorts before synonyms"""
...@@ -622,8 +636,8 @@ def compilesuite((suite, pathname, modname), major, minor, language, script, ...@@ -622,8 +636,8 @@ def compilesuite((suite, pathname, modname), major, minor, language, script,
comps.sort() comps.sort()
enums.sort() enums.sort()
fp = open(pathname, 'w') self.fp = fp = open(self.pathname, 'w')
MacOS.SetCreatorAndType(pathname, 'Pyth', 'TEXT') MacOS.SetCreatorAndType(self.pathname, 'Pyth', 'TEXT')
fp.write('"""Suite %s: %s\n' % (ascii(name), ascii(desc))) fp.write('"""Suite %s: %s\n' % (ascii(name), ascii(desc)))
fp.write("Level %d, version %d\n\n" % (level, version)) fp.write("Level %d, version %d\n\n" % (level, version))
...@@ -635,29 +649,30 @@ def compilesuite((suite, pathname, modname), major, minor, language, script, ...@@ -635,29 +649,30 @@ def compilesuite((suite, pathname, modname), major, minor, language, script,
fp.write('import aetools\n') fp.write('import aetools\n')
fp.write('import MacOS\n\n') fp.write('import MacOS\n\n')
fp.write("_code = %s\n\n"% `code`) fp.write("_code = %s\n\n"% `code`)
if basepackage and basepackage._code_to_module.has_key(code): if self.basepackage and self.basepackage._code_to_module.has_key(code):
# We are an extension of a baseclass (usually an application extending # We are an extension of a baseclass (usually an application extending
# Standard_Suite or so). Import everything from our base module # Standard_Suite or so). Import everything from our base module
fp.write('from %s import *\n'%basepackage._code_to_fullname[code][0]) fp.write('from %s import *\n'%self.basepackage._code_to_fullname[code][0])
basemodule = basepackage._code_to_module[code] basemodule = self.basepackage._code_to_module[code]
elif basepackage and basepackage._code_to_module.has_key(code.lower()): elif self.basepackage and self.basepackage._code_to_module.has_key(code.lower()):
# This is needed by CodeWarrior and some others. # This is needed by CodeWarrior and some others.
fp.write('from %s import *\n'%basepackage._code_to_fullname[code.lower()][0]) fp.write('from %s import *\n'%self.basepackage._code_to_fullname[code.lower()][0])
basemodule = basepackage._code_to_module[code.lower()] basemodule = self.basepackage._code_to_module[code.lower()]
else: else:
# We are not an extension. # We are not an extension.
basemodule = None basemodule = None
compileclassheader(fp, modname, basemodule) self.basemodule = basemodule
self.compileclassheader()
enumsneeded = {} self.enumsneeded = {}
if events: if events:
for event in events: for event in events:
compileevent(fp, event, enumsneeded) self.compileevent(event)
else: else:
fp.write("\tpass\n\n") fp.write("\tpass\n\n")
objc = ObjectCompiler(fp, basemodule, precompinfo, interact=interact, objc = ObjectCompiler(fp, basemodule, precompinfo, interact=(self.edit_modnames is None),
verbose=verbose) verbose=self.verbose)
for cls in classes: for cls in classes:
objc.compileclass(cls) objc.compileclass(cls)
for cls in classes: for cls in classes:
...@@ -667,26 +682,25 @@ def compilesuite((suite, pathname, modname), major, minor, language, script, ...@@ -667,26 +682,25 @@ def compilesuite((suite, pathname, modname), major, minor, language, script,
for enum in enums: for enum in enums:
objc.compileenumeration(enum) objc.compileenumeration(enum)
for enum in enumsneeded.keys(): for enum in self.enumsneeded.keys():
objc.checkforenum(enum) objc.checkforenum(enum)
objc.dumpindex() objc.dumpindex()
return code, modname def compileclassheader(self):
def compileclassheader(fp, name, module=None):
"""Generate class boilerplate""" """Generate class boilerplate"""
classname = '%s_Events'%name classname = '%s_Events'%self.modname
if module: if self.basemodule:
modshortname = string.split(module.__name__, '.')[-1] modshortname = string.split(self.basemodule.__name__, '.')[-1]
baseclassname = '%s_Events'%modshortname baseclassname = '%s_Events'%modshortname
fp.write("class %s(%s):\n\n"%(classname, baseclassname)) self.fp.write("class %s(%s):\n\n"%(classname, baseclassname))
else: else:
fp.write("class %s:\n\n"%classname) self.fp.write("class %s:\n\n"%classname)
def compileevent(fp, event, enumsneeded): def compileevent(self, event):
"""Generate code for a single event""" """Generate code for a single event"""
[name, desc, code, subcode, returns, accepts, arguments] = event [name, desc, code, subcode, returns, accepts, arguments] = event
fp = self.fp
funcname = identify(name) funcname = identify(name)
# #
# generate name->keyword map # generate name->keyword map
...@@ -761,7 +775,7 @@ def compileevent(fp, event, enumsneeded): ...@@ -761,7 +775,7 @@ def compileevent(fp, event, enumsneeded):
if ename <> '****': if ename <> '****':
fp.write("\t\taetools.enumsubst(_arguments, %s, _Enum_%s)\n" % fp.write("\t\taetools.enumsubst(_arguments, %s, _Enum_%s)\n" %
(`kname`, identify(ename))) (`kname`, identify(ename)))
enumsneeded[ename] = 1 self.enumsneeded[ename] = 1
fp.write("\n") fp.write("\n")
# #
# Do the transaction # Do the transaction
...@@ -783,24 +797,14 @@ def compileevent(fp, event, enumsneeded): ...@@ -783,24 +797,14 @@ def compileevent(fp, event, enumsneeded):
fp.write("\t\t\treturn _arguments['----']\n") fp.write("\t\t\treturn _arguments['----']\n")
fp.write("\n") fp.write("\n")
# print "\n# Command %s -- %s (%s, %s)" % (`name`, `desc`, `code`, `subcode`) def findenumsinevent(self, event):
# print "# returns", compiledata(returns)
# print "# accepts", compiledata(accepts)
# for arg in arguments:
# compileargument(arg)
def compileargument(arg):
[name, keyword, what] = arg
print "# %s (%s)" % (name, `keyword`), compiledata(what)
def findenumsinevent(event, enumsneeded):
"""Find all enums for a single event""" """Find all enums for a single event"""
[name, desc, code, subcode, returns, accepts, arguments] = event [name, desc, code, subcode, returns, accepts, arguments] = event
for a in arguments: for a in arguments:
if is_enum(a[2]): if is_enum(a[2]):
ename = a[2][0] ename = a[2][0]
if ename <> '****': if ename <> '****':
enumsneeded[ename] = 1 self.enumsneeded[ename] = 1
# #
# This class stores the code<->name translations for a single module. It is used # This class stores the code<->name translations for a single module. It is used
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment