mirror of
https://github.com/pmret/papermario.git
synced 2024-11-09 12:32:38 +01:00
add explicit const/float DSL commands, improve match disassembly
This commit is contained in:
parent
d11595684e
commit
f811ed0b92
@ -49,6 +49,8 @@ script_parser = Lark(r"""
|
||||
| "await" expr -> await_stmt
|
||||
| lhs "=" "spawn" expr -> spawn_set_stmt
|
||||
| lhs set_op expr -> set_stmt
|
||||
| lhs set_op "f" expr -> set_float_stmt
|
||||
| lhs set_op "c" expr -> set_const_stmt
|
||||
| bind_stmt
|
||||
| bind_set_stmt
|
||||
| "unbind" -> unbind_stmt
|
||||
@ -75,6 +77,7 @@ script_parser = Lark(r"""
|
||||
| "?" -> cond_op_flag
|
||||
|
||||
match_stmt: "match" expr "{" NEWLINE* (match_cases STMT_SEP*)? "}"
|
||||
match_const_stmt: "matchc" expr "{" NEWLINE* (match_cases STMT_SEP*)? "}"
|
||||
match_cases: match_case STMT_SEP* match_cases
|
||||
| match_case
|
||||
?match_case: "else" block -> case_else
|
||||
@ -337,6 +340,10 @@ class Compile(Transformer):
|
||||
*cases,
|
||||
Cmd(0x24),
|
||||
]
|
||||
def match_const_stmt(self, tree):
|
||||
commands = self.match_stmt(tree)
|
||||
commands[0].opcode = 0x15
|
||||
return commands
|
||||
def match_cases(self, tree):
|
||||
if len(tree.children) == 1:
|
||||
return [tree.children[0]]
|
||||
@ -471,18 +478,24 @@ class Compile(Transformer):
|
||||
if is_fixed_var(rhs):
|
||||
opcode = opcodes.get("float", None)
|
||||
if not opcode:
|
||||
raise CompileError(f"operation `{opcodes['__op__']}' not supported for floats", tree.meta)
|
||||
raise CompileError(f"float operation `{opcodes['__op__']}' not supported", tree.meta)
|
||||
else:
|
||||
opcode = opcodes.get("int", None)
|
||||
if not opcode:
|
||||
raise CompileError(f"operation `{opcodes['__op__']}' not supported for ints", tree.meta)
|
||||
raise CompileError(f"int operation `{opcodes['__op__']}' not supported", tree.meta)
|
||||
return Cmd(opcode, lhs, rhs)
|
||||
def set_float_stmt(self, tree):
|
||||
lhs, opcodes, rhs = tree.children
|
||||
opcode = opcodes.get("float", None)
|
||||
if not opcode:
|
||||
raise CompileError(f"float operation `{opcodes['__op__']}' not supported", tree.meta)
|
||||
return Cmd(opcode, lhs, rhs)
|
||||
def set_const_stmt(self, tree):
|
||||
lhs, opcodes, rhs = tree.children
|
||||
opcode = opcodes.get("const", None)
|
||||
if not opcode:
|
||||
raise CompileError(f"const operation `{opcodes['__op__']}' not supported", tree.meta)
|
||||
return Cmd(opcode, lhs, rhs)
|
||||
# def set_const_stmt(self, tree):
|
||||
# lhs, opcodes, rhs = tree.children
|
||||
# opcode = opcodes.get("const", None)
|
||||
# if not opcode:
|
||||
# raise CompileError(f"operation `{opcodes['__op__']}' not supported for consts", tree.meta)
|
||||
# return Cmd(opcode, lhs, rhs)
|
||||
def set_op_eq(self, tree):
|
||||
return {
|
||||
"__op__": "=",
|
||||
|
@ -332,10 +332,10 @@ class ScriptDSLDisassembler(ScriptDisassembler):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# False: not in case
|
||||
# True: in case block
|
||||
# CASES: in condition, but { not written yet
|
||||
# MULTI: in ',' condition(s), but { not written yet
|
||||
# True: case block
|
||||
# CASE: single condition
|
||||
# MULTI: multi-condition(s)
|
||||
# MATCH: match block
|
||||
self.case_stack = []
|
||||
|
||||
self.was_multi_case = False
|
||||
@ -369,36 +369,40 @@ class ScriptDSLDisassembler(ScriptDisassembler):
|
||||
else:
|
||||
return f"{arg}"
|
||||
|
||||
def verify_float(self, var):
|
||||
def is_float(self, var):
|
||||
try:
|
||||
float(var)
|
||||
return True
|
||||
except Exception:
|
||||
# not a float!
|
||||
raise UnsupportedScript("non-float used in float command")
|
||||
|
||||
return var
|
||||
return False
|
||||
|
||||
def disassemble_command(self, opcode, argc, argv):
|
||||
# write case block braces
|
||||
if self.in_case == "CASES" or self.in_case == "MULTI":
|
||||
if self.in_case == "CASE" or self.in_case == "MULTI":
|
||||
if opcode == 0x1D: # multi case
|
||||
pass
|
||||
elif 0x16 <= opcode <= 0x21: # standard case conditions
|
||||
# open and close empty case
|
||||
self.out += " {}\n"
|
||||
|
||||
self.case_stack.pop()
|
||||
self.case_stack.append(False)
|
||||
assert self.in_case == "MATCH"
|
||||
|
||||
self.was_multi_case = False
|
||||
else:
|
||||
# open case
|
||||
self.out += " {\n"
|
||||
self.was_multi_case = self.in_case == "MULTI"
|
||||
|
||||
self.case_stack.pop()
|
||||
self.case_stack.append(True)
|
||||
elif self.in_case is True and 0x16 <= opcode <= 0x21: # new case
|
||||
self.case_stack.pop()
|
||||
|
||||
self.indent += 1
|
||||
elif self.in_case != "MATCH" and 0x16 <= opcode <= 0x21: # new case, not including the first
|
||||
assert self.case_stack.pop() == True
|
||||
self.was_multi_case = self.case_stack.pop() == "MULTI"
|
||||
assert self.in_case == "MATCH"
|
||||
|
||||
self.indent -= 1
|
||||
self.write_line("}")
|
||||
self.indent += 1
|
||||
|
||||
if opcode == 0x01:
|
||||
if self.out.endswith("return\n"):
|
||||
@ -458,91 +462,109 @@ class ScriptDSLDisassembler(ScriptDisassembler):
|
||||
self.write_line("}")
|
||||
elif opcode == 0x14:
|
||||
self.write_line(f"match {self.var(argv[0])} {{")
|
||||
self.indent += 2
|
||||
self.case_stack.append(False)
|
||||
# elif opcode == 0x15:
|
||||
# self.write_line(f"SI_SWITCH_CONST(0x{argv[0]:X}),")
|
||||
# self.indent += 2
|
||||
self.indent += 1
|
||||
self.case_stack.append("MATCH")
|
||||
elif opcode == 0x15:
|
||||
self.write_line(f"matchc {self.var(argv[0])} {{")
|
||||
self.indent += 1
|
||||
self.case_stack.append("MATCH")
|
||||
elif opcode == 0x16:
|
||||
self.indent -= 1
|
||||
self.case_stack.append("CASES")
|
||||
self.case_stack.append("CASE")
|
||||
self.write(f"== {self.var(argv[0])}")
|
||||
self.indent += 1
|
||||
elif opcode == 0x17:
|
||||
self.indent -= 1
|
||||
self.case_stack.append("CASES")
|
||||
self.case_stack.append("CASE")
|
||||
self.write(f"!= {self.var(argv[0])}")
|
||||
self.indent += 1
|
||||
elif opcode == 0x18:
|
||||
self.indent -= 1
|
||||
self.case_stack.append("CASES")
|
||||
self.case_stack.append("CASE")
|
||||
self.write(f"< {self.var(argv[0])}")
|
||||
self.indent += 1
|
||||
elif opcode == 0x19:
|
||||
self.indent -= 1
|
||||
self.case_stack.append("CASES")
|
||||
self.case_stack.append("CASE")
|
||||
self.write(f"> {self.var(argv[0])}")
|
||||
self.indent += 1
|
||||
elif opcode == 0x1A:
|
||||
self.indent -= 1
|
||||
self.case_stack.append("CASES")
|
||||
self.case_stack.append("CASE")
|
||||
self.write(f"<= {self.var(argv[0])}")
|
||||
self.indent += 1
|
||||
elif opcode == 0x1B:
|
||||
self.indent -= 1
|
||||
self.case_stack.append("CASES")
|
||||
self.case_stack.append("CASE")
|
||||
self.write(f">= {self.var(argv[0])}")
|
||||
self.indent += 1
|
||||
elif opcode == 0x1C:
|
||||
self.indent -= 1
|
||||
self.case_stack.append("CASES")
|
||||
self.case_stack.append("CASE")
|
||||
self.write(f"else")
|
||||
self.indent += 1
|
||||
elif opcode == 0x1D:
|
||||
self.indent -= 1
|
||||
if self.in_case == "CASES" or self.in_case == "MULTI":
|
||||
if self.in_case == "CASE" or self.in_case == "MULTI":
|
||||
self.out += f", {self.var(argv[0])}"
|
||||
|
||||
# replace(!) CASE with MULTI
|
||||
self.case_stack.pop()
|
||||
self.case_stack.append("MULTI")
|
||||
else:
|
||||
self.write(f"{self.var(argv[0])}")
|
||||
self.case_stack.append("MULTI")
|
||||
self.indent += 1
|
||||
self.case_stack.append("MULTI")
|
||||
# opcode 0x1E?
|
||||
elif opcode == 0x1F:
|
||||
self.indent -= 1
|
||||
self.case_stack.append("CASE")
|
||||
self.write_line(f"? {self.var(argv[0])}")
|
||||
self.indent += 1
|
||||
elif opcode == 0x20 and self.was_multi_case:
|
||||
self.indent -= 1
|
||||
self.indent += 1
|
||||
elif opcode == 0x20:
|
||||
if not self.was_multi_case:
|
||||
raise UnsupportedScript("unexpected SI_END_MULTI_CASE")
|
||||
elif opcode == 0x21:
|
||||
self.indent -= 1
|
||||
self.write_line(f"{self.var(argv[0])}..{self.var(argv[1])} {{")
|
||||
self.write_line(f"{self.var(argv[0])}..{self.var(argv[1])}")
|
||||
self.indent += 1
|
||||
elif opcode == 0x22: self.write_line("break")
|
||||
elif opcode == 0x23:
|
||||
self.indent -= 1
|
||||
if self.in_case:
|
||||
# close open case if needed
|
||||
if self.in_case != "MATCH":
|
||||
self.case_stack.pop() == True
|
||||
self.case_stack.pop() in ["MULTI", "CASE"]
|
||||
|
||||
self.indent -= 1
|
||||
self.write_line("}")
|
||||
self.case_stack.pop()
|
||||
self.case_stack.pop()
|
||||
|
||||
assert self.case_stack.pop() == "MATCH"
|
||||
|
||||
self.indent -= 1
|
||||
self.write_line("}")
|
||||
elif opcode == 0x24: self.write_line(f"{self.var(argv[0])} = {self.var(argv[1])}")
|
||||
#elif opcode == 0x25: self.write_line(f"{self.var(argv[0])} #= 0x{argv[1]:X}")
|
||||
elif opcode == 0x26: self.write_line(f"{self.var(argv[0])} = {self.verify_float(self.var(argv[1]))}")
|
||||
elif opcode == 0x25: self.write_line(f"{self.var(argv[0])} =c 0x{argv[1]:X}")
|
||||
elif opcode == 0x26:
|
||||
lhs = self.var(argv[1])
|
||||
if self.is_float(lhs):
|
||||
self.write_line(f"{self.var(argv[0])} = {lhs}")
|
||||
else:
|
||||
self.write_line(f"{self.var(argv[0])} =f {lhs}")
|
||||
elif opcode == 0x27: self.write_line(f"{self.var(argv[0])} += {self.var(argv[1])}")
|
||||
elif opcode == 0x28: self.write_line(f"{self.var(argv[0])} -= {self.var(argv[1])}")
|
||||
elif opcode == 0x29: self.write_line(f"{self.var(argv[0])} *= {self.var(argv[1])}")
|
||||
elif opcode == 0x2A: self.write_line(f"{self.var(argv[0])} /= {self.var(argv[1])}")
|
||||
elif opcode == 0x2B: self.write_line(f"{self.var(argv[0])} %= {self.var(argv[1])}")
|
||||
elif opcode == 0x2C: self.write_line(f"{self.var(argv[0])} += {self.verify_float(self.var(argv[1]))}")
|
||||
elif opcode == 0x2D: self.write_line(f"{self.var(argv[0])} -= {self.verify_float(self.var(argv[1]))}")
|
||||
elif opcode == 0x2E: self.write_line(f"{self.var(argv[0])} *= {self.verify_float(self.var(argv[1]))}")
|
||||
elif opcode == 0x2F: self.write_line(f"{self.var(argv[0])} /= {self.verify_float(self.var(argv[1]))}")
|
||||
elif opcode == 0x2C:
|
||||
lhs = self.var(argv[1])
|
||||
if self.is_float(lhs):
|
||||
self.write_line(f"{self.var(argv[0])} += {lhs}")
|
||||
else:
|
||||
self.write_line(f"{self.var(argv[0])} +=f {lhs}")
|
||||
elif opcode == 0x2D:
|
||||
lhs = self.var(argv[1])
|
||||
if self.is_float(lhs):
|
||||
self.write_line(f"{self.var(argv[0])} -= {lhs}")
|
||||
else:
|
||||
self.write_line(f"{self.var(argv[0])} -=f {lhs}")
|
||||
elif opcode == 0x2E:
|
||||
lhs = self.var(argv[1])
|
||||
if self.is_float(lhs):
|
||||
self.write_line(f"{self.var(argv[0])} *= {lhs}")
|
||||
else:
|
||||
self.write_line(f"{self.var(argv[0])} *=f {lhs}")
|
||||
elif opcode == 0x2F:
|
||||
lhs = self.var(argv[1])
|
||||
if self.is_float(lhs):
|
||||
self.write_line(f"{self.var(argv[0])} /= {lhs}")
|
||||
else:
|
||||
self.write_line(f"{self.var(argv[0])} /=f {lhs}")
|
||||
elif opcode == 0x3F: self.write_line(f"{self.var(argv[0])} &= {self.var(argv[1])}")
|
||||
elif opcode == 0x40: self.write_line(f"{self.var(argv[0])} |= {self.var(argv[1])}")
|
||||
#elif opcode == 0x41: self.write_line(f"{self.var(argv[0])} #&= {argv[1]:X})")
|
||||
#elif opcode == 0x42: self.write_line(f"{self.var(argv[0])} #|= {argv[1]:X})")
|
||||
elif opcode == 0x41: self.write_line(f"{self.var(argv[0])} &=c {argv[1]:X}")
|
||||
elif opcode == 0x42: self.write_line(f"{self.var(argv[0])} |=c {argv[1]:X}")
|
||||
elif opcode == 0x43:
|
||||
argv_str = ", ".join(self.var(arg) for arg in argv[1:])
|
||||
self.write_line(f"{self.addr_ref(argv[0])}({argv_str})")
|
||||
|
Loading…
Reference in New Issue
Block a user