mirror of https://github.com/pmret/papermario.git
add do..while psuedoinstruction
This commit is contained in:
parent
652c52d3dd
commit
d29496e6e0
|
@ -90,12 +90,10 @@ Script M(GoombaIdle) = SCRIPT({
|
||||||
SetSelfEnemyFlagBits(0x00000020, TRUE)
|
SetSelfEnemyFlagBits(0x00000020, TRUE)
|
||||||
|
|
||||||
// Wait until read_sign sets NPC var 0
|
// Wait until read_sign sets NPC var 0
|
||||||
lbl:
|
do {
|
||||||
GetSelfVar(0, SI_VAR(0))
|
GetSelfVar(0, SI_VAR(0))
|
||||||
sleep 1
|
sleep 1
|
||||||
if SI_VAR(0) == FALSE {
|
} while SI_VAR(0) == FALSE
|
||||||
goto lbl
|
|
||||||
}
|
|
||||||
|
|
||||||
// Peel and jump off the sign
|
// Peel and jump off the sign
|
||||||
SetNpcFlagBits(NpcId_SELF, 0x00240000, TRUE)
|
SetNpcFlagBits(NpcId_SELF, 0x00240000, TRUE)
|
||||||
|
|
|
@ -29,6 +29,7 @@ script_parser = Lark(r"""
|
||||||
| label ":" -> label_decl
|
| label ":" -> label_decl
|
||||||
| "goto" label -> label_goto
|
| "goto" label -> label_goto
|
||||||
| if_stmt
|
| if_stmt
|
||||||
|
| do_while_stmt
|
||||||
| "return" -> return_stmt
|
| "return" -> return_stmt
|
||||||
| "break" -> break_stmt
|
| "break" -> break_stmt
|
||||||
| "sleep" expr -> sleep_stmt
|
| "sleep" expr -> sleep_stmt
|
||||||
|
@ -52,6 +53,8 @@ script_parser = Lark(r"""
|
||||||
?if_op: "==" -> if_op_eq
|
?if_op: "==" -> if_op_eq
|
||||||
| "!=" -> if_op_ne
|
| "!=" -> if_op_ne
|
||||||
|
|
||||||
|
do_while_stmt: "do" block "while" expr if_op expr
|
||||||
|
|
||||||
suspend_stmt: "suspend" control_type expr ("," control_type expr)* [","]
|
suspend_stmt: "suspend" control_type expr ("," control_type expr)* [","]
|
||||||
resume_stmt: "resume" control_type expr ("," control_type expr)* [","]
|
resume_stmt: "resume" control_type expr ("," control_type expr)* [","]
|
||||||
kill_stmt: "kill" control_type expr ("," control_type expr)* [","]
|
kill_stmt: "kill" control_type expr ("," control_type expr)* [","]
|
||||||
|
@ -114,7 +117,7 @@ class Cmd():
|
||||||
self.context = []
|
self.context = []
|
||||||
|
|
||||||
def add_context(self, context):
|
def add_context(self, context):
|
||||||
self.context.append(context)
|
self.context.insert(0, context)
|
||||||
|
|
||||||
def to_bytecode(self):
|
def to_bytecode(self):
|
||||||
return [ self.opcode, len(self.args), *self.args ]
|
return [ self.opcode, len(self.args), *self.args ]
|
||||||
|
@ -128,22 +131,32 @@ class BreakCmd(Cmd):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def opcode(self):
|
def opcode(self):
|
||||||
# are we in a switch or a loop?
|
for ctx in self.context:
|
||||||
context = None
|
if "break_opcode" in ctx:
|
||||||
for c in self.context:
|
return ctx.break_opcode(self.meta)
|
||||||
if c in ("switch", "loop"):
|
return 0x01 # break out of whole script (end; no return)
|
||||||
context = c
|
|
||||||
|
|
||||||
if not context:
|
|
||||||
return 0x01 # END
|
|
||||||
elif context == "loop":
|
|
||||||
return 0x07 # SI_BREAK_LOOP
|
|
||||||
elif context == "switch":
|
|
||||||
return 0x22 # BREAK_CASE
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "BreakCmd"
|
return "BreakCmd"
|
||||||
|
|
||||||
|
class CmdCtx():
|
||||||
|
pass
|
||||||
|
|
||||||
|
class IfCtx(CmdCtx):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class SwitchCtx(CmdCtx):
|
||||||
|
def break_opcode(self, meta):
|
||||||
|
return Cmd(0x22)
|
||||||
|
|
||||||
|
class LoopCtx(CmdCtx):
|
||||||
|
def break_opcode(self, meta):
|
||||||
|
return Cmd(0x07)
|
||||||
|
|
||||||
|
class DoWhileCtx(CmdCtx):
|
||||||
|
def break_opcode(self, meta):
|
||||||
|
raise CompileError("breaking out of a do..while loop is not supported (hint: use a label)", meta)
|
||||||
|
|
||||||
class CompileError(Exception):
|
class CompileError(Exception):
|
||||||
def __init__(self, message, meta):
|
def __init__(self, message, meta):
|
||||||
super().__init__(message)
|
super().__init__(message)
|
||||||
|
@ -168,6 +181,10 @@ class LabelAllocation(Visitor):
|
||||||
raise CompileError(f"label `{name}' already declared", tree.meta)
|
raise CompileError(f"label `{name}' already declared", tree.meta)
|
||||||
self.labels.append(name)
|
self.labels.append(name)
|
||||||
|
|
||||||
|
def gen_label(self):
|
||||||
|
self.labels.append("$generated")
|
||||||
|
return len(self.labels) - 1
|
||||||
|
|
||||||
@v_args(tree=True)
|
@v_args(tree=True)
|
||||||
class Compile(Transformer):
|
class Compile(Transformer):
|
||||||
SIGNED_INT = str
|
SIGNED_INT = str
|
||||||
|
@ -210,7 +227,7 @@ class Compile(Transformer):
|
||||||
a, op, b, block = tree.children
|
a, op, b, block = tree.children
|
||||||
for cmd in block:
|
for cmd in block:
|
||||||
if type(cmd) == Cmd:
|
if type(cmd) == Cmd:
|
||||||
cmd.add_context("if")
|
cmd.add_context(IfCtx())
|
||||||
return [ Cmd(op, a, b, meta=tree.meta), *block, Cmd(0x13) ]
|
return [ Cmd(op, a, b, meta=tree.meta), *block, Cmd(0x13) ]
|
||||||
def if_op_eq(self, tree): return 0x0A
|
def if_op_eq(self, tree): return 0x0A
|
||||||
def if_op_ne(self, tree): return 0x0B
|
def if_op_ne(self, tree): return 0x0B
|
||||||
|
@ -221,16 +238,36 @@ class Compile(Transformer):
|
||||||
|
|
||||||
for cmd in block:
|
for cmd in block:
|
||||||
if type(cmd) == Cmd:
|
if type(cmd) == Cmd:
|
||||||
cmd.add_context("loop")
|
cmd.add_context(LoopCtx())
|
||||||
|
|
||||||
return [ Cmd(0x05, expr, meta=tree.meta), *block, Cmd(0x06) ]
|
return [ Cmd(0x05, expr, meta=tree.meta), *block, Cmd(0x06) ]
|
||||||
|
|
||||||
def return_stmt(self, tree): return Cmd(0x02, meta=tree.meta)
|
# do..while pseudoinstruction
|
||||||
|
def do_while_stmt(self, tree):
|
||||||
|
block, a, op, b = tree.children
|
||||||
|
|
||||||
|
for cmd in block:
|
||||||
|
if type(cmd) == Cmd:
|
||||||
|
cmd.add_context(DoWhileCtx())
|
||||||
|
|
||||||
|
label = self.alloc.gen_label()
|
||||||
|
|
||||||
|
return [
|
||||||
|
Cmd(0x03, label, meta=tree.meta), # label:
|
||||||
|
*block,
|
||||||
|
Cmd(op, a, b, meta=tree.meta), # if a op b
|
||||||
|
Cmd(0x04, label, meta=tree.meta), # goto label
|
||||||
|
Cmd(0x13, meta=tree.meta), # end if
|
||||||
|
]
|
||||||
|
|
||||||
|
def return_stmt(self, tree):
|
||||||
|
return Cmd(0x02, meta=tree.meta)
|
||||||
|
|
||||||
def break_stmt(self, tree):
|
def break_stmt(self, tree):
|
||||||
return BreakCmd(meta=tree.meta)
|
return BreakCmd(meta=tree.meta)
|
||||||
|
|
||||||
def set_group(self, tree): return Cmd(0x4D, tree.children[0], meta=tree.meta)
|
def set_group(self, tree):
|
||||||
|
return Cmd(0x4D, tree.children[0], meta=tree.meta)
|
||||||
|
|
||||||
def suspend_stmt(self, tree):
|
def suspend_stmt(self, tree):
|
||||||
commands = []
|
commands = []
|
||||||
|
@ -355,17 +392,6 @@ class Compile(Transformer):
|
||||||
return self.alloc.labels.index(name)
|
return self.alloc.labels.index(name)
|
||||||
raise CompileError(f"label `{name}' is undeclared", tree.meta)
|
raise CompileError(f"label `{name}' is undeclared", tree.meta)
|
||||||
|
|
||||||
#define SI_SET_CONST(var, value) SI_CMD(0x25, var, value) // Does not get_variable
|
|
||||||
#define SI_SUB(a, b) SI_CMD(0x28, a, b) // -=
|
|
||||||
#define SI_MUL(a, b) SI_CMD(0x29, a, b) // *=
|
|
||||||
#define SI_DIV(a, b) SI_CMD(0x2A, a, b) // /=
|
|
||||||
#define SI_MOD(a, b) SI_CMD(0x2B, a, b) // %=
|
|
||||||
|
|
||||||
#define SI_SET_F(var, value) SI_CMD(0x26, var, value)
|
|
||||||
#define SI_SUB_F(a, b) SI_CMD(0x2D, a, b) // -=
|
|
||||||
#define SI_MUL_F(a, b) SI_CMD(0x2E, a, b) // *=
|
|
||||||
#define SI_DIV_F(a, b) SI_CMD(0x2F, a, b) // /=
|
|
||||||
|
|
||||||
def compile_script(s):
|
def compile_script(s):
|
||||||
tree = script_parser.parse(s)
|
tree = script_parser.parse(s)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue