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 }