Wire offline message
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 82 KiB |
@@ -9,6 +9,13 @@ import compiler
|
|||||||
import syntax
|
import syntax
|
||||||
|
|
||||||
|
|
||||||
|
# -------------------------------------------------
|
||||||
|
# Global function environment
|
||||||
|
# -------------------------------------------------
|
||||||
|
|
||||||
|
FUNCTIONS = {} # name -> (func_start, func_end)
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------
|
# -------------------------------------------------
|
||||||
# Expressions — NO CFG NODES
|
# Expressions — NO CFG NODES
|
||||||
# -------------------------------------------------
|
# -------------------------------------------------
|
||||||
@@ -64,13 +71,21 @@ class SEQ(compiler.SEQ):
|
|||||||
|
|
||||||
class IF(compiler.IF):
|
class IF(compiler.IF):
|
||||||
def cfa(self, pred, end):
|
def cfa(self, pred, end):
|
||||||
cond = CFG_DIAMOND(self)
|
# decision node (condition only)
|
||||||
|
cond = CFG_DIAMOND(self.cond)
|
||||||
pred.add_child(cond)
|
pred.add_child(cond)
|
||||||
|
|
||||||
|
# explicit branch entries
|
||||||
|
then_entry = CFG_Node()
|
||||||
|
else_entry = CFG_Node()
|
||||||
|
cond.add_child(then_entry)
|
||||||
|
cond.add_child(else_entry)
|
||||||
|
|
||||||
|
# join node
|
||||||
join = CFG_Node()
|
join = CFG_Node()
|
||||||
|
|
||||||
then_end = self.exp1.cfa(cond, end)
|
then_end = self.exp1.cfa(then_entry, end)
|
||||||
else_end = self.exp2.cfa(cond, end)
|
else_end = self.exp2.cfa(else_entry, end)
|
||||||
|
|
||||||
if then_end is not None:
|
if then_end is not None:
|
||||||
then_end.add_child(join)
|
then_end.add_child(join)
|
||||||
@@ -82,13 +97,19 @@ class IF(compiler.IF):
|
|||||||
|
|
||||||
class WHILE(compiler.WHILE):
|
class WHILE(compiler.WHILE):
|
||||||
def cfa(self, pred, end):
|
def cfa(self, pred, end):
|
||||||
cond = CFG_DIAMOND(self)
|
# loop condition
|
||||||
|
cond = CFG_DIAMOND(self.cond)
|
||||||
pred.add_child(cond)
|
pred.add_child(cond)
|
||||||
|
|
||||||
body_end = self.body.cfa(cond, end)
|
# body entry
|
||||||
if body_end is not None:
|
body_entry = CFG_Node()
|
||||||
body_end.add_child(cond)
|
cond.add_child(body_entry)
|
||||||
|
|
||||||
|
body_end = self.body.cfa(body_entry, end)
|
||||||
|
if body_end is not None:
|
||||||
|
body_end.add_child(cond) # back-edge
|
||||||
|
|
||||||
|
# loop exit
|
||||||
after = CFG_Node()
|
after = CFG_Node()
|
||||||
cond.add_child(after)
|
cond.add_child(after)
|
||||||
|
|
||||||
@@ -96,21 +117,47 @@ class WHILE(compiler.WHILE):
|
|||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------
|
# -------------------------------------------------
|
||||||
# Functions / calls
|
# Functions / calls (interprocedural CFG)
|
||||||
# -------------------------------------------------
|
# -------------------------------------------------
|
||||||
|
|
||||||
class CALL(compiler.CALL):
|
class CALL(compiler.CALL):
|
||||||
def cfa(self, pred, end):
|
def cfa(self, pred, end):
|
||||||
n = CFG_CALL(self)
|
call = CFG_CALL(self)
|
||||||
pred.add_child(n)
|
pred.add_child(call)
|
||||||
return n
|
|
||||||
|
# continuation after return
|
||||||
|
cont = CFG_Node()
|
||||||
|
|
||||||
|
if self.f_name not in FUNCTIONS:
|
||||||
|
raise RuntimeError(f"Call to undefined function '{self.f_name}'")
|
||||||
|
|
||||||
|
f_start, f_end = FUNCTIONS[self.f_name]
|
||||||
|
|
||||||
|
# call → function entry
|
||||||
|
call.add_child(f_start)
|
||||||
|
|
||||||
|
# function exit → continuation
|
||||||
|
f_end.add_child(cont)
|
||||||
|
|
||||||
|
return cont
|
||||||
|
|
||||||
|
|
||||||
class DECL(compiler.DECL):
|
class DECL(compiler.DECL):
|
||||||
def cfa(self, pred, end):
|
def cfa(self, pred, end):
|
||||||
entry = CFG_Node(self)
|
# function entry / exit
|
||||||
pred.add_child(entry)
|
f_start = CFG_Node(self)
|
||||||
return self.body.cfa(entry, end)
|
f_end = CFG_Node(self)
|
||||||
|
|
||||||
|
# register function
|
||||||
|
FUNCTIONS[self.f_name] = (f_start, f_end)
|
||||||
|
|
||||||
|
# build function body
|
||||||
|
body_end = self.body.cfa(f_start, f_end)
|
||||||
|
if body_end is not None:
|
||||||
|
body_end.add_child(f_end)
|
||||||
|
|
||||||
|
# function declaration does not alter current control flow
|
||||||
|
return pred
|
||||||
|
|
||||||
|
|
||||||
class LET(compiler.LET):
|
class LET(compiler.LET):
|
||||||
@@ -130,5 +177,5 @@ class RETURN(syntax.EXPRESSION):
|
|||||||
def cfa(self, pred, end):
|
def cfa(self, pred, end):
|
||||||
n = CFG_RETURN(self)
|
n = CFG_RETURN(self)
|
||||||
pred.add_child(n)
|
pred.add_child(n)
|
||||||
n.add_child(end) # direct jump to global END
|
n.add_child(end) # return to function exit
|
||||||
return None # no fallthrough
|
return None # no fallthrough
|
||||||
|
|||||||
Reference in New Issue
Block a user