Stmt::=skip::=∣if Expr then Stmt else Stmt::=∣while Expr do Stmt::=∣return Expr::=∣let x:=Expr::=∣x:=Expr::=∣Stmt;Stmt
翻译规则/指称语义
最直觉的规则:
[[skip;s]][[if (c) then st else se;s]][[while (c) do st;s]][[return e]][[let x:=e;s]]p[[x:=e;s]]p=[[s]]=if [[c]] then [[st;s]] else [[se;s]]=if [[c]] then [[st;while (c) do st;s]] else [[s]]=[[e]]=[[s]]p[[e]]=[[s]]p{x/[[e]]}
携带env(表示当前环境中的变量/参数):
[[if (c) then st else se;s]]env[[while (c) do st;s]]env[[return e]]env[[let x:=e;s]]p[[x:=e;s]]p=if [[c]]env then [[st;s]]env else [[se;s]]env=if [[c]]env then [[st;while (c) do st;s]]env else [[s]]env=[[e]]env=[[s]](p,x)p[[e]]p=[[s]]pp{x/[[e]]p}
处理语句块
语义中采用的模式为通过 Seq 连接语句,而实际的语言中使用语句块来表示多条语句。
BStmt::=skip::=∣if Expr then BStmt else BStmt::=∣while Expr do BStmt::=∣return Expr::=∣let x:=Expr::=∣x:=Expr::=∣{BStmt∗}
转换模式:计算每条语句的第一条可执行语句和剩余的语句列表。对于嵌套语句块,直接展平。
head::[BStmt]→Stmttail::[BStmt]→[BStmt]
于是翻译规则可以定义如下:
translateS=headS;translatetailS
块作用域
展平语句块后,块作用域的信息丢失了。我们需要在翻译时保留块作用域的信息。
int x = 2;{ int x = 1; }return x;
对嵌套作用域内的变量提前重命名:
int x = 2;{ int x' = 1; }return x;
语句命名
带有语句命名的语法:
NStmtSStmtStmt::=⟨name,SStmt⟩::=end::=∣Stmt;NStmt::=if Expr then NStmt else NStmt::=∣while Expr do NStmt::=∣return Expr::=∣let x:=Expr::=∣x:=ExprBStmt::=skip::=∣if Expr then BStmt else BStmt::=∣while Expr do BStmt::=∣return Expr::=∣let x:=Expr::=∣x:=Expr::=∣{BStmt∗}::=∣Labell:BStmt←explicit label