Esempio n. 1
0
    def generateCode(self,gSym,iSym,lSym,cref,blocko,blocki):
	# set up internal return stuff
	oldReturn = lSym['_return']
	lSym['_return'] = None
	oldSelf = lSym['@']
	# set up new block
	block = Block(blocko.getName()+"_inner",True)
	# transfer arguments
	argNumber = 0
	start = blocko.temporaries_count
	for arg in self.args:
	    # implicit given
	    if arg[0:2] == '@@':
		lSym['@'] = TemporaryEntry(blocko)
	    # assignment
	    elif arg[0:1] == '@':
		lSym[arg[1:]] = TemporaryEntry(blocko)
	    # ignore
	    elif arg[0:1] == '_':
		TemporaryEntry(blocko)
	    argNumber += 1
	finish = blocko.temporaries_count - 1
	if finish>=start:
	    block.add_instruction("BlockArgs %i %i"%(start,finish))
	blocki.add_instruction("Block #%s"%(block.getName()))
	self.expr.generateCode(gSym,iSym,lSym,cref,blocko,block)
	if lSym['_return']==True:
	    block.add_instruction('RetValReturn')
	elif lSym['_return']:
	    lSym['_return'].loadCode(block)
	    block.add_instruction('Return')
	lSym['_blocks'].append(block)
	lSym['_return'] = oldReturn
	lSym['@'] = oldSelf
Esempio n. 2
0
    def generateCode(self,symbolTable):
	test_global = Global()
	store_global = Global()
	test_global.setName('test'+self.name)
	store_global.setName('store'+self.name)

	secondary_block = Block(innerBlock = True)
	secondary_block.add_instruction('Global $store'+self.name)
	secondary_block.add_instruction('Return')

	blocks = []
	self.block.add_instruction('Block #'+secondary_block.getName())
	self.block.add_instruction('Global $test'+self.name)
	self.block.add_instruction("MCall 1 'and:'")
	self.block.add_instruction('Pop')
	self.expr.generateCode(symbolTable,
		{},
		{'_return': None,'@':None,'_blocks':blocks},
		None,
		self.block,
		self.block)
	self.block.add_instruction('Dup')
	self.block.add_instruction('StoreGlobal $store'+self.name)
	self.block.add_instruction('Global $true')
	self.block.add_instruction('StoreGlobal $test'+self.name)
	self.block.add_instruction("Return")
	return [self.block,secondary_block,store_global,test_global]+blocks
Esempio n. 3
0
    def generateCode(self,gSym,iSym,lSym,cref,blocko,blocki):
	block = Block(blocko.getName()+"_inner",True)
	blocki.add_instruction("Block #%s"%(block.getName()))
	if self.operator:
	    if self.messageName == '?//' or self.messageName == ':[]=':
		self.argCount = 2
	    elif self.messageName == '[~~]':
		self.argCount = 3
	    elif self.messageName == ':[~~]=':
		self.argCount = 4
	    else:
		self.argCount = 1
	for i in range(0,self.argCount):
	    block.add_instruction('BlockArg %i'%(i+1))
	block.add_instruction('BlockArg 0')
	if self.messageName == "+":
	    block.add_instruction("Add 1 '+'")
	else:
	    block.add_instruction("MCall %i '%s'"%\
		    (self.argCount,self.messageName))

	lSym['_blocks'].append(block)
Esempio n. 4
0
    def generateCode(self,symbolTable):
	argNumber = 0
	blocks = []
	selector = Selector(self.selector,False)
	for value in self.values:
	    block = Block()
	    block.add_instruction('Arg %i'%(argNumber))
	    block.add_instruction("MCall 0 '()'")
	    block.add_instruction("Return")
	    symbolTable[value].addMethod(symbolTable,
		    selector,
		    PseudoMethod(block.getName(),selector))
	    blocks += [block]
	    argNumber = argNumber + 1
	return blocks
Esempio n. 5
0
    def parseMethodCode(self):
	if self.tokenizer.check(';'):
	    self.expr = None
	else:
	    self.tokenizer.require('{')
	    self.expr = parseExpression(self.tokenizer)
	    self.tokenizer.require('}')
	if self.selector.operator:
	    name = None
	else:
	    name = self.selector.messageName
	    name = name + "_" + self.cls
	    if self.isClass:
		name = name + "_class"
	self.block = Block(name = name,nameSet = False)
	self.name = self.block.getName()
	return True
Esempio n. 6
0
    def tryParse(self):
	publicToken = self.tokenizer.check('public')
	if not publicToken:
	    publicToken = self.tokenizer.check('private')
	if not self.tokenizer.check('global'):
	    if publicToken:
		self.tokenizer.push(publicToken)
	    return False
	self.tokenizer.require('$')
	idToken = self.tokenizer.nextToken()
	if idToken.type() != TokenTypes.identifier:
	    raise SyntaxError("expected identifier: "+idToken.errForm())
	self.name = idToken.str
	self.tokenizer.require('=')
	self.expr = parseExpressionSimple(self.tokenizer)
	if not self.expr:
	    raise SyntaxError('expression required for global')
	self.tokenizer.require(';')
	self.block = Block(innerBlock = False)
	return True
Esempio n. 7
0
    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]
Esempio n. 8
0
    def parseArgsWithSelector(self):
	self.args = []
	while not self.tokenizer.peekCheck('{') and \
		not self.tokenizer.peekCheck(';') and \
		not self.tokenizer.peekCheck('('):
	    if not self.tokenizer.check('@'):
		if self.tokenizer.check('#'):
		    class Foo: pass
		    self.block = Foo()
		    name = self.tokenizer.nextToken().str
		    self.block.name = name
		    self.block.getName = lambda: name
		    self.special = True
		    self.name = self.block.name
		    self.tokenizer.check(';')
		    return True
		else:
		    raise SyntaxError('@ or {: '+
				    self.tokenizer.nextToken().errForm())
	    self.args += ['@'+self.tokenizer.nextToken().str]
	    if not self.tokenizer.check(','):
		break
Esempio n. 9
0
class MethodDecl(ASTNode):
    def tryParse(self):
	self.access = ''
	publicToken = self.tokenizer.check('public')
	if publicToken:
	    self.access = 'public'
	else:
	    publicToken = self.tokenizer.check('private')
	    if publicToken:
		self.access = 'private'
	dollarSign = self.tokenizer.check('$')
	if not dollarSign:
	    if publicToken:
		self.tokenizer.push(publicToken)
	    return False
	classToken = self.tokenizer.nextToken()
	self.cls = classToken.str
	self.isClass = self.tokenizer.check('class')
	self.isMixin = False # TODO mixin methods
	mixinToken = self.tokenizer.check('mixin')
	self.expr = None
	if mixinToken:
	    self.tokenizer.push(mixinToken)
	    self.tokenizer.push(classToken)
	    self.tokenizer.push(dollarSign)
	    if publicToken:
		self.tokenizer.push(publicToken)
	    return False
	# TODO constructor code generation
	self.isConstructor = self.tokenizer.check('constructor')
	self.isAbstract = self.tokenizer.check('abstract')
	self.isUndefine = self.tokenizer.check('undefine')
	if not self.isAbstract:
	    self.isAbstract = self.tokenizer.check('optional')
	self.isFinal = self.tokenizer.check('final')
	self.isAlias = self.tokenizer.check('alias')
	self.special = False
	self.selector = tryParse(SelectorLiteral, self.tokenizer)
	if self.selector:
	    if self.isAlias:
		self.aliasTarget = tryParse(SelectorLiteral, self.tokenizer)
		if not self.aliasTarget:
		    raise SyntaxError('Expected selector; found: ' + \
			    self.tokenizer.nextToken().errForm())
		self.tokenizer.require(';')
		return True
	    if self.isAbstract:
		self.tokenizer.require(';')
		return True
	    else:
		self.parseArgsWithSelector()
	else:
	    self.parseInterwoven()
	if self.special:
	    return True
	else:
	    self.parseSecureLevelDecl()
	    return self.parseMethodCode()
    def parseArgument(self):
	arg = self.tryParseArgument()
	if not arg:
	    raise SyntaxError("argument expected: "+\
		    self.tokenizer.nextToken().errForm())
	return arg
    def tryParseArgument(self):
	if self.tokenizer.check('@'):
	    id = self.tokenizer.nextToken()
	    if id.type() != TokenTypes.identifier:
		raise SyntaxError("not id: "+id.errForm())
	    return "@"+id.str
	elif self.tokenizer.check('_'):
	    return "_"
	elif self.tokenizer.check('!'):
	    id = self.tokenizer.nextToken()
	    if id.type() != TokenTypes.identifier:
		raise SyntaxError("not id: "+id.errForm())
	    return "!"+id.str
	else:
	    return None
    def getArgCount(self):
	return len(self.args)
    def parseInterwoven(self):
	nextToken = self.tokenizer.nextToken()
	if nextToken.type() == TokenTypes.operator:
	    if nextToken.str not in ['?','[',':[', '(']:
		self.args = [self.parseArgument()]
		self.selector = Selector(nextToken.str,True)
		return
	    elif nextToken.str == '?':
		self.selector = Selector('?//',True)
		self.args = [self.parseArgument()]
		self.tokenizer.require('//')
		self.args += [self.parseArgument()]
		return 
	    elif nextToken.str == ':[':
		self.args = [self.parseArgument()]
		if self.tokenizer.check('~'):
		    self.selector = Selector(':[~~]=',True)
		    self.args += [self.parseArgument()]
		    self.tokenizer.require('~')
		    self.args += [self.parseArgument()]
		else:
		    self.selector = Selector(':[]=',True)
		self.tokenizer.require(']=')
		self.args += [self.parseArgument()]
		return
	    elif nextToken.str == '[':
		self.args = [self.parseArgument()]
		if self.tokenizer.check('~'):
		    self.selector = Selector('[~~]',True)
		    self.args += [self.parseArgument()]
		    self.tokenizer.require('~')
		    self.args += [self.parseArgument()]
		else:
		    self.selector = Selector('[]',True)
		self.tokenizer.require(']')
		return
	    elif nextToken.str == '(':
		self.args = [self.parseArgument()]
		# TODO (for C3 probably) check if this is a list and match
		self.selector = Selector('()',True)
		self.tokenizer.require(')')
		return
	elif nextToken.type() == TokenTypes.identifier:
	    #so it's either a unary message-send or a keyworder.
	    colon = self.tokenizer.checkNoWhitespace(':')
	    if colon:
		self.args = [self.parseArgument()]
		name = nextToken.str + ':'
		while True:
		    nextToken = self.tokenizer.nextToken()
		    if nextToken.type() != TokenTypes.identifier:
			self.tokenizer.push(nextToken)
			break
		    self.tokenizer.require(':')
		    self.args += [self.parseArgument()]
		    name += nextToken.str + ':'
		self.selector = Selector(name,False)
	    else:
		self.args = []
		self.selector = Selector(nextToken.str,False)
	    return

    def parseArgsWithSelector(self):
	self.args = []
	while not self.tokenizer.peekCheck('{') and \
		not self.tokenizer.peekCheck(';') and \
		not self.tokenizer.peekCheck('('):
	    if not self.tokenizer.check('@'):
		if self.tokenizer.check('#'):
		    class Foo: pass
		    self.block = Foo()
		    name = self.tokenizer.nextToken().str
		    self.block.name = name
		    self.block.getName = lambda: name
		    self.special = True
		    self.name = self.block.name
		    self.tokenizer.check(';')
		    return True
		else:
		    raise SyntaxError('@ or {: '+
				    self.tokenizer.nextToken().errForm())
	    self.args += ['@'+self.tokenizer.nextToken().str]
	    if not self.tokenizer.check(','):
		break
    def parseSecureLevelDecl(self):
	# TODO check these values and store them in a cleaner way.
	# TODO Actually use securelevels.
	if not self.tokenizer.check('('):
	    return # no securelevel decl
	self.securelevel = self.tokenizer.nextToken()
	self.tokenizer.require(',')
	self.writability = self.tokenizer.nextToken()
	self.tokenizer.require(')')
    def parseMethodCode(self):
	if self.tokenizer.check(';'):
	    self.expr = None
	else:
	    self.tokenizer.require('{')
	    self.expr = parseExpression(self.tokenizer)
	    self.tokenizer.require('}')
	if self.selector.operator:
	    name = None
	else:
	    name = self.selector.messageName
	    name = name + "_" + self.cls
	    if self.isClass:
		name = name + "_class"
	self.block = Block(name = name,nameSet = False)
	self.name = self.block.getName()
	return True
    def __str__(self):
	res = '$'
	res += self.cls
	if self.isAlias:
	    res += ' alias '
	res += str(self.selector)
	res += ' '
	if self.isAlias:
	    res += str(self.aliasTarget)
	    res += ';'
	else:
	    for arg in self.args:
		res += '@'
		res += arg
		res += ', '
	    res += "{\n"
	    res += str(self.expr)
	    res += "\n}\n"
	return res
    def registerMethod(self,symbolTable):
	if not self.isAbstract: # TODO addAbstract() and check instead
	    symbolTable[self.cls].addMethod(symbolTable,self.selector,self)
    def generateCode(self,symbolTable):
	self.registerMethod(symbolTable)
	if self.isAlias or self.isAbstract or self.special:
	    return []
	cls = symbolTable[self.cls]
	itable = cls.generateInstanceSymbolTable(symbolTable)
	table = self.generateLocalSymbolTable(itable)
	table['_classMethod'] = self.isClass
	self.block.add_instruction('" '+self.selector.messageName)
	if self.expr:
	    self.expr.generateCode(symbolTable,
				   itable,
				   table,
				   cls,
				   self.block,
				   self.block)
	if table['_return'].__class__ == SelfEntry:
	    self.block.add_instruction("SReturn")
	elif table['_return']==True:
	    self.block.add_instruction("RetValReturn")
	elif table['_return']:
	    table['_return'].loadCode(self.block)
	    self.block.add_instruction("Return")
	return [self.block]+table['_blocks']
    def generateLocalSymbolTable(self,itable):
	res = {'@':SelfEntry(),
		'_return':SelfEntry(),
		'_blocks':[]}
	argNum = 0
	if self.selector.messageName == '()' and len(self.args) == 1:
	    self.block.add_instruction("AllocFromArgs")
	    self.block.add_instruction("Dup")
	    self.block.add_instruction("ChMTable %PrimitiveArray")
	    realArg = self.args[0]
	    if realArg[0] == '@':
		arg = realArg[1:]
		res[arg] = TemporaryEntry(self.block)
		self.block.add_instruction('StoreTemp %i'%\
			(res[arg].getNumber()))
	    elif realArg[0] == '_':
		self.block.add_instruction("Pop")
	    elif realArg[0] == '!':
		arg = realArg[1:]
		ivar = itable[arg]
		ivar.storeCode(self.block)
	else:
	    for realArg in self.args:
		if realArg[0] == '@':
		    arg = realArg[1:]
		    res[arg] = ArgumentEntry(argNum)
		elif realArg[0] == '_':
		    pass
		elif realArg[0] == '!':
		    arg = realArg[1:]
		    ivar = itable[arg]
		    self.block.add_instruction('Arg %i'%(argNum))
		    ivar.storeCode(self.block)
		argNum += 1
	return res
Esempio n. 10
0
    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
Esempio n. 11
0
    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())
Esempio n. 12
0
    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))
Esempio n. 13
0
class GlobalDecl(ASTNode):
    def tryParse(self):
	publicToken = self.tokenizer.check('public')
	if not publicToken:
	    publicToken = self.tokenizer.check('private')
	if not self.tokenizer.check('global'):
	    if publicToken:
		self.tokenizer.push(publicToken)
	    return False
	self.tokenizer.require('$')
	idToken = self.tokenizer.nextToken()
	if idToken.type() != TokenTypes.identifier:
	    raise SyntaxError("expected identifier: "+idToken.errForm())
	self.name = idToken.str
	self.tokenizer.require('=')
	self.expr = parseExpressionSimple(self.tokenizer)
	if not self.expr:
	    raise SyntaxError('expression required for global')
	self.tokenizer.require(';')
	self.block = Block(innerBlock = False)
	return True
    def extractSymbols(self):
	return {self.name: self}
    def generateCode(self,symbolTable):
	test_global = Global()
	store_global = Global()
	test_global.setName('test'+self.name)
	store_global.setName('store'+self.name)

	secondary_block = Block(innerBlock = True)
	secondary_block.add_instruction('Global $store'+self.name)
	secondary_block.add_instruction('Return')

	blocks = []
	self.block.add_instruction('Block #'+secondary_block.getName())
	self.block.add_instruction('Global $test'+self.name)
	self.block.add_instruction("MCall 1 'and:'")
	self.block.add_instruction('Pop')
	self.expr.generateCode(symbolTable,
		{},
		{'_return': None,'@':None,'_blocks':blocks},
		None,
		self.block,
		self.block)
	self.block.add_instruction('Dup')
	self.block.add_instruction('StoreGlobal $store'+self.name)
	self.block.add_instruction('Global $true')
	self.block.add_instruction('StoreGlobal $test'+self.name)
	self.block.add_instruction("Return")
	return [self.block,secondary_block,store_global,test_global]+blocks
    def loadCode(self,block):
	block.add_instruction("Self")
	block.add_instruction("Call 0 #%s"%(self.block.getName()))
	return [self.block]