1
0
mirror of synced 2024-11-24 06:20:12 +01:00

Convert expression rendering to an explicit function so we can retain __repr__ for debugging.

This commit is contained in:
Jennifer Taylor 2021-04-24 18:07:01 +00:00
parent f2761b90b0
commit b0778e1110
2 changed files with 62 additions and 22 deletions

View File

@ -95,14 +95,14 @@ class Statement(ConvertedAction):
def object_ref(obj: Any) -> str:
if isinstance(obj, (GenericObject, Variable, Member)):
return repr(obj)
return obj.render(nested=True)
else:
raise Exception(f"Unsupported objectref {obj} ({type(obj)})")
def value_ref(param: Any) -> str:
if isinstance(param, (Expression)):
return repr(param)
def value_ref(param: Any, parens: bool = False) -> str:
if isinstance(param, Expression):
return param.render(nested=parens)
elif isinstance(param, (str, int, float)):
return repr(param)
else:
@ -113,7 +113,7 @@ def name_ref(param: Any) -> str:
if isinstance(param, str):
return param
elif isinstance(param, StringConstant):
return repr(param)
return param.render()
else:
raise Exception(f"Unsupported nameref {param} ({type(param)})")
@ -161,7 +161,7 @@ class ExpressionStatement(Statement):
self.expr = expr
def __repr__(self) -> str:
return f"{self.expr}"
return f"{self.expr.render()}"
class StopMovieStatement(Statement):
@ -183,6 +183,9 @@ class FunctionCall(Expression):
self.params = params
def __repr__(self) -> str:
return self.render()
def render(self, nested: bool = False) -> str:
name = name_ref(self.name)
params = [value_ref(param) for param in self.params]
return f"{name}({', '.join(params)})"
@ -196,6 +199,9 @@ class MethodCall(Expression):
self.params = params
def __repr__(self) -> str:
return self.render()
def render(self, nested: bool = False) -> str:
obj = object_ref(self.objectref)
name = name_ref(self.name)
params = [value_ref(param) for param in self.params]
@ -210,7 +216,14 @@ class NewFunction(Expression):
self.body = body
def __repr__(self) -> str:
return f"new function({repr(self.funcname) or '<anonymous function>'}, {hex(self.flags)}, 'TODO: ByteCode')"
return self.render()
def render(self, nested: bool = False) -> str:
val = f"new function({repr(self.funcname) or '<anonymous function>'}, {hex(self.flags)}, 'TODO: ByteCode')"
if nested:
return f"({val})"
else:
return val
class NewObject(Expression):
@ -220,9 +233,16 @@ class NewObject(Expression):
self.params = params
def __repr__(self) -> str:
return self.render()
def render(self, nested: bool = False) -> str:
objname = name_ref(self.objname)
params = [value_ref(param) for param in self.params]
return f"new {objname}({', '.join(params)})"
val = f"new {objname}({', '.join(params)})"
if nested:
return f"({val})"
else:
return val
class SetMemberStatement(Statement):
@ -298,7 +318,7 @@ class IsUndefinedIf(IfExpr):
self.negate = negate
def __repr__(self) -> str:
val = value_ref(self.conditional)
val = value_ref(self.conditional, parens=True)
if self.negate:
return f"if ({val} is not UNDEFINED)"
else:
@ -314,7 +334,7 @@ class IsBooleanIf(IfExpr):
self.negate = negate
def __repr__(self) -> str:
val = value_ref(self.conditional)
val = value_ref(self.conditional, parens=True)
if self.negate:
return f"if ({val} is False)"
else:
@ -331,8 +351,8 @@ class IsEqualIf(IfExpr):
self.negate = negate
def __repr__(self) -> str:
val1 = value_ref(self.conditional1)
val2 = value_ref(self.conditional2)
val1 = value_ref(self.conditional1, parens=True)
val2 = value_ref(self.conditional2, parens=True)
return f"if ({val1} {'!=' if self.negate else '=='} {val2})"
@ -346,8 +366,8 @@ class IsStrictEqualIf(IfExpr):
self.negate = negate
def __repr__(self) -> str:
val1 = value_ref(self.conditional1)
val2 = value_ref(self.conditional2)
val1 = value_ref(self.conditional1, parens=True)
val2 = value_ref(self.conditional2, parens=True)
return f"if ({val1} {'!==' if self.negate else '==='} {val2})"
@ -361,8 +381,8 @@ class MagnitudeIf(IfExpr):
self.negate = negate
def __repr__(self) -> str:
val1 = value_ref(self.conditional1)
val2 = value_ref(self.conditional2)
val1 = value_ref(self.conditional1, parens=True)
val2 = value_ref(self.conditional2, parens=True)
return f"if ({val1} {'<' if self.negate else '>'} {val2})"
@ -376,8 +396,8 @@ class MagnitudeEqualIf(IfExpr):
self.negate = negate
def __repr__(self) -> str:
val1 = value_ref(self.conditional1)
val2 = value_ref(self.conditional2)
val1 = value_ref(self.conditional1, parens=True)
val2 = value_ref(self.conditional2, parens=True)
return f"if ({val1} {'<=' if self.negate else '>='} {val2})"
@ -553,6 +573,9 @@ class Variable(Expression):
self.name = name
def __repr__(self) -> str:
return f"Variable({name_ref(self.name)})"
def render(self, nested: bool = False) -> str:
return name_ref(self.name)
@ -562,6 +585,9 @@ class Member(Expression):
self.member = member
def __repr__(self) -> str:
return self.render()
def render(self, nested: bool = False) -> str:
member = name_ref(self.member)
ref = object_ref(self.objectref)
return f"{ref}.{member}"

View File

@ -615,17 +615,22 @@ class DefineFunction2Action(AP2Action):
class Expression:
# This is just a type class for all things that can be expressions.
pass
# Any thing that can be evaluated for a result, such as a variable
# reference, function call, or mathematical operation.
def render(self, nested: bool = False) -> str:
raise NotImplementedError()
# A bunch of stuff for implementing PushAction
class GenericObject(Expression):
def __init__(self, name: str) -> None:
self.__name = name
self.name = name
def __repr__(self) -> str:
return self.__name
return self.name
def render(self, nested: bool = False) -> str:
return self.name
NULL = GenericObject('NULL')
@ -642,6 +647,9 @@ class Register(Expression):
self.no = no
def __repr__(self) -> str:
return f"Register({self.no})"
def render(self, nested: bool = False) -> str:
return f"registers[{self.no}]"
@ -2586,6 +2594,12 @@ class StringConstant(Expression):
self.alias = alias
def __repr__(self) -> str:
if self.alias:
return f"StringConstant({hex(self.const)}: {self.alias})"
else:
return f"StringConstant({hex(self.const)}: {StringConstant.property_to_name(self.const)})"
def render(self, nested: bool = False) -> str:
if self.alias:
return self.alias
else: