Browse Source

added goto

rlbr-dev
Larry Xue 5 years ago
parent
commit
db7cc0a716
  1. 25
      c2logic/compiler.py
  2. 11
      c2logic/instructions.py
  3. 16
      examples/goto.c

25
c2logic/compiler.py

@ -10,7 +10,7 @@ from pycparser.c_ast import (
from .consts import builtins, draw_funcs, func_binary_ops, func_unary_ops
from .instructions import (
BinaryOp, Draw, DrawFlush, Enable, End, FunctionCall, GetLink, Instruction, JumpCondition,
BinaryOp, Draw, DrawFlush, Enable, End, FunctionCall, GetLink, Goto, Instruction, JumpCondition,
Print, PrintFlush, Radar, RawAsm, Read, RelativeJump, Return, Sensor, Set, Shoot, UnaryOp, Write
)
@ -24,7 +24,7 @@ class Function():
start: int = dataclasses.field(default=None, init=False)
callees: set = dataclasses.field(init=False, default_factory=set)
callers: set = dataclasses.field(init=False, default_factory=set)
labels: list = dataclasses.field(init=False, default_factory=list)
labels: dict = dataclasses.field(init=False, default_factory=dict)
def __post_init__(self):
self.locals = self.params[:]
@ -65,7 +65,10 @@ class Compiler(c_ast.NodeVisitor):
self.remove_uncalled_funcs()
init_call = FunctionCall("main")
if self.opt_level >= 3:
preamble = [init_call]
if len(self.functions) == 1:
preamble = []
else:
preamble = [init_call]
else:
preamble = [Set("__retaddr_main", "2"), init_call, End()]
@ -85,9 +88,14 @@ class Compiler(c_ast.NodeVisitor):
instruction.func_start = function.start
elif isinstance(instruction, FunctionCall):
instruction.func_start = self.functions[instruction.func_name].start
elif isinstance(instruction, Goto):
instruction.offset = function.labels[instruction.label]
instruction.func_start = function.start
elif isinstance(instruction, Set) and instruction.dest.startswith("__retaddr"):
instruction.src += function.start
out = ["\n".join(map(str, preamble))]
out = []
if preamble:
out.append("\n".join(map(str, preamble)))
out.extend(
"\n".join(map(str, function.instructions)) for function in self.functions.values()
)
@ -96,7 +104,6 @@ class Compiler(c_ast.NodeVisitor):
def remove_uncalled_funcs(self):
to_remove = set()
for name, function in list(self.functions.items()):
print(function)
if name in to_remove:
continue
callers = set()
@ -225,7 +232,6 @@ class Compiler(c_ast.NodeVisitor):
self.curr_function = self.functions[func_name]
else:
func_decl = node.decl.type
print(func_decl)
params = [param_decl.name for param_decl in func_decl.args.params]
self.curr_function = Function(func_name, params)
self.visit(node.body)
@ -377,6 +383,13 @@ class Compiler(c_ast.NodeVisitor):
self.visit(node.expr)
self.push_ret()
def visit_Label(self, node):
self.curr_function.labels[node.name] = self.curr_offset() + 1
self.visit(node.stmt)
def visit_Goto(self, node):
self.push(Goto(node.name))
def visit_FuncCall(self, node):
name = node.name.name
if node.args is not None:

11
c2logic/instructions.py

@ -62,7 +62,7 @@ class RelativeJump(Instruction):
self.cond = cond
def __str__(self):
return f"jump {self.func_start+self.offset} {self.cond}"
return f"jump {self.func_start + self.offset} {self.cond}"
class FunctionCall(Instruction):
def __init__(self, func_name: str):
@ -79,6 +79,15 @@ class Return(Instruction):
def __str__(self):
return f"set @counter __retaddr_{self.func_name}"
class Goto(Instruction):
def __init__(self, label: str):
self.label = label
self.offset: int = None
self.func_start: int = None
def __str__(self):
return f"jump {self.func_start + self.offset} {JumpCondition.always}"
class Print(Instruction):
def __init__(self, val: str):
self.val = val

16
examples/goto.c

@ -0,0 +1,16 @@
#include "c2logic/builtins.h"
extern struct MindustryObject message1;
void main(void) {
goto b;
a:
goto e;
b:
goto d;
c:
goto a;
d:
goto c;
e:
print("end");
printflush(message1);
}
Loading…
Cancel
Save