def AssignmentExpression(self, operator, left, right, **kwargs): operator = operator[:-1] if left['type'] == 'MemberExpression': self.emit(left['object']) if left['computed']: self.emit(left['property']) self.emit(right) if operator: self.emit('STORE_MEMBER_OP', operator) else: self.emit('STORE_MEMBER') else: self.emit(right) if operator: self.emit('STORE_MEMBER_DOT_OP', left['property']['name'], operator) else: self.emit('STORE_MEMBER_DOT', left['property']['name']) elif left['type'] == 'Identifier': if left['name'] in SPECIAL_IDENTIFIERS: raise MakeError('SyntaxError', 'Invalid left-hand side in assignment') self.emit(right) if operator: self.emit('STORE_OP', left['name'], operator) else: self.emit('STORE', left['name']) else: raise MakeError('SyntaxError', 'Invalid left-hand side in assignment')
def VariableDeclarator(self, id, init, **kwargs): name = id['name'] if name in SPECIAL_IDENTIFIERS: raise MakeError('Invalid left-hand side in assignment') self.declared_vars.append(name) if init is not None: self.emit(init) self.emit('STORE', name) self.emit('POP')
def BreakStatement(self, label, **kwargs): if label is None: self.emit('JUMP', self.implicit_breaks[-1]) else: label = label.get('name') if label not in self.declared_break_labels: raise MakeError('SyntaxError', 'Undefined label \'%s\'' % label) else: self.emit('JUMP', self.declared_break_labels[label])
def ForInStatement(self, left, right, body, **kwargs): # prepare the needed labels body_start_label = self.exe.get_new_label() continue_label = self.exe.get_new_label() break_label = self.exe.get_new_label() # prepare the name if left['type'] == 'VariableDeclaration': if len(left['declarations']) != 1: raise MakeError( 'SyntaxError', ' Invalid left-hand side in for-in loop: Must have a single binding.' ) self.emit(left) name = left['declarations'][0]['id']['name'] elif left['type'] == 'Identifier': name = left['name'] else: raise MakeError('SyntaxError', 'Invalid left-hand side in for-loop') # prepare the iterable self.emit(right) # emit ForIn Opcode self.emit('FOR_IN', name, body_start_label, continue_label, break_label) # a special continue position self.emit('LABEL', continue_label) self.emit('NOP') self.emit('LABEL', body_start_label) self.implicit_continues.append(continue_label) self.implicit_breaks.append(break_label) self.emit('LOAD_UNDEFINED') self.emit(body) self.implicit_continues.pop() self.implicit_breaks.pop() self.emit('NOP') self.emit('LABEL', break_label) self.emit('NOP')
def UpdateExpression(self, operator, argument, prefix, **kwargs): incr = int(operator == "++") post = int(not prefix) if argument['type'] == 'MemberExpression': if argument['computed']: self.emit(argument['object']) self.emit(argument['property']) self.emit('POSTFIX_MEMBER', post, incr) else: self.emit(argument['object']) name = to_key(argument['property']) self.emit('POSTFIX_MEMBER_DOT', post, incr, name) elif argument['type'] == 'Identifier': name = to_key(argument) self.emit('POSTFIX', post, incr, name) else: raise MakeError('SyntaxError', 'Invalid left-hand side in assignment')
def UnaryExpression(self, operator, argument, **kwargs): if operator == 'typeof' and argument['type']=='Identifier': # todo fix typeof self.emit('TYPEOF', argument['name']) elif operator == 'delete': if argument['type'] == 'MemberExpression': self.emit(argument['object']) if argument['property']['type'] == 'Identifier': self.emit('LOAD_STRING', unicode(argument['property']['name'])) else: self.emit(argument['property']) self.emit('DELETE_MEMBER') elif argument['type'] == 'Identifier': self.emit('DELETE', argument['name']) else: self.emit('LOAD_BOOLEAN', 1) elif operator in UNARY_OPERATIONS: self.emit(argument) self.emit('UNARY_OP', operator) else: raise MakeError('SyntaxError', 'Unknown unary operator %s' % operator)
import pyjsparser from space import Space import fill_space from byte_trans import ByteCodeGenerator from code import Code from simplex import MakeError import sys sys.setrecursionlimit(100000) pyjsparser.parser.ENABLE_JS2PY_ERRORS = lambda msg: MakeError(u'SyntaxError', unicode(msg)) def eval_js_vm(js): a = ByteCodeGenerator(Code()) s = Space() a.exe.space = s s.exe = a.exe d = pyjsparser.parse(js) a.emit(d) fill_space.fill_space(s, a) # print a.exe.tape a.exe.compile() return a.exe.run(a.exe.space.GlobalObj)