|
module Set = import "data/set.ml"
|
|
open import "prelude.ml"
|
|
|
|
type update_flag = Updatable | Function
|
|
|
|
type lambda_form 'a <- { name : string, free_vars : Set.t string, args : list string, update : update_flag, body : 'a }
|
|
|
|
type stg_atom =
|
|
| Var of string
|
|
| Int of int
|
|
|
|
type stg_pattern =
|
|
| Con_pat of int * list string
|
|
| Default
|
|
|
|
type stg_primitive =
|
|
| Add
|
|
| Sub
|
|
| Mul
|
|
| Div
|
|
| Equ
|
|
|
|
type stg_expr =
|
|
| Let of list (lambda_form stg_expr) * stg_expr
|
|
| Case of stg_expr * string * list (stg_pattern * stg_expr)
|
|
| App of stg_atom * list stg_atom
|
|
| Con of int * int * list stg_atom
|
|
| Prim of stg_primitive * list stg_atom
|
|
| Atom of stg_atom
|
|
|
|
type stg_def =
|
|
| Fun of { name : string, args : list string, body : stg_expr, is_con : option int }
|
|
| Ffi_def of { name : string, fent : string, arity : int }
|
|
|
|
let stg_fv =
|
|
let rec go = function
|
|
| Atom a -> go_atom a
|
|
| Let (lfs, e) ->
|
|
let fv = go e
|
|
fv `Set.difference` Set.from_list (map (.name) lfs)
|
|
| App (a, args) -> foldl Set.union Set.empty (map go_atom (a::args))
|
|
| Con (_, _, i) -> foldl Set.union Set.empty (map go_atom i)
|
|
| Case (ex, binder, pats) ->
|
|
foldl go_pat (go ex) pats
|
|
|> Set.delete binder
|
|
| Prim (_, args) -> foldl Set.union Set.empty (map go_atom args)
|
|
and go_atom = function
|
|
| Int _ -> Set.empty
|
|
| Var e -> Set.singleton e
|
|
and go_pat set = function
|
|
| Default, e -> Set.union set (go e)
|
|
| Con_pat (_, args), e -> Set.union set (go e `Set.difference` Set.from_list args)
|
|
go
|