% $Id: FreeVarIds.oz,v 1.13 2012/01/17 11:50:53 leavens Exp leavens $ % AUTHOR: Gary T. Leavens \insert 'SetOps.oz' declare % historically we are interested in statements FreeVarIds = FreeVarIdsStmt fun {FreeVarIdsProgram program(Qs ...)} {UnionList {Map Qs FreeVarIdsQuery}} end fun {FreeVarIdsQuery Q} case Q of seqQuery(S ...) then {FreeVarIdsStmt S} [] declareInQuery(S1 S2 ...) then {Minus {Union {FreeVarIdsStmt S1} {FreeVarIdsStmt S2}} {DeclarableVarIdsStmt S1}} [] declareQuery(S ...) then {Minus {FreeVarIdsStmt S} {DeclarableVarIdsStmt S}} end end fun {DeclarableVarIdsStmt Stmt} %% ENSURES: Result is the set of variable identifiers %% that occur either on the left hand sides of assignments %% or as the names of functions in named function statements %% (since they desugar to the left hand sides of assignments). case Stmt of unifyStmt(varId(V ...) Exp ...) then {AsSet [V]} [] namedFunStmt(Name ...) then {AsSet [Name]} [] seqStmt(StmtList ...) then {UnionList {Map StmtList DeclarableVarIdsStmt}} [] localStmt(varId(V ...) Body ...) then {Minus {DeclarableVarIdsStmt Body} {AsSet [V]}} [] threadStmt(S ...) then {DeclarableVarIdsStmt S} else {EmptySet} end end fun {FreeVarIdsStmt Stmt} %% ENSURES: Result is the set of variable identifiers %% that occur free in Stmt case Stmt of skipStmt then {EmptySet} [] skipStmt(...) then {EmptySet} [] seqStmt(StmtList ...) then {UnionList {Map StmtList FreeVarIds}} [] localStmt(varId(V ...) Body ...) then {Minus {FreeVarIds Body} {AsSet [V]}} [] unifyStmt(varId(V ...) Exp ...) then {Union {AsSet [V]} {FreeVarIdsExp Exp}} [] ifStmt(TestExp S1 S2 ...) then {Union {FreeVarIdsExp TestExp} {Union {FreeVarIds S1} {FreeVarIds S2}}} [] caseStmt(Exp Pattern S1 S2 ...) then {Union {FreeVarIdsExp Exp} {Union {Minus {FreeVarIds S1} {DeclaredIdsPattern Pattern}} {FreeVarIds S2}}} [] applyStmt(ProcExp ArgExpList ...) then {Union {FreeVarIdsExp ProcExp} {UnionList {Map ArgExpList FreeVarIdsExp}}} [] namedFunStmt(Name Formals Body ...) then {Union {AsSet [Name]} {Minus {FreeVarIdsExp Body} {UnionList {Map Formals DeclaredIdsPattern}}}} [] inStmt(Pattern Exp Body ...) then {Union {FreeVarIdsExp Exp} {Minus {FreeVarIds Body} {DeclaredIdsPattern Pattern}}} [] threadStmt(S ...) then {FreeVarIds S} end end fun {FreeVarIdsExp Exp} %% ENSURES: Result is the set of variable identifiers %% that occur free in Exp case Exp of varId(V ...) then {AsSet [V]} [] atomExp(...) then {EmptySet} [] boolExp(...) then {EmptySet} [] intLit(...) then {EmptySet} [] floatLit(...) then {EmptySet} [] recordExp(LabelExp FieldList ...) then {Union {FreeVarIdsExp LabelExp} {UnionList {Map FieldList FreeVarIdsField}}} [] procExp(Formals Body ...) then {Minus {FreeVarIds Body} {UnionList {Map Formals DeclaredIdsPattern}}} [] ifExp(TestExp E1 E2 ...) then {Union {FreeVarIdsExp TestExp} {Union {FreeVarIdsExp E1} {FreeVarIdsExp E2}}} [] caseExp(Exp Pattern E1 E2 ...) then {Union {FreeVarIdsExp Exp} {Union {Minus {FreeVarIdsExp E1} {DeclaredIdsPattern Pattern}} {FreeVarIdsExp E2}}} [] applyExp(FunExp ArgExpList ...) then {Union {FreeVarIdsExp FunExp} {UnionList {Map ArgExpList FreeVarIdsExp}}} [] threadExp(E ...) then {FreeVarIdsExp E} end end fun {DeclaredIdsPattern Pat} %% ENSURES: Result is the set of variable identifiers %% that occur free in Pat case Pat of varIdPat(V ...) then {AsSet [V]} [] atomPat(...) then {EmptySet} [] boolPat(...) then {EmptySet} [] recordPat(_ FieldList ...) then {UnionList {Map FieldList DeclaredIdsPatField}} end end fun {FreeVarIdsField Field} %% ENSURES: Result is the set of variable identifiers %% that occur free in Field case Field of colonFld(_ Exp ...) then {FreeVarIdsExp Exp} [] posFld(Exp ...) then {FreeVarIdsExp Exp} end end fun {DeclaredIdsPatField PF} %% ENSURES: Result is the set of variable identifiers %% that are declared (occur free) in PF case PF of colonFld(_ Pat ...) then {DeclaredIdsPattern Pat} [] posFld(Pat ...) then {DeclaredIdsPattern Pat} end end