| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- open Ast
- open Util
- let block_body = function
- | Block nodes -> nodes
- | _ -> raise InvalidNode
- let rec flatten_blocks = function
- | [] -> []
- | Block nodes :: t -> (flatten_blocks nodes) @ (flatten_blocks t)
- | h :: t -> h :: (flatten_blocks t)
- let rec replace_var var replacement = function
- | Var (name, loc) when name = var -> Var (replacement, loc)
- | node -> transform_children (replace_var var replacement) node
- let for_to_while node =
- let new_vars = ref [] in
- let rec traverse = function
- (* Do not traverse into local functions (already done by var_init) *)
- | FunDef (_, _, _, _, _, _) as node -> node
- (* Transform for-loops to while-loops *)
- | For (counter, start, stop, step, body, loc) ->
- let _i = fresh_var counter in
- let _stop = fresh_var "stop" in
- let _step = fresh_var "step" in
- new_vars := !new_vars @ [_i; _stop; _step];
- let vi = Var (_i, noloc) in
- let vstop = Var (_stop, locof stop) in
- let vstep = Var (_step, locof step) in
- let cond = Cond (
- Binop (Gt, vstep, IntConst (0, noloc), noloc),
- Binop (Lt, vi, vstop, noloc),
- Binop (Gt, vi, vstop, noloc),
- noloc
- ) in
- Block [
- Assign (_i, start, locof start);
- Assign (_stop, stop, locof stop);
- Assign (_step, step, locof step);
- While (cond, traverse (Block (
- (* TODO: check for illegal assigments of counter in body *)
- block_body (replace_var counter _i body) @
- [Assign (_i, Binop (Add, vi, vstep, noloc), noloc)]
- )), loc);
- ]
- | node -> transform_children traverse node
- in
- let node = traverse node in
- (node, new_vars)
- let rec var_init = function
- (* Move global initialisations to __init function *)
- | Program (decls, loc) ->
- let decls = flatten_blocks (List.map var_init decls) in
- let rec trav assigns = function
- | [] -> (assigns, [])
- | (Assign (_, _, _) as h) :: t -> trav (assigns @ [h]) t
- | h :: t ->
- let (assigns, decls) = trav assigns t in
- (assigns, (h :: decls))
- in
- let (assigns, decls) = trav [] decls in (
- match assigns with
- | [] -> Program (decls, loc)
- | assigns ->
- let init_func = FunDef (true, Void, "__init", [], Block assigns, noloc) in
- Program (init_func :: decls, loc)
- )
- (* Move global variable initialisations to exported __init function *)
- | GlobalDef (export, ctype, name, Some init, loc) ->
- Block [GlobalDef (export, ctype, name, None, loc);
- Assign (name, init, locof init)]
- (* Split local variable initialisations in declaration and assignment *)
- | FunDef (export, ret_type, name, params, Block body, loc) ->
- let move_inits body =
- let rec trav inits node = match node with
- (* translate scalar array initialisation to ArrayScalar node,
- * for easy replacement later on *)
- | VarDec (ArrayDef (_, _) as vtype, name,
- Some ((BoolConst (_, l)) as v), loc) :: t
- | VarDec (ArrayDef (_, _) as vtype, name,
- Some ((FloatConst (_, l)) as v), loc) :: t
- | VarDec (ArrayDef (_, _) as vtype, name,
- Some ((IntConst (_, l)) as v), loc) :: t ->
- trav inits (VarDec (vtype, name, Some (ArrayScalar (v, l)), loc) :: t)
- | VarDec (ctype, name, init, loc) :: t ->
- (* array definition: create __allocate statement *)
- let alloc = match ctype with
- | ArrayDef (_, dims) -> [Allocate (name, dims, loc)]
- | _ -> []
- in
- (* initialisation: create assign statement *)
- let add = match init with
- | Some value -> alloc @ [Assign (name, value, loc)]
- | None -> alloc
- in
- VarDec (ctype, name, None, loc) :: (trav (inits @ add) t)
- (* initialisations need to be placed after local functions *)
- | (FunDef (_, _, _, _, _, _) as h) :: t ->
- (var_init h) :: (trav inits t)
- (* rest of function body: recurse *)
- | rest -> inits @ (List.map var_init rest)
- in
- flatten_blocks (trav [] body)
- in
- let (body, new_vars) = for_to_while (Block (move_inits body)) in
- let create_vardec name = VarDec (Int, name, None, noloc) in
- let new_vardecs = List.map create_vardec !new_vars in
- let stats = new_vardecs @ (flatten_blocks (block_body body)) in
- FunDef (export, ret_type, name, params, Block stats, loc)
- | node -> transform_children var_init node
- (*
- let rec array_init = function
- (* transform scalar assignment into nested for loops *)
- | Assign (name, ArrayScalar (value)) ->
- let rec add_loop indices = function
- | [] ->
- Assign (Deref (name, indices), value)
- | dim :: rest ->
- let counter = fresh_var "counter" in
- let ind = (indices @ [Var counter]) in
- For (counter, IntConst 0, dim, IntConst 1, add_loop ind rest)
- in
- add_loop [] dims
- | Assign (name, ArrayConst (dims)) -> Block []
- | node -> transform array_init node
- *)
- let rec phase input =
- prerr_endline "- Desugaring";
- match input with
- | Ast (node, args) ->
- Ast (var_init node, args)
- | _ -> raise (InvalidInput "desugar")
|