[jsinterp] Refactoring getvalue and putvalue
Previously deokenization and value lookup was handled tandem Moved methods from JSInterpreter into Reference
This commit is contained in:
parent
9d1f75667c
commit
f942bb3fa6
@ -22,12 +22,23 @@ class Context(object):
|
|||||||
|
|
||||||
class Reference(object):
|
class Reference(object):
|
||||||
def __init__(self, value, parent=None):
|
def __init__(self, value, parent=None):
|
||||||
self.value = value
|
self._value = value
|
||||||
self.parent = parent
|
self._parent = parent
|
||||||
|
|
||||||
|
def getvalue(self):
|
||||||
|
return self._value
|
||||||
|
|
||||||
|
def putvalue(self, value):
|
||||||
|
if self._parent is None:
|
||||||
|
raise ExtractorError('Trying to set a read-only reference')
|
||||||
|
parent, key = self._parent
|
||||||
|
if not hasattr(parent, '__setitem__'):
|
||||||
|
raise ExtractorError('Unknown reference')
|
||||||
|
parent.__setitem__(key, Reference(value, (parent, key)))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
parent, key = self.parent
|
parent, key = self._parent
|
||||||
return '<Reference> value: %s, parent: %s -> %s)' % (self.value, parent.__class__.__name__, key)
|
return '<Reference> value: %s, parent: %s -> %s)' % (self._value, parent.__class__.__name__, key)
|
||||||
|
|
||||||
|
|
||||||
class JSInterpreter(object):
|
class JSInterpreter(object):
|
||||||
@ -467,42 +478,6 @@ class JSInterpreter(object):
|
|||||||
|
|
||||||
return (Token.OPEXPR, out)
|
return (Token.OPEXPR, out)
|
||||||
|
|
||||||
def getvalue(self, ref):
|
|
||||||
if (ref.value is None or ref.value is self.undefined or
|
|
||||||
isinstance(ref.value, (int, float, compat_str, list))):
|
|
||||||
return ref.value
|
|
||||||
ref_id, ref_value = ref.value
|
|
||||||
if ref_id is Token.ID:
|
|
||||||
if ref_value in self.context.local_vars:
|
|
||||||
return self.context.local_vars[ref_value].value
|
|
||||||
# TODO error handling (unknown id)
|
|
||||||
return self.global_vars[ref_value].value
|
|
||||||
elif ref_id in _token_keys:
|
|
||||||
return ref_value
|
|
||||||
elif ref_id is Token.EXPR:
|
|
||||||
ref = self.interpret_statement(ref_value)
|
|
||||||
return self.getvalue(ref)
|
|
||||||
elif ref_id is Token.ARRAY:
|
|
||||||
array = []
|
|
||||||
for key, expr in enumerate(ref_value):
|
|
||||||
value = self.interpret_expression(expr)
|
|
||||||
value.parent = array, key
|
|
||||||
array.append(value)
|
|
||||||
return array
|
|
||||||
else:
|
|
||||||
raise ExtractorError('Unable to get value of reference type %s' % ref_id)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def putvalue(ref, value):
|
|
||||||
if ref.parent is None:
|
|
||||||
raise ExtractorError('Trying to set a read-only reference')
|
|
||||||
|
|
||||||
parent, key = ref.parent
|
|
||||||
if not hasattr(parent, '__setitem__'):
|
|
||||||
raise ExtractorError('Unknown reference')
|
|
||||||
|
|
||||||
parent.__setitem__(key, Reference(value, (parent, key)))
|
|
||||||
|
|
||||||
def interpret_statement(self, stmt):
|
def interpret_statement(self, stmt):
|
||||||
if stmt is None:
|
if stmt is None:
|
||||||
return None
|
return None
|
||||||
@ -517,10 +492,10 @@ class JSInterpreter(object):
|
|||||||
for stmt in block:
|
for stmt in block:
|
||||||
s = self.interpret_statement(stmt)
|
s = self.interpret_statement(stmt)
|
||||||
if s is not None:
|
if s is not None:
|
||||||
ref = self.getvalue(s)
|
ref = s.getvalue()
|
||||||
elif name is Token.VAR:
|
elif name is Token.VAR:
|
||||||
for name, value in stmt[1]:
|
for name, value in stmt[1]:
|
||||||
self.context.local_vars[name] = Reference(self.getvalue(self.interpret_expression(value)),
|
self.context.local_vars[name] = Reference(self.interpret_expression(value).getvalue(),
|
||||||
(self.context.local_vars, name))
|
(self.context.local_vars, name))
|
||||||
elif name is Token.EXPR:
|
elif name is Token.EXPR:
|
||||||
for expr in stmt[1]:
|
for expr in stmt[1]:
|
||||||
@ -529,10 +504,10 @@ class JSInterpreter(object):
|
|||||||
# continue, break
|
# continue, break
|
||||||
elif name is Token.RETURN:
|
elif name is Token.RETURN:
|
||||||
ref = self.interpret_statement(stmt[1])
|
ref = self.interpret_statement(stmt[1])
|
||||||
ref = None if ref is None else self.getvalue(ref)
|
ref = None if ref is None else ref.getvalue()
|
||||||
if isinstance(ref, list):
|
if isinstance(ref, list):
|
||||||
# TODO test nested arrays
|
# TODO test nested arrays
|
||||||
ref = [self.getvalue(elem) for elem in ref]
|
ref = [elem.getvalue() for elem in ref]
|
||||||
|
|
||||||
self.context.ended = True
|
self.context.ended = True
|
||||||
# with
|
# with
|
||||||
@ -557,9 +532,9 @@ class JSInterpreter(object):
|
|||||||
else:
|
else:
|
||||||
# TODO handle undeclared variables (create propery)
|
# TODO handle undeclared variables (create propery)
|
||||||
leftref = self.interpret_expression(left)
|
leftref = self.interpret_expression(left)
|
||||||
leftvalue = self.getvalue(leftref)
|
leftvalue = leftref.getvalue()
|
||||||
rightvalue = self.getvalue(self.interpret_expression(right))
|
rightvalue = self.interpret_expression(right).getvalue()
|
||||||
self.putvalue(leftref, op(leftvalue, rightvalue))
|
leftref.putvalue(op(leftvalue, rightvalue))
|
||||||
# TODO check specs
|
# TODO check specs
|
||||||
ref = leftref
|
ref = leftref
|
||||||
|
|
||||||
@ -574,10 +549,10 @@ class JSInterpreter(object):
|
|||||||
if token[0] in (Token.OP, Token.AOP, Token.UOP, Token.LOP, Token.REL):
|
if token[0] in (Token.OP, Token.AOP, Token.UOP, Token.LOP, Token.REL):
|
||||||
right = stack.pop()
|
right = stack.pop()
|
||||||
left = stack.pop()
|
left = stack.pop()
|
||||||
stack.append(Reference(token[1](self.getvalue(left), self.getvalue(right))))
|
stack.append(Reference(token[1](left.getvalue(), right.getvalue())))
|
||||||
elif token[0] is Token.UOP:
|
elif token[0] is Token.UOP:
|
||||||
right = stack.pop()
|
right = stack.pop()
|
||||||
stack.append(token[1](self.getvalue(right)))
|
stack.append(token[1](right.getvalue()))
|
||||||
else:
|
else:
|
||||||
stack.append(self.interpret_expression(token))
|
stack.append(self.interpret_expression(token))
|
||||||
result = stack.pop()
|
result = stack.pop()
|
||||||
@ -596,10 +571,8 @@ class JSInterpreter(object):
|
|||||||
# TODO interpret field
|
# TODO interpret field
|
||||||
raise ExtractorError('''Can't interpret expression called %s''' % tail_name)
|
raise ExtractorError('''Can't interpret expression called %s''' % tail_name)
|
||||||
elif tail_name is Token.ELEM:
|
elif tail_name is Token.ELEM:
|
||||||
index = self.interpret_statement(tail_value)
|
index = self.interpret_statement(tail_value).getvalue()
|
||||||
index = self.getvalue(index)
|
target = target.getvalue()[index]
|
||||||
target = self.getvalue(target)
|
|
||||||
target = target[index]
|
|
||||||
elif tail_name is Token.CALL:
|
elif tail_name is Token.CALL:
|
||||||
# TODO interpret call
|
# TODO interpret call
|
||||||
raise ExtractorError('''Can't interpret expression called %s''' % tail_name)
|
raise ExtractorError('''Can't interpret expression called %s''' % tail_name)
|
||||||
@ -608,10 +581,19 @@ class JSInterpreter(object):
|
|||||||
elif name is Token.ID:
|
elif name is Token.ID:
|
||||||
# TODO error handling (unknown id)
|
# TODO error handling (unknown id)
|
||||||
ref = self.context.local_vars[expr[1]] if expr[1] in self.context.local_vars else self.global_vars[expr[1]]
|
ref = self.context.local_vars[expr[1]] if expr[1] in self.context.local_vars else self.global_vars[expr[1]]
|
||||||
|
|
||||||
# literal
|
# literal
|
||||||
elif name in _token_keys or name is Token.ARRAY:
|
elif name in _token_keys:
|
||||||
ref = Reference(self.getvalue(Reference(expr)))
|
ref = Reference(expr[1])
|
||||||
|
|
||||||
|
elif name is Token.ARRAY:
|
||||||
|
array = []
|
||||||
|
for key, elem in enumerate(expr[1]):
|
||||||
|
value = self.interpret_expression(elem)
|
||||||
|
value._parent = array, key
|
||||||
|
array.append(value)
|
||||||
|
ref = Reference(array)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ExtractorError('''Can't interpret expression called %s''' % name)
|
raise ExtractorError('''Can't interpret expression called %s''' % name)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user