diff --git a/src/ast2lic.ml b/src/ast2lic.ml index dbf77b524c51ae020e48be8aa9134f970018277f..af426fca9975c316bc12bfcfe014144fae5ba880 100644 --- a/src/ast2lic.ml +++ b/src/ast2lic.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 27/03/2013 (at 09:34) by Erwan Jahier> *) +(* Time-stamp: <modified the 02/04/2013 (at 09:29) by Erwan Jahier> *) open Lxm @@ -405,6 +405,20 @@ and (translate_val_exp : IdSolver.t -> UnifyClock.subst -> AstCore.val_exp let mk_by_pos_op by_pos_op_eff = CallByPosLic(flagit by_pos_op_eff lxm, vel_eff) in + let mk_nary_pos_op by_pos_op_eff = + (* For nor and diese: internally, nor and diese takes an array of val_exp, + to make it easier the translation into boolred. + + It is the good spot to do that? what could be a better spot? + *) + let array_val_exp = + { ve_core = CallByPosLic(flagit Lic.ARRAY lxm, vel_eff); + ve_typ = [Array_type_eff(List.hd (List.hd vel_eff).ve_typ, List.length vel_eff)]; + ve_clk = (List.hd vel_eff).ve_clk + } + in + CallByPosLic(flagit by_pos_op_eff lxm, [array_val_exp]) + in let s, vef_core = match by_pos_op with | WITH_n(_,_,_) -> assert false (* handled at the top of the function *) @@ -415,6 +429,10 @@ and (translate_val_exp : IdSolver.t -> UnifyClock.subst -> AstCore.val_exp | Predef_n({it=RCONST_n r}) -> s,mk_by_pos_op(Lic.CONST (Real_const_eff r)) | Predef_n({it=ICONST_n i}) -> s, mk_by_pos_op(Lic.CONST (Int_const_eff i)) + | Predef_n({it=NOR_n;src=lxm}) -> s, mk_nary_pos_op( + Lic.PREDEF_CALL (flagit (AstPredef.op_to_long NOR_n,[]) lxm)) + | Predef_n({it=DIESE_n;src=lxm}) -> s, mk_nary_pos_op( + Lic.PREDEF_CALL (flagit (AstPredef.op_to_long DIESE_n,[]) lxm)) | Predef_n(op) -> s, mk_by_pos_op( Lic.PREDEF_CALL (flagit (AstPredef.op_to_long op.it,[]) op.src)) | CALL_n node_exp_f -> diff --git a/src/lic2soc.ml b/src/lic2soc.ml index 74f99c730263460c66e8a92156971302bc536fec..9af1d89b90dafbb304ff183d1616974230c6f48e 100644 --- a/src/lic2soc.ml +++ b/src/lic2soc.ml @@ -1,4 +1,4 @@ -(** Time-stamp: <modified the 29/03/2013 (at 16:36) by Erwan Jahier> *) +(** Time-stamp: <modified the 02/04/2013 (at 08:32) by Erwan Jahier> *) open Lxm open Lic @@ -348,7 +348,7 @@ let soc_step_to_operation: | None -> Soc.Procedure (comp.Soc.key) | Some (i) -> Soc.Method(i,name) -let (action_of_step: Lxm.t -> Soc.t -> Lic.clock -> Soc.var_expr list -> +let (action_of_step : Lxm.t -> Soc.t -> Lic.clock -> Soc.var_expr list -> Soc.var_expr list -> Soc.instance option -> Soc.step_method -> action) = fun lxm c clk il ol mem step -> let local_nth i l = @@ -536,8 +536,7 @@ let rec (actions_of_expression_acc: Lxm.t -> Soc.tbl -> - instances - action dependances *) - let inputs : Soc.var_expr list = - List.map (val_exp_to_filter ctx.prg) val_exp_list in + let inputs = List.map (val_exp_to_filter ctx.prg) val_exp_list in let ctx, mem_opt = make_instance lxm clk ctx soc in let actions = let m2act = action_of_step lxm soc clk inputs lpl mem_opt in @@ -619,8 +618,8 @@ let rec f: (LicPrg.t -> Lic.node_key -> Soc.key * Soc.tbl) = | None -> assert false | Some node_def -> (match soc_of_node prog node_def soc_tbl with - | Some(_,soc,soc_tbl) -> SocMap.add sk soc soc_tbl - | None -> + | Some(_,soc,soc_tbl) -> SocMap.add sk soc soc_tbl + | None -> print_string ("Undefined soc : " ^ (string_of_node_key nk) ^ "\n"); flush stdout; soc_tbl @@ -636,9 +635,9 @@ let rec f: (LicPrg.t -> Lic.node_key -> Soc.key * Soc.tbl) = | Undef_soc (sk,lxm,pos_op, types) -> let soc = SocPredef.soc_interface_of_pos_op lxm pos_op types in if sk<>soc.key then ( - print_string ("Soc key mismatch :\n\t" ^ + print_string ("Soc key mismatch :\n\t" ^ (SocUtils.string_of_soc_key sk) ^ "\n<>\n\t" ^ - (SocUtils.string_of_soc_key soc.key) ^ "\n"); + (SocUtils.string_of_soc_key soc.key) ^ "\n"); flush stdout; assert false ); @@ -647,10 +646,10 @@ let rec f: (LicPrg.t -> Lic.node_key -> Soc.key * Soc.tbl) = (* The arrow is translated into a if. So we make sure that the "if" is in the soc tbl *) let if_sk = "Lustre::if", [Bool;t;t], None in - let soc_tbl = + let soc_tbl = if pos_op = Lic.ARROW && not(SocMap.mem if_sk soc_tbl) then - let soc = SocPredef.soc_interface_of_pos_op lxm - (Lic.PREDEF_CALL ({ it=("Lustre","if"),[]; src=lxm})) [Bool;t;t] + let soc = SocPredef.soc_interface_of_pos_op lxm + (Lic.PREDEF_CALL ({ it=("Lustre","if"),[]; src=lxm})) [Bool;t;t] in SocMap.add soc.key soc soc_tbl else diff --git a/src/licEvalType.ml b/src/licEvalType.ml index f2400ac09ae5825fd95026403a4271b43c431607..9aa140e99543f4c6afc84c522f503e1e9eb4bfe0 100644 --- a/src/licEvalType.ml +++ b/src/licEvalType.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 27/03/2013 (at 10:00) by Erwan Jahier> *) +(* Time-stamp: <modified the 02/04/2013 (at 10:18) by Erwan Jahier> *) open AstPredef open Lxm @@ -64,6 +64,9 @@ let rrr_profile = [(id "i1", r);(id "i2", r)], [(id "o", r)] (* real*real -> rea let ri_profile = [id "i", r], [id "o", i] (* real -> int *) let ir_profile = [id "i", i], [id "o", r] (* int -> real *) +(* for nor and diese, I cannot know the size of the array, so I put an 'any' type *) +let ab_profile = [(id "i", TypeVar Any)], [(id "o", b)] (* bool^s -> bool *) + (** Constant profiles *) let b_profile = [],[id "o", b] let i_profile = [],[id "o", i] @@ -258,10 +261,8 @@ let boolred_profile let op2profile (* BEQUILLE *) - (id_solver_opt: IdSolver.t option) - (op: AstPredef.op) - (lxm: Lxm.t) -: Lic.node_profile = + (id_solver_opt: IdSolver.t option) (op: AstPredef.op) (lxm: Lxm.t) + : Lic.node_profile = let res = match op with | TRUE_n | FALSE_n -> b_profile @@ -279,14 +280,7 @@ let op2profile | MINUS_n | PLUS_n | TIMES_n | SLASH_n | DIV_n -> ooo_profile | RMINUS_n | RPLUS_n | RTIMES_n | RSLASH_n -> rrr_profile | MOD_n | IMINUS_n | IPLUS_n | ISLASH_n | ITIMES_n -> iii_profile - (* - The current representation of node_profile prevent us from - being able to represent "bool list" (i.e., operator of variable - arity). I could extend the type node_profile, but is it worth the - complication just to be able to define alias nodes on "nor" and "#"? - Actually, even if I extend this data type, I don'ty know how I could - generate an alias node for them anyway... *) - | NOR_n | DIESE_n -> assert false (* diese_profile *) + | NOR_n | DIESE_n -> ab_profile in res @@ -294,13 +288,8 @@ let op2profile (* VERSION GÉNÉRALE, valable pour les MACROS, et qui necessite donc un IdSolver.t *) -let make_node_exp_eff - (id_solver: IdSolver.t) - (has_mem: bool option) - (op: op) - (lxm: Lxm.t) -: Lic.node_exp = - +let make_node_exp_eff (id_solver: IdSolver.t) (has_mem: bool option) (op: op) (lxm: Lxm.t) + : Lic.node_exp = let id = AstPredef.op_to_long op in let (lti,lto) = op2profile (Some id_solver) op lxm in let i = ref 0 in @@ -342,12 +331,7 @@ let make_node_exp_eff (* VERSION SIMPLE, valable UNIQUEMENT pour les NON MACROS *) -let make_simple_node_exp_eff - (has_mem: bool option) - (op: op) - (lxm: Lxm.t) -: Lic.node_exp = - +let make_simple_node_exp_eff (has_mem: bool option) (op: op) (lxm: Lxm.t) : Lic.node_exp = let id = AstPredef.op_to_long op in let (lti,lto) = op2profile None op lxm in let i = ref 0 in @@ -387,11 +371,7 @@ let make_simple_node_exp_eff res (* exported *) -let f - (id_solver: IdSolver.t) - (op: op) - (lxm: Lxm.t) - : typer = fun ll -> +let f (id_solver: IdSolver.t) (op: op) (lxm: Lxm.t) : typer = fun ll -> match op with | IF_n -> ( (* VERRUE 1 *) @@ -404,15 +384,6 @@ let f (type_error (List.flatten [[Bool_type_eff]; t; e]) "bool*any*any") | x -> (raise_arity_error "" (List.length x) 3) ) - | (NOR_n | DIESE_n) -> - (* VERRUE 2 : cf XXX above: therefore i define an ad-hoc - check for them. *) - let check_nary_iter acc ceff = - match ceff with (Bool_type_eff) -> - acc | _ -> (type_error [ceff] "bool") - in - List.fold_left check_nary_iter () (List.flatten ll); - [Bool_type_eff] | _ -> (* general case *) let node_eff = make_node_exp_eff id_solver (Some false) op lxm in diff --git a/src/licEvalType.mli b/src/licEvalType.mli index 1f96bbf6a49234a6a881e5c24be7eb684f2956d4..a6645720e404017290a6025630ec84b4b74220d9 100644 --- a/src/licEvalType.mli +++ b/src/licEvalType.mli @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 12/02/2013 (at 18:06) by Erwan Jahier> *) +(* Time-stamp: <modified the 02/04/2013 (at 09:49) by Erwan Jahier> *) (** Performs static evaluations of predefined operators in type expressions *) @@ -23,6 +23,7 @@ val f : IdSolver.t -> AstPredef.op -> Lxm.t -> typer - une pour les macros, qui nécessite un IdSolver.t pour traiter les Lic.static_arg list - l'autre pour les noeuds simple qui peut être utilisée statiquement *) +(* [make_node_exp_eff id_solver has_mem op size lxm] *) val make_node_exp_eff : IdSolver.t -> bool option -> AstPredef.op -> Lxm.t -> Lic.node_exp diff --git a/src/socExecEvalPredef.ml b/src/socExecEvalPredef.ml index 4cb18adb1ac689fbb631fc702c283a701fc106d4..0623740da9e12cf965b0e913a7cfa40af35e5dc5 100644 --- a/src/socExecEvalPredef.ml +++ b/src/socExecEvalPredef.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 28/03/2013 (at 15:37) by Erwan Jahier> *) +(* Time-stamp: <modified the 02/04/2013 (at 10:15) by Erwan Jahier> *) open SocExecValue open Soc @@ -153,6 +153,15 @@ let lustre_and ctx = in { ctx with s = sadd ctx.s vn vv } +let lustre_xor ctx = + let (vn,vv) = + match ([get_val "x" ctx; get_val "y" ctx]) with + | [B x1; B x2] -> "z"::ctx.cpath,B(x1 <> x2) + | [U; _] | [_;U] -> "z"::ctx.cpath,U + | _ -> assert false + in + { ctx with s = sadd ctx.s vn vv } + let lustre_neq ctx = let (vn,vv) = @@ -230,15 +239,6 @@ let lustre_hat tl ctx = in { ctx with s = sadd ctx.s vn vv } -(* That one is different *) -let lustre_xor ctx = assert false -let lustre_diese ctx = assert false -(* let (vn,vv) = *) -(* let values = [get_val "x" ctx; get_val "y" ctx] in *) -(* let l = List.filter (fun x -> x=B true) values in *) -(* "z"::ctx.cpath,B(List.length l = 1) *) - - (* exported *) let (get: Soc.key -> (ctx -> ctx)) = fun (n,tl,_) -> @@ -259,6 +259,7 @@ let (get: Soc.key -> (ctx -> ctx)) = | "Lustre::lte" -> lustre_lte | "Lustre::gte" -> lustre_gte + | "Lustre::xor" -> lustre_xor | "Lustre::and" -> lustre_and | "Lustre::eq" -> lustre_eq | "Lustre::neq" -> lustre_neq @@ -272,8 +273,8 @@ let (get: Soc.key -> (ctx -> ctx)) = | "Lustre::array" -> lustre_array tl | "Lustre::concat" -> lustre_concat - | "Lustre::xor" -> lustre_xor - | "Lustre::diese" -> lustre_diese + | "Lustre::nor" -> assert false (* ougth to be translated into boolred *) + | "Lustre::diese" -> assert false (* ditto *) | _ -> raise Not_found diff --git a/src/socPredef.ml b/src/socPredef.ml index a7cdd5924a8703bc98fa9a7d294dcb9a8db539a8..f96d31f4f8de0b358acc1cc2ef2a1864d2085d4f 100644 --- a/src/socPredef.ml +++ b/src/socPredef.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 29/03/2013 (at 16:06) by Erwan Jahier> *) +(* Time-stamp: <modified the 02/04/2013 (at 10:20) by Erwan Jahier> *) (** Synchronous Object Code for Predefined operators. *) @@ -25,14 +25,17 @@ let (soc_profile_of_types : Soc.var_type list -> var list * var list) = | [t1; t2] -> aa t1 t2 | [t1;t2;t3] -> aaa t1 t2 t3 | [Bool;t1;t2;t3] -> baaa t1 - | tl -> - (* diese and xor XXX todo *) print_string ("Unsupported case: "^ ( String.concat "," (List.map SocUtils.string_of_type_ref tl))); flush stdout; assert false - + +(* For diese and nor *) +let (soc_profile_of_types_nary : Soc.var_type list -> var list * var list) = + fun vl -> + ["x", Array(Bool,List.length vl)], ["z",Bool] + let step11 = { (* a useful alias again *) name = "step"; @@ -78,6 +81,7 @@ let of_soc_key : Soc.key -> Soc.t = fun sk -> let (id, tl, _) = sk in let sp = soc_profile_of_types in + let sp_nary = soc_profile_of_types_nary in match id with | "Lustre::mod" -> (make_soc sk (sp tl) [step11]) | "Lustre::uminus" -> (make_soc sk (sp tl) [step11]) @@ -104,7 +108,7 @@ let of_soc_key : Soc.key -> Soc.t = | "Lustre::current" -> (make_soc sk (sp tl) [step11]) - (* Those have instances *) + (* Those have instances *) | "Lustre::pre" -> let _,tl,_ = sk in @@ -168,46 +172,46 @@ let of_soc_key : Soc.key -> Soc.t = } | "Lustre::fby" -> assert false - (* replace fby by '->' + 'pre' ? - let _,tl,_ = sk in - let t = List.hd tl in - let pre_mem:var = Var(get_mem_name sk, t) in - let v1,v2,vout = match prof with ([v1;v2],[vout]) -> v1,v2,vout | _ -> assert false in - { - key = sk; - profile = (sp tl); - instances = [("fby_mem", sk)]; - step = [ - { - name = "get"; - lxm = Lxm.dummy "predef soc"; - idx_ins = []; - idx_outs = [0]; - impl = Some([pre_mem],[Call([Var(vout)], Assign, [pre_mem])]);; - }; - { - name = "set"; - lxm = Lxm.dummy "predef soc"; - idx_ins = [1]; - idx_outs = []; - impl = Gaol([pre_mem],[Call([pre_mem], Assign, [Var(v1)])]);; - have_mem = true; - }; - ]; - precedences = ["set", ["get"]]; - init = Some { - name = "init"; - lxm = Lxm.dummy "predef soc"; - idx_ins = [0] ; - idx_outs = []; - impl = None; - }; - } *) + (* replace fby by '->' + 'pre' ? + let _,tl,_ = sk in + let t = List.hd tl in + let pre_mem:var = Var(get_mem_name sk, t) in + let v1,v2,vout = match prof with ([v1;v2],[vout]) -> v1,v2,vout | _ -> assert false in + { + key = sk; + profile = (sp tl); + instances = [("fby_mem", sk)]; + step = [ + { + name = "get"; + lxm = Lxm.dummy "predef soc"; + idx_ins = []; + idx_outs = [0]; + impl = Some([pre_mem],[Call([Var(vout)], Assign, [pre_mem])]);; + }; + { + name = "set"; + lxm = Lxm.dummy "predef soc"; + idx_ins = [1]; + idx_outs = []; + impl = Gaol([pre_mem],[Call([pre_mem], Assign, [Var(v1)])]);; + have_mem = true; + }; + ]; + precedences = ["set", ["get"]]; + init = Some { + name = "init"; + lxm = Lxm.dummy "predef soc"; + idx_ins = [0] ; + idx_outs = []; + impl = None; + }; + } *) | "Lustre::if" -> { key = sk; profile = (sp tl); instances = []; - (* init = None; *) + (* init = None; *) precedences = []; have_mem = None; step = [ @@ -217,9 +221,50 @@ let of_soc_key : Soc.key -> Soc.t = idx_ins = [0; 1; 2]; idx_outs = [0]; impl = Predef; + } ]; + } + | "Lustre::nor" -> + let size = match sk with + | _,[Array(Bool,size);_],_ -> size + | _ -> assert false + in + { + Soc.key = sk; + Soc.profile = sp_nary tl; + Soc.instances = [] ; + Soc.step = [ + { + name = "step"; + lxm = Lxm.dummy "nor soc"; + idx_ins = [0]; + idx_outs = [0]; + impl = Boolred(0,0, size); } ]; - } + Soc.have_mem = None; + Soc.precedences = []; + } + | "Lustre::diese" -> + let size = match sk with + | _,[Array(Bool,size);_],_ -> size + | _ -> assert false + in + { + Soc.key = sk; + Soc.profile = sp_nary tl; + Soc.instances = [] ; + Soc.step = [ + { + name = "step"; + lxm = Lxm.dummy "nor soc"; + idx_ins = [0]; + idx_outs = [0]; + impl = Boolred(1,1, size); + } + ]; + Soc.have_mem = None; + Soc.precedences = []; + } | _ -> print_string ("*** The soc of "^id ^ " is not defined. FINISH ME! \n"); flush stdout; assert false @@ -390,7 +435,10 @@ let output_type_of_op op tl = | "Lustre::lt" | "Lustre::gt" | "Lustre::lte" - | "Lustre::gte" -> Bool + | "Lustre::gte" + | "Lustre::nor" + | "Lustre::diese" + -> Bool | "Lustre::real2int" -> Int | "Lustre::int2real" -> Real | "Lustre::if" -> List.hd (List.tl tl) @@ -405,14 +453,12 @@ let (soc_interface_of_pos_op: let concrete_type = List.nth types 1 in let soc = of_soc_key ("Lustre::if", types@[concrete_type], None) in instanciate_soc soc concrete_type - - | Lic.PREDEF_CALL {Lxm.it=(op,sargs)}, _ -> + | Lic.PREDEF_CALL {Lxm.it=(op,sargs)}, _ -> assert (sargs=[]); let soc_name = Ident.string_of_long op in let out_type = output_type_of_op soc_name types in let soc = of_soc_key (soc_name, types@[out_type], None) in soc - | Lic.FBY, _ -> let concrete_type = List.nth types 0 in let soc = of_soc_key (("Lustre::fby"), types@[concrete_type], None) in diff --git a/test/should_work/arrays.lus b/test/should_work/arrays.lus index dcbe0f7c1c206df999f7d54fc11c482f5b2502b6..bf91fc0d904987e8a7e6bc04390bd7bfaed0c4d9 100644 --- a/test/should_work/arrays.lus +++ b/test/should_work/arrays.lus @@ -70,7 +70,7 @@ let co, s = fillred<<fillred<<fillred<<full_adder; n>>; m>>; p>>(false, x, y); tel ------------ un noeud principale pour tester le tout ---------------------- +----------- un noeud principal pour tester le tout ---------------------- type tab3d = int^n^m^p; node arrays( init_incr: int; init_long: long ) diff --git a/todo.org b/todo.org index cc3342f6af640bdced9ea78d92d766e6b7f461bf..b7d9190a0bd253725a28b7e759d4dfa3fa96f5b7 100644 --- a/todo.org +++ b/todo.org @@ -2,35 +2,54 @@ #+CATEGORY: lv6 * lus2lic -exec +** TODO meta operateurs + - State "TODO" from "" [2013-03-19 Tue 10:33] +** TODO Unifier les modules Data de Lustre V6 et Lutin + - State "TODO" from "" [2013-04-02 Tue 08:33] + +ie. rajouter les tableaux, struct, et enum en lutin quitte à ne pas s'en servir +tout de suite. + +Ca va facilité l'utilisation sans duplic de code du module rif_base + +** TODO Integrer ce mode -exec dans lurette, à la facon dont je l'ai fait pour Lutin + - State "TODO" from "" [2013-03-30 Sat 14:35] +Question : comment j'integre ? via un lus2lic.a ? + +file:~/lurette/source/common/lustreRun.mli + ** TODO Trouver un moyen d'automatiser des tests - State "TODO" from "" [2013-03-19 Tue 10:35] via lurette ? -faudrait rajouter une option dans lurette qui, en cas de varaibles +en comparant le mode -exec avec le résultat obtenu via ec puis ec2c + +faudrait rajouter une option dans lurette qui, en cas de variables manquantes, genere le programme lutin qui va bien (loop true) plutot que de lancer luciole --auto-stubs + +** TODO Traiter la fleche plus proprement. + - State "TODO" from "" [2013-04-02 Tue 08:33] ** TODO Écrire un test qui mette en jeu exhaustivement tous les operateurs - State "TODO" from "" [2013-03-19 Tue 10:38] -** TODO revoir l'intégration à rif_base et genlex - - State "TODO" from "" [2013-03-19 Tue 10:25] -** TODO Découper un peu les fonctions dans src/lic2soc.ml - - State "TODO" from "" [2013-03-19 Tue 10:26] -le role et le perimetre get_leaf en particulier n'est pas clair. -de plus son code est dupliqué. -file:src/lic2soc.ml -** TODO fonctions externes - - State "TODO" from "" [2013-03-19 Tue 10:33] ** TODO condact, merge - State "TODO" from "" [2013-03-19 Tue 10:33] ** TODO when, current - State "TODO" from "" [2013-03-19 Tue 10:33] -** TODO meta operateurs +** TODO fonctions externes - State "TODO" from "" [2013-03-19 Tue 10:33] +** TODO Découper un peu les fonctions dans src/lic2soc.ml + - State "TODO" from "" [2013-03-19 Tue 10:26] +le role et le perimetre get_leaf en particulier n'est pas clair. +de plus son code est dupliqué. +file:src/lic2soc.ml +** TODO revoir l'intégration à rif_base et genlex + - State "TODO" from "" [2013-03-19 Tue 10:25] * Packages, modeles, etc. ** STARTED Il ne detecte plus les erreurs de type lors d'instanciation de noeuds diff --git a/todo.org_archive b/todo.org_archive index 8b960ccdb932c7c6898fc07a35898a69c7dab5cc..f7c2dc6b69769963f0efeaedd71a001a6489e698 100644 --- a/todo.org_archive +++ b/todo.org_archive @@ -538,6 +538,16 @@ XXX essayer de virer le constructeur Oper qui n'a pas l'air de servir à grand c :ARCHIVE_CATEGORY: lv6 :ARCHIVE_TODO: TODO :END: +* TODO diese et nor + - State "TODO" from "" [2013-03-30 Sat 14:31] + :PROPERTIES: + :ARCHIVE_TIME: 2013-04-02 Tue 10:21 + :ARCHIVE_FILE: ~/lus2lic/todo.org + :ARCHIVE_OLPATH: lus2lic -exec + :ARCHIVE_CATEGORY: lv6 + :ARCHIVE_TODO: TODO + :END: +