Esempio n. 1
0
    def getMethodTable(self,symbolTable):
	if not self.methodTable:
	    self.methodTable = MethodTable(self.name)
	    self.classMethodTable = self.methodTable.child(self.name+\
		    "_class")
	    for mixinName in self.mixins:
		mixin = symbolTable[mixinName]
		self.methodTable.addParent(mixin.getMethodTable(symbolTable))
		self.classMethodTable.addParent(mixin.classMethodTable)
	    self.mixinMethodTable = self.methodTable.child(self.name+\
		    "_mixin")
	    # TODO should have a $Mixin class, but use $Object for now.
	    self.mixinMethodTable.addParent(symbolTable['Object'].
		    getMethodTable(symbolTable))
	return self.methodTable
Esempio n. 2
0
    def getMethodTable(self,symbolTable):
	if not self.methodTable:
	    if self.parent != self.name:
		parent = symbolTable[self.parent]
		self.methodTable =\
			parent.getMethodTable(symbolTable).child(self.name)
		self.classMethodTable =\
			parent.classMethodTable.child(self.name+"_class")
	    else:
		self.methodTable = MethodTable(self.name)
		self.classMethodTable = self.methodTable.child(self.name+\
			"_class")
	    for mixinName in self.mixins:
		mixin = symbolTable[mixinName]
		self.methodTable.addParent(mixin.getMethodTable(symbolTable))
		self.classMethodTable.addParent(mixin.classMethodTable)
	return self.methodTable
Esempio n. 3
0
class MixinDecl(ASTNode):
    def tryParse(self):
	self.mixins = []
	self.methodTable = None
	self.classMethodTable = None
	self.mixinMethodTable = None
	publicToken = self.tokenizer.check('public')
	if not publicToken:
	    publicToken = self.tokenizer.check('private')
	mixinToken = self.tokenizer.check('mixin')
	if not mixinToken:
	    if publicToken:
		self.tokenizer.push(publicToken)
	    return False
	sigilToken = self.tokenizer.check('$')
	if not sigilToken:
	    raise SyntaxError('expected sigil: '+\
		    self.tokenizer.nextToken().errForm())
	idToken = self.tokenizer.nextToken()
	if idToken.type() != TokenTypes.identifier:
	    raise SyntaxError('expected: identifier: '+idToken.errForm())
	self.name = idToken.str
	self.selector = tryParse(SelectorLiteral,self.tokenizer)
	self.tokenizer.require(';')
	if self.selector:
	    self.methods = [(self.selector,generateTrueMethod(self.selector))]
	else:
	    self.methods = []
	return True
    def __str__(self):
	return 'mixin %s' % self.name
    def extractSymbols(self):
	return {self.name:self}
    def addMixin(self,mixinName,symbolTable):
	self.mixins += [mixinName]
	if self.methodTable:
	    mixin = symbolTable[mixinName]
	    self.methodTable.addParent(mixin.getMethodTable(symbolTable))
	    self.classMethodTable.addParent(mixin.classMethodTable)
    def addMethod(self,symbolTable,selector,method):
	#self.methods += [(selector,method)]
	self.getMethodTable(symbolTable)
	if method.isClass:
	    mt = self.classMethodTable
	elif method.isMixin:
	    mt = self.mixinMethodTable
	elif method.isConstructor:
	    raise Error('constructors on mixins not implemented')
	else:
	    mt = self.methodTable
	if method.isAlias:
	    mt.addAlias(selector.messageName,method.aliasTarget.messageName)
	else:
	    mt.addMethod(selector.messageName,method.block.getName())
    def getMethods(self,stable):
	if self.selector:
	    stable['Object'].addMethod(stable,self.selector,\
		    generateFalseMethod(self.selector))
	    self.selector = None
	return self.methods
    def getMethodTable(self,symbolTable):
	if not self.methodTable:
	    self.methodTable = MethodTable(self.name)
	    self.classMethodTable = self.methodTable.child(self.name+\
		    "_class")
	    for mixinName in self.mixins:
		mixin = symbolTable[mixinName]
		self.methodTable.addParent(mixin.getMethodTable(symbolTable))
		self.classMethodTable.addParent(mixin.classMethodTable)
	    self.mixinMethodTable = self.methodTable.child(self.name+\
		    "_mixin")
	    # TODO should have a $Mixin class, but use $Object for now.
	    self.mixinMethodTable.addParent(symbolTable['Object'].
		    getMethodTable(symbolTable))
	return self.methodTable
    def generateCode(self,stable):
	self.getMethodTable(stable) #ensure method tables initialized
	gvar = Global()  # mixin object reference
	gvar.setName(self.name) # our name
	obj = BytecodeObject(self.name) # class/singleton object
	gvar.setValue(obj) # which the reference points to
	obj.setMTable(self.mixinMethodTable) #mixin objects get mixin mtable
	return [self.mixinMethodTable,obj,gvar]
    def generateInstanceSymbolTable(self,symbolTable):
	return {}
    def loadCode(self,block):
	block.add_instruction('Global $%s'%(self.name))
Esempio n. 4
0
class ClassDecl(ASTNode):
    def checkNameUniqueness(self):
	global nameList
	if self.name in nameList:
	    raise Exception('double class: %s'%(self.name))
	else:
	    nameList[self.name] = self
    def tryParse(self):
	self.parent = None
	self.exceptionHandlingBlocks = []
	self.exception = False
	self.mixins = []
	publicToken = self.tokenizer.check('public')
	privateToken = self.tokenizer.check('private')
	classToken = self.tokenizer.check('class')
	if not classToken:
	    classToken = self.tokenizer.check('exception')
	    if classToken:
		self.exception = True
	if classToken:
	    self.singleton = False
	else:
	    singletonToken = self.tokenizer.check('singleton')
	    if not singletonToken:
		if privateToken:
		    self.tokenizer.push(privateToken)
		if publicToken:
		    self.tokenizer.push(publicToken)
		return False
	    else:
		self.singleton = True
	sigilToken = self.tokenizer.check('$')
	if not sigilToken:
	    raise SyntaxError('sigil sigil error')
	idToken = self.tokenizer.nextToken()
	if idToken.type() != TokenTypes.identifier:
	    raise SyntaxError('Token type non-id -id '+idToken.errForm())
	self.name = idToken.str
	self.checkNameUniqueness()
	if self.tokenizer.check('('):
	    if not self.tokenizer.check('$'):
		raise SyntaxError('no sigil in class decl')
	    self.parent = self.tokenizer.nextToken().str
	    if self.parent == self.name and self.name != 'Object':
		raise SemanticError('Only $Object may inherit from itself.')
	    if not self.tokenizer.check(')'):
		raise SyntaxError('no close paren in class decl')
	else:
	    if self.exception:
		self.parent = 'Exception'
	    else:
		self.parent = 'Object'
	self.ivars = []
	if self.exception:
	    self.selector = tryParse(SelectorLiteral,self.tokenizer)
	while not self.tokenizer.check(';'):
	    if not self.tokenizer.check('!'):
		raise SyntaxError('; or !')
	    self.ivars += [self.tokenizer.nextToken().str]
	    if not self.tokenizer.check(','):
		self.tokenizer.require(';')
		break
	self.methodTable = None
	return True
    def addClassMethod(self,symbolTable):
	blk = Block()
	blk.add_instruction('Global $%s' % self.name)
	blk.add_instruction('Return')
	if not self.exceptionHandlingBlocks:
	    self.exceptionHandlingBlocks = []
	self.exceptionHandlingBlocks += [blk]

	class FakeSelector:
	    def __init__(self,name):
		self.messageName = name
	selector = FakeSelector('class')
	method = PseudoMethod(blk.getName(),selector)
	self.addMethod(symbolTable,selector,method) # XXX ???
	self.exceptionHandlingBlocks += [blk]
    def __str__(self):
	if self.singleton:
	    res = 'singleton $'
	else:
	    res = 'class $'
	res += self.name
	res += ' ($'
	res += self.parent
	res += ') '
	for ivar in self.ivars:
	    res +='!'
	    res += ivar
	    res += ','
	res += ";\n"
	return res
    def getMethodTable(self,symbolTable):
	if not self.methodTable:
	    if self.parent != self.name:
		parent = symbolTable[self.parent]
		self.methodTable =\
			parent.getMethodTable(symbolTable).child(self.name)
		self.classMethodTable =\
			parent.classMethodTable.child(self.name+"_class")
	    else:
		self.methodTable = MethodTable(self.name)
		self.classMethodTable = self.methodTable.child(self.name+\
			"_class")
	    for mixinName in self.mixins:
		mixin = symbolTable[mixinName]
		self.methodTable.addParent(mixin.getMethodTable(symbolTable))
		self.classMethodTable.addParent(mixin.classMethodTable)
	return self.methodTable
    def extractSymbols(self):
	return {self.name: self}
    def defineExceptionMethod(self,symbolTable):
	self.exception = False
	class FakeSelector:
	    def __init__(self,name):
		self.messageName = name
	testerSelector = FakeSelector('internal_is'+self.name)
	self.addMethod(symbolTable,testerSelector,
		    generateTrueMethod(testerSelector))
	symbolTable['Object'].addMethod(symbolTable,testerSelector,
		    generateFalseMethod(testerSelector))
	blk1 = Block()
	blk1.add_instruction('BlockArg 0')
	blk1.add_instruction("MCall 0 'internal_is%s'"%(self.name))
	blk2 = Block()
	blk2.add_instruction('Block #%s'%(blk1.getName()))
	blk2.add_instruction('Arg 0')
	blk2.add_instruction('Self')
	blk2.add_instruction("MCall 2 'onExceptionMatching:do:'")
	blk2.add_instruction("Return")
	self.exceptionHandlingBlocks = [blk1,blk2]
	symbolTable['Block'].addMethod(symbolTable,self.selector,
		PseudoMethod(blk2.getName(),self.selector))
    def addMixin(self,mixinName,symbolTable):
	self.mixins += [mixinName]
	if self.methodTable:
	    mixin = symbolTable[mixinName]
	    self.methodTable.addParent(mixin.getMethodTable(symbolTable))
	    self.classMethodTable.addParent(mixin.classMethodTable)
    def addMethod(self,symbolTable,selector,method):
	if self.exception:
	    self.defineExceptionMethod(symbolTable)
	self.getMethodTable(symbolTable)
	if method.isClass:
	    mt = self.classMethodTable
	elif method.isConstructor:
	    self.methodTable.addMethod(selector.messageName,
		    method.block.getName())
	    classMethodBlock = Block()
	    classMethodBlock.incrementTemporaries()
	    classMethodBlock.add_instruction('Self')
	    classMethodBlock.add_instruction("MCall 0 'basicNew'")
	    classMethodBlock.add_instruction("StoreTemp 0")
	    for i in range(0,method.getArgCount()):
		classMethodBlock.add_instruction("Arg %i"%(i))
	    classMethodBlock.add_instruction("Temp 0")
	    classMethodBlock.add_instruction("MCall %i '%s'"%\
		    (method.getArgCount(),selector.messageName))
	    classMethodBlock.add_instruction("Temp 0")
	    #classMethodBlock.add_instruction("MCall 0 'secure'")
	    classMethodBlock.add_instruction("Return")
	    self.exceptionHandlingBlocks += [classMethodBlock]
	    self.classMethodTable.addMethod(selector.messageName,
		    classMethodBlock.getName())
	    return
	else:
	    mt = self.methodTable
	if method.isAlias:
	    mt.addAlias(selector.messageName,method.aliasTarget.messageName)
	else:
	    mt.addMethod(selector.messageName,method.block.getName())
    def resolveMixins(self,stable):
	for mixinName in self.mixins:
	    # TODO mixin hierarchy?
	    methods = stable[self.mixinName].getMethods(stable)
	    for method in methods:
		(selector,method) = method
		#print 'MIXIN DEBUG', cls, selector, method
		# TODO conditional add
		cls.addMethod(stable,selector,method)
    def generateCode(self,stable):
	self.getMethodTable(stable) #ensure method tables initialized
	self.addClassMethod(stable)
	#self.resolveMixins(stable)
	gvar = Global()  # class/singleton object reference
	gvar.setName(self.name) # our name
	obj = BytecodeObject(self.name) # class/singleton object
	gvar.setValue(obj) # which the reference points to
	if self.singleton:
	    obj.setMTable(self.methodTable) #singletons get object mtable
	    return [self.methodTable,obj,gvar]+self.exceptionHandlingBlocks
	else:
	    obj.setMTable(self.classMethodTable) #non-singletons get factory one
	    block = Block(name = '_new_' + self.name) # new method
	    block.add_instruction("Int %i"%\
		    (self.getInstanceVariableCount(stable)))
	    block.add_instruction("Alloc %i"% \
		    self.getInstanceVariableCount(stable))
	    block.add_instruction("Dup")
	    block.add_instruction("ChMTable %%%s"%(self.methodTable.name))
	    block.add_instruction("Return")
	    self.classMethodTable.addMethod('basicNew',block.name)
	    return [self.methodTable,self.classMethodTable,block,obj,gvar]+\
		    self.exceptionHandlingBlocks
    def getParent(self,symbolTable):
	if self.name != self.parent:
	    return symbolTable[self.parent]
	else:
	    return None
    def getInstanceVariableCount(self,symbolTable):
	parent = self.getParent(symbolTable)
	if parent:
	    count = parent.getInstanceVariableCount(symbolTable)
	else:
	    count = 0
	return count + len(self.ivars)
    def generateInstanceSymbolTable(self,symbolTable):
	if self.singleton:
	    return {} #singletons haven't got any instance variables.
	parent = self.getParent(symbolTable)
	if parent:
	    ivarNum = parent.getInstanceVariableCount(symbolTable)
	else:
	    ivarNum = 0
	res = {}
	for ivar in self.ivars:
	    res[ivar] = InstanceVariableEntry(ivarNum)
	    ivarNum += 1
	return res
    def storeCode(self,block): ERROR
    def loadCode(self,block):
	block.add_instruction('Global $%s'%(self.name))