
000001| (** A translation from unlabeled AST to labeled AST. *)

000002|

000003| (* Requirements:

000004|

000005| Lexing.position/ASTnode --> line_label (for pprinting analysis result)

000006|

000007| fun_label --> Fun literal (for CFA)

000008| table_label --> Table literal (for heap analysis)

000009|

000010| + enclosing function label (option)

000011| *)

000012|

000013| module A = Ast

000014| module L = Last

000015|

000016| let reset,make_label,make_res_label =

000017| (*[1]*)let count = ref 1 in

000018| (*[1]*)let res_count = ref 0 in

000019| (*[1]*)(fun () -> (*[172]*)count := 1),

000020| (fun () -> (*[2045]*)let label = !count in

000021| (*[2045]*)begin

000022| (*[2045]*)incr count;

000023| (*[2045]*)label

000024| end),

000025| (fun () -> (*[8]*)let label = !res_count in

000026| (*[8]*)begin

000027| (*[8]*)decr res_count;

000028| (*[8]*)label

000029| end)

000030|

000031| type info =

000032| { mutable enclosing_fun : L.label option;

000033| mutable inside_loop : bool;

000034| mutable pos_map : (L.label * L.stmt) list; (* stmt or stmt list? *)

000035| mutable fun_map : (L.label * L.lit) list;

000036| mutable table_map : (L.label * L.lit) list; }

000037|

000038| let rec label_lit info l = match l with

000039| | A.Nil -> (*[74]*)L.Nil

000040| | A.Bool b -> (*[50]*)L.Bool b

000041| | A.Number n -> (*[270]*)L.Number n

000042| | A.String s -> (*[301]*)L.String s

000043| | A.Table (unnamed,named) ->

000044| (*[120]*)let lab = make_label () in

000045| (*[120]*)let unnamed' = List.map (fun e -> (*[27]*)label_exp info e) unnamed in

000046| (*[120]*)let named' = List.map (fun (s,e) -> ((*[108]*)s,label_exp info e)) named in

000047| (*[120]*)let tab = L.Table (lab,unnamed',named') in

000048| (*[120]*)info.table_map <- (lab,tab)::info.table_map; (*add table*)

000049| (*[120]*)tab

000050|

000051| | A.Fun (xs,bl) ->

000052| (*[110]*)let old_lab = info.enclosing_fun in

000053| (*[110]*)let old_flag = info.inside_loop in

000054| (*[110]*)let lab = make_label () in

000055| (*[110]*)let () = info.enclosing_fun <- Some lab in (*new enclosing*)

000056| (*[110]*)let () = info.inside_loop <- false in (*inside function, not loop*)

000057| (*[110]*)let bl' = label_block info bl in

000058| (*[110]*)let () = info.enclosing_fun <- old_lab in (*reset label*)

000059| (*[110]*)let () = info.inside_loop <- old_flag in (*reset flag*)

000060| (*[110]*)let endlab = make_label () in

000061| (*[110]*)let f = L.Fun (lab,xs,bl',endlab) in

000062| (*[110]*)info.fun_map <- (lab,f)::info.fun_map; (*add function*)

000063| (*[110]*)f

000064|

000065| and label_lvalue info lv = match lv with

000066| | A.Name n -> (*[1376]*)L.Name n

000067| | A.Index (e,f) ->

000068| (*[128]*)let clab = make_label () in

000069| (*[128]*)let e' = label_exp info e in

000070| (*[128]*)let e'' = label_exp info (A.Lit (A.String (A.Normal f))) in

000071| (*[128]*)L.DynIndex(clab,e',e'')

000072| | A.DynIndex (e0,e1) ->

000073| (*[90]*)let clab = make_label () in

000074| (*[90]*)let e0' = label_exp info e0 in

000075| (*[90]*)let e1' = label_exp info e1 in

000076| (*[90]*)L.DynIndex (clab,e0',e1')

000077|

000078| and label_exp info e = match e with

000079| | A.Lit l -> (*[925]*)L.Lit (label_lit info l)

000080| | A.Lvalue lv -> (*[1269]*)L.Lvalue (label_lvalue info lv)

000081| | A.Unop (uo,e) ->

000082| (*[8]*)let e' = label_exp info e in

000083| (*[8]*)L.Unop (uo,e')

000084| | A.Binop (e0,bo,e1) ->

000085| (*[136]*)let clab = make_label () in

000086| (*[136]*)let e0' = label_exp info e0 in

000087| (*[136]*)let e1' = label_exp info e1 in

000088| (*[136]*)L.Binop (clab,e0',bo,e1')

000089| | A.And (e0,e1) ->

000090| (*[13]*)let e0' = label_exp info e0 in

000091| (*[13]*)let e1' = label_exp info e1 in

000092| (*[13]*)L.And (e0',e1')

000093| | A.Or (e0,e1) ->

000094| (*[4]*)let e0' = label_exp info e0 in

000095| (*[4]*)let e1' = label_exp info e1 in

000096| (*[4]*)L.Or (e0',e1')

000097| | A.Call (e,es) ->

000098| (*[142]*)let clab = make_label () in

000099| (*[142]*)let e' = label_exp info e in

000100| (*[142]*)let es' = List.map (label_exp info) es in

000101| (*[142]*)L.Call (clab,e',es')

000102| | A.Methcall (e,mname,es) ->

000103| (*[8]*)let clab = make_label () in

000104| (*[8]*)let ilab = make_label () in

000105| (*[8]*)let e' = label_exp info e in

000106| (*[8]*)let es' = List.map (label_exp info) es in

000107| (*[8]*)L.Methcall (clab,ilab,e',mname,es')

000108| | A.Paren e0 ->

000109| (*[14]*)let e0' = label_exp info e0 in

000110| (*[14]*)L.Paren e0'

000111|

000112| and label_stmt info s =

000113| (*[984]*)let line_lab = make_label () in

000114| (*[984]*)let pos = { L.lex_pos = s.A.stmt_pos;

000115| L.func = info.enclosing_fun;

000116| L.line_label = line_lab; } in

000117| (*[984]*)let mkstmt s =

000118| (*[984]*)let stm = { L.stmt_pos = pos; L.stmt = s } in

000119| (*[984]*)info.pos_map <- (line_lab,stm)::info.pos_map; (* add stm *)

000120| (*[984]*)stm in

000121| match s.A.stmt with

000122| | A.Break ->

000123| (*[11]*)if info.inside_loop

000124| then (*[11]*)mkstmt L.Break

000126| | A.If (e,bl1,bl2) ->

000127| (*[36]*)let e' = label_exp info e in

000128| (*[36]*)let bl1' = label_block info bl1 in

000129| (*[36]*)let bl2' = label_block info bl2 in

000130| (*[36]*)mkstmt (L.If (e',bl1',bl2'))

000131| | A.WhileDo (e,bl) ->

000132| (*[35]*)let elab = make_label () in

000133| (*[35]*)let flag = info.inside_loop in

000134| (*[35]*)let e' = label_exp info e in

000135| (*[35]*)info.inside_loop <- true; (* entering loop *)

000136| (*[35]*)let bl' = label_block info bl in

000137| (*[35]*)let () = info.inside_loop <- flag in (*;*) (* reset loop flag *)

000138| (*[35]*)let stm = mkstmt (L.WhileDo (e',bl',elab)) in

000139| (*[35]*)let () = info.pos_map <- (elab,stm)::info.pos_map in(*;*) (* add end-label to while-stm binding *)

000140| (*[35]*)stm

000141| (* | A.For (x,e0,e1,bl) ->

000142| let e0' = label_exp info e0 in

000143| let e1' = label_exp info e1 in

000144| let bl' = label_block info bl in

000145| mkstmt (L.For (x,e0',e1',bl')) *)

000146| | A.Doend bl ->

000147| (*[18]*)let bl' = label_block info bl in

000148| (*[18]*)mkstmt (L.Doend bl')

000149| | A.Assign (lvs,es) ->

000150| (*[311]*)let lvs' = List.map (label_lvalue info) lvs in

000151| (*[311]*)let es' = List.map (label_exp info) es in

000152| (*[311]*)mkstmt (L.Assign (lvs',es'))

000153| | A.Local (xs,es) ->

000154| (*[242]*)let es' = List.map (label_exp info) es in

000155| (*[242]*)mkstmt (L.Local (xs,es'))

000156| | A.Callstmt (e,es) ->

000157| (*[203]*)let e' = label_exp info e in

000158| (*[203]*)let es' = List.map (label_exp info) es in

000159| (*[203]*)mkstmt (L.Callstmt (e',es'))

000160| | A.Methcallstmt (e,mname,es) ->

000161| (*[2]*)let ilab = make_label () in

000162| (*[2]*)let e' = label_exp info e in

000163| (*[2]*)let es' = List.map (label_exp info) es in

000164| (*[2]*)mkstmt (L.Methcallstmt (ilab,e',mname,es'))

000165| | A.Return es ->

000166| (*[126]*)let es' = List.map (label_exp info) es in

000167| (*[126]*)mkstmt (L.Return es')

000168|

000169| and label_block info bl =

000170| (*[407]*)let stmts = List.map (label_stmt info) bl in

000171| match stmts with

000172| | [] -> (*[22]*)None

000173| | s::_ ->

000174| (*[385]*)let lab = s.L.stmt_pos.L.line_label in

000175| (*[385]*)Some { L.label = lab;

000176| L.stmts = stmts; }

000177|

000178| (* label_prog : string option -> Ast.block -> Last.last *)

000179| let label_prog fname_opt p =

000180| let info = { enclosing_fun = None;

000181| inside_loop = false;

000182| pos_map = [];

000183| fun_map = [];

000184| table_map = []; } in

000185| let p' = label_block info p in

000186| let retlab = make_label () in

000187| let pos_map (*l*) = (*List.assoc l*) info.pos_map in

000188| let fun_map l = List.assoc l info.fun_map in

000189| let table_map l = List.assoc l info.table_map in

000190| { L.name = fname_opt;

000191| L.last = p';

000192| L.ret_label = retlab;

000193| L.pos_map = pos_map;

000194| L.fun_map = fun_map;

000195| L.table_map = table_map }