示例#1
0
	def visit_Import (self, node):	# Import .. can only import modules
		names = [alias for alias in node.names if not alias.name.startswith (self.stubsName)]
		
		if not names:
			self.skipSemiNew = True
			return
		
		for index, alias in enumerate (names):
			try:
				self.useModule (alias.name)
			except Exception as exception:
				utils.enhanceException (exception, moduleName = self.module.metadata.name, lineNr = self.lineNr, message = 'Can\'t import module \'{}\''.format (alias.name))
			
			if alias.asname:
				self.emit ('var {} =  __init__ (__world__.{})', self.filterId (alias.asname), self.filterId (alias.name))
			else:
				aliasSplit = alias.name.split ('.', 1)
				head = aliasSplit [0]
				tail = aliasSplit [1] if len (aliasSplit) > 1 else ''
				
				self.importHeads.add (head)
				self.emit ('__nest__ ({}, \'{}\', __init__ (__world__.{}))', self.filterId (head), self.filterId (tail), self.filterId (alias.name))
			
			if index < len (names) - 1:
				self.emit (';\n')
示例#2
0
	def compile (self):
		# Define names early, since they are cross-used in module compilation
		prefix = 'org.{}'.format (__base__.__envir__.transpilerName)
		self.coreModuleName = '{}.{}'.format (prefix, '__core__')
		self.baseModuleName = '{}.{}'.format (prefix, '__base__')
		self.standardModuleName = '{}.{}'.format (prefix, '__standard__')
		self.builtinModuleName = '{}.{}'.format (prefix, '__builtin__')
		self.mainModuleName = self.sourceFileName [ : -3]

		# Module compilation
		Module (self, ModuleMetadata (self, self.coreModuleName))
		Module (self, ModuleMetadata (self, self.baseModuleName))
		Module (self, ModuleMetadata (self, self.standardModuleName))
		Module (self, ModuleMetadata (self, self.builtinModuleName))
					
		try:
			moduleMetadata = ModuleMetadata (self, self.mainModuleName)
			Module (self, moduleMetadata)	# Will trigger recursive compilation
		except Exception as exception:
			utils.enhanceException (
				exception,
				message = str (exception)
			)
			
		# Join all non-inline modules
		normallyImportedTargetCode = ''.join ([
			self.moduleDict [moduleName] .targetCode
			for moduleName in sorted (self.moduleDict)
			if not moduleName in (self.coreModuleName, self.baseModuleName, self.standardModuleName, self.builtinModuleName, self.mainModuleName)
		])
		
		# And sandwich them between the in-line modules
		targetCode = (
			self.header +
			'function {} () {{\n'.format (self.mainModuleName) +
			self.moduleDict [self.coreModuleName].targetCode +
			self.moduleDict [self.baseModuleName] .targetCode +
			self.moduleDict [self.standardModuleName] .targetCode +
			self.moduleDict [self.builtinModuleName].targetCode +
			normallyImportedTargetCode +
			self.moduleDict [self.mainModuleName].targetCode +
			'	return __all__;\n' +
			'}\n' +
			'window [\'{0}\'] = {0} ();\n'.format (self.mainModuleName)
		)	
		
		targetFileName = '{}/{}.js'.format ('{}/{}'.format (self.sourceDir, __base__.__envir__.targetSubDir), self.mainModuleName)
		utils.log (False, 'Saving result in: {}\n', targetFileName)
		with utils.create (targetFileName) as aFile:
			aFile.write (targetCode)

		miniFileName = '{}/{}/{}.min.js'.format (self.sourceDir, __base__.__envir__.targetSubDir, self.mainModuleName)
		utils.log (False, 'Saving minified result in: {}\n', miniFileName)
		
		if not utils.commandArgs.nomin:
			minify.run (targetFileName, miniFileName)
示例#3
0
		def assignTarget (target, value, pathIndices = []):
			def emitPathIndices ():
				if pathIndices:
					self.emit (' ')
					for pathIndex in pathIndices:
						self.emit ('[{}]'.format (pathIndex))
				else:	# Most frequent and simple case, only one atomary LHS
					pass
					
			# Special case for target slice (as opposed to target index)
			if type (target) == ast.Subscript and type (target.slice) == ast.Slice:
				self.visit (target.value)
				
				try:
					self.emit ('.__setslice__ (')
					
					if target.slice.lower == None:
						self.emit ('0')
					else:
						self.visit (target.slice.lower)
						
					self.emit (', ')
					if target.slice.upper == None:
						self.emit ('null')
					else:
						self.visit (target.slice.upper)
				
					self.emit (', ')
					if target.slice.step:
						self.visit (target.slice.step)
					else:
						self.emit ('null')

					self.emit (', ')
					self.visit (value)
							
					self.emit (')')
				except Exception as exception:
					utils.enhanceException (exception, lineNr = self.lineNr, message = 'Invalid LHS slice')	
			else:
				if isPropertyAssign and not target.id == self.getTemp ('left'):
					self.emit ('Object.defineProperty ({}, \'{}\', '.format (self.getscope () .name, target.id))
					self.visit (value)
					emitPathIndices ()
					self.emit (');')
				else:
					if type (target) == ast.Name:
						if type (self.getscope ()) == ast.ClassDef and target.id != self.getTemp ('left'):
							self.emit ('{}.'.format (self.getscope () .name))
						else:
							self.emit ('var ')
							
					self.visit (target)
					self.emit (' = ')
					self.visit (value)
					emitPathIndices ()
示例#4
0
	def visit_ClassDef (self, node):
		if not self.scopes:
			self.all.add (node.name)

		self.emit ('var {0} = __class__ (\'{0}\', [', node.name)
		if node.bases:
			for index, expr in enumerate (node.bases):
				try:
					self.emitComma (index)
					self.visit_Name (expr)
				except Exception as exception:
					utils.enhanceException (moduleName = self.module.metadata.name, lineNr = node.lineno, message = 'Invalid base class')
		else:
			self.emit ('object')
		self.emit ('], {{')
		self.inscope (self.classScope)			
		
		self.indent ()
		classVarAssigns = []
		index = 0
		for stmt in node.body:
			if type (stmt) == ast.FunctionDef:
				self.emitComma (index, False)
				self.visit (stmt)
				index += 1
			elif type (stmt) == ast.Assign:
				classVarAssigns.append (stmt)
			elif (
				type (stmt) == ast.Expr and type (stmt.value) == ast.Call and
				type (stmt.value.func) == ast.Name and stmt.value.func.id == '__pragma__'
			):
				self.visit (stmt)
		self.dedent ()
				
		self.emit ('\n}})')

		for index, classVarAssign in enumerate (classVarAssigns):
			self.emit (';\n')
			self.emit ('{}.', node.name)
			self.visit (classVarAssign)

		self.descope ()	# No earlier, class vars need it
示例#5
0
	def parse (self):
		try:
			utils.log (False, 'Parsing module: {}\n', self.metadata.sourcePath)
			
			with open (self.metadata.sourcePath) as sourceFile:
				self.sourceCode = utils.extraLines + sourceFile.read ()
				
			self.parseTree = ast.parse (self.sourceCode)
		except SyntaxError as syntaxError:
			utils.enhanceException (
				syntaxError,
				moduleName = self.metadata.name,
				lineNr = syntaxError.lineno,
				message = (
					'{} <SYNTAX FAULT] {}'.format (
						syntaxError.text [:syntaxError.offset].lstrip (),
						syntaxError.text [syntaxError.offset:].rstrip ()
					)
					if syntaxError.text else
					syntaxError.args [0]
				)
			)
示例#6
0
		def assignTarget (target, value):
			# Special case for target slice (as opposed to target index)
			if type (target) == ast.Subscript and type (target.slice) == ast.Slice:
				self.visit (target.value)
				
				try:
					self.emit ('.__setslice__ (')
					
					if target.slice.lower == None:
						self.emit ('0')
					else:
						self.visit (target.slice.lower)
						
					self.emit (', ')
					if target.slice.upper == None:
						self.emit ('null')
					else:
						self.visit (target.slice.upper)
				
					self.emit (', ')
					if target.slice.step:
						self.visit (target.slice.step)
					else:
						self.emit ('null')

					self.emit (', ')
					self.visit (value)
							
					self.emit (')')
				except Exception as exception:
					utils.enhanceException (exception, lineNr = target.lineno, message = 'Invalid LHS slice')	
			else:
				if not (self.scopes and self.scopes [-1] == self.classScope) and type (target) == ast.Name:
					# No class var so <className>. not already emitted
					self.emit ('var ')
				
				self.visit (target)
				self.emit (' = ')
				self.visit (value)		
示例#7
0
	def visit_ClassDef (self, node):
		if type (self.getscope ()) == ast.Module:
			self.all.add (node.name)

		self.emit ('var {0} = __class__ (\'{0}\', [', self.filterId (node.name))
		if node.bases:
			for index, expr in enumerate (node.bases):
				try:
					self.emitComma (index)
					self.visit_Name (expr)
				except Exception as exception:
					utils.enhanceException (moduleName = self.module.metadata.name, lineNr = self.lineNr, message = 'Invalid base class')
		else:
			self.emit ('object')
		self.emit ('], {{')
		self.inscope (node)			
		
		self.indent ()
		classVarAssigns = []
		index = 0
		for stmt in node.body:
			if type (stmt) == ast.FunctionDef:
				self.emitComma (index, False)
				self.visit (stmt)
				index += 1
			elif type (stmt) == ast.Assign:
				classVarAssigns.append (stmt)	# Has to be done after the class because tuple assignment requires the use of an algorithm
			elif self.getPragmaKindFromExpr (stmt):
				self.visit (stmt)
		self.dedent ()
				
		self.emit ('\n}})')

		for index, classVarAssign in enumerate (classVarAssigns):
			self.emit (';\n')
			self.visit (classVarAssign)

		self.descope ()	# No earlier, class vars need it
示例#8
0
	def visit_Subscript (self, node):
		self.visit (node.value)
		
		if type (node.slice) == ast.Slice:	# Then we're sure node.ctx == ast.Load	
			try:
				if node.slice.step == None:
					self.emit ('.slice (')
					
					if node.slice.lower == None:
						self.emit ('0')
					else:
						self.visit (node.slice.lower)
						
					if node.slice.upper != None:
						self.emit (', ')
						self.visit (node.slice.upper)
				else:
					self.emit ('.__getslice__ (')
					
					if node.slice.lower == None:
						self.emit ('0')
					else:
						self.visit (node.slice.lower)
						
					self.emit (', ')
					if node.slice.upper == None:
						self.emit ('null')
					else:
						self.visit (node.slice.upper)
				
					self.emit (', ')
					self.visit (node.slice.step)
					
				self.emit (')')
			except Exception as exception:
				utils.enhanceException (exception, lineNr = self.lineNr, message = 'Invalid RHS slice')	
		else:								# Here target.slice is an ast.Index, target.ctx may vary (ast.ExtSlice not dealth with yet)
			self.visit (node.slice)
示例#9
0
	def visit_ImportFrom (self, node):	# From .. import can import modules or entities in modules
		if node.module.startswith (self.stubsName):
			self.skipSemiNew = True 
			return
		
		try:			
			# N.B. It's ok to call a modules __init__ multiple times, see __core__.mod.js
			for index, alias in enumerate (node.names):
				if alias.name == '*':											# * Never refers to modules, only to entities in modules
					if len (node.names) > 1:
						raise Error (moduleName = module.metadata.name, lineNr = node.lineno, message = 'Can\'t import module \'{}\''.format (alias.name))
						
					module = self.useModule (node.module)

					for index, name in enumerate (module.all):				
						self.emit ('var {0} = __init__ (__world__.{1}).{0}', self.filterId (name), self.filterId (node.module))
						if index < len (module.all) - 1:
							self.emit (';\n')
				else:
					try:														# Try if alias.name denotes a module
						self.useModule ('{}.{}'.format (node.module, alias.name))
												
						if alias.asname:
							self.emit ('var {} = __init__ (__world__.{}.{})', self.filterId (alias.asname), self.filterId (node.module), self.filterId (alias.name))
						else:
							self.emit ('var {0} = __init__ (__world__.{1}.{0})', self.filterId (alias.name), self.filterId (node.module))						
					except:														# If it doesn't it denotes an entity inside a module
						self.useModule (node.module)
						
						if alias.asname:
							self.emit ('var {} = __init__ (__world__.{}).{}', self.filterId (alias.asname), self.filterId (node.module), self.filterId (alias.name))
						else:
							self.emit ('var {0} = __init__ (__world__.{1}).{0}', self.filterId (alias.name), self.filterId (node.module))						
					if index < len (node.names) - 1:
						self.emit (';\n')
		except Exception as exception:
			utils.enhanceException (exception, lineNr = self.lineNr, message = 'Can\'t import from module \'{}\''.format (node.module))
示例#10
0
	def __init__ (self, module):	
		self.module = module
		
		self.targetFragments = []		
		self.skipSemiNew = False
		self.indentLevel = 0
		self.scopes = []
		self.use = set ()
		self.all = set ()
		self.importHeads = set ()
		
		self.aliasers = [self.getAliaser (*alias) for alias in (
# START predef_aliases 
			('js_sort', 'sort'),
			('sort', 'py_sort'),
			('js_split', 'split'),
			('split', 'py_split'),
			('keys', 'py_keys'),
			('js_arguments', 'arguments'),
			('arguments', 'py_arguments')
# END predef_aliases
		)]
		
		self.tempIndices = {}
		self.stubsName = 'org.{}.stubs.'.format (__base__.__envir__.transpilerName)
		
		self.nameConsts = {
			None: 'null',
			True: 'true',
			False: 'false'
		}
		
		self.operators = {
			ast.Invert: ('~', 100),
			ast.UAdd: ('+', 100),
			ast.USub: ('-', 100),
			ast.Pow: (None, 110),		# Dealt with separately
			ast.Mult: ('*', 90),
			ast.MatMult: (None,	90),	# Dealt with separately
			ast.Div: ('/', 90),
			ast.FloorDiv: (None, 90),	# Dealt with separately
			ast.Mod: ('%', 90), 
			ast.Add: ('+', 80),
			ast.Sub: ('-', 80),
			ast.LShift: ('<<', 70),
            ast.RShift: ('>>', 70),
			ast.BitAnd: ('&', 60),
			ast.BitXor: ('^', 50),
			ast.BitOr: ('|', 40),
			ast.Eq: ('==', 30),
			ast.NotEq: ('!=', 30),
			ast.Lt: ('<', 30),
			ast.LtE: ('<=', 30),
			ast.Gt: ('>', 30),
			ast.GtE: ('>=', 30),
			ast.Is: ('===', 30),		# Not really, but closest for now
			ast.IsNot: ('!==', 30),		# Not really, but closest for now
			ast.In:	(None, 30),			# Dealt with separately
			ast.NotIn: (None, 30),		# Dealt with separately
			ast.Not: ('!', 20), 
			ast.And: ('&&', 10),
			ast.Or: ('||', 0)
		}
		
		self.allowKeywordArgs = utils.commandArgs.kwargs
		self.memoizeCalls = utils.commandArgs.fcall
		self.codeGeneration = True
		
		try:
			self.visit (module.parseTree)
		except Exception as exception:
			utils.enhanceException (exception, moduleName = self.module.metadata.name, lineNr = self.lineNr)
			
		if self.tempIndices:
			raise utils.Error (
				message = '\n\tTemporary variables leak in code generator: {}'.format (self.tempIndices)
			)