diff --git a/bin/sailor.ml b/bin/sailor.ml index bb0bbee..f53da98 100644 --- a/bin/sailor.ml +++ b/bin/sailor.ml @@ -16,30 +16,30 @@ module Thir = IrThir.Thir.Pass module Mir = IrMir.Mir.Pass module Imports = IrMisc.Imports.Pass module MCall = IrMisc.MethodCall.Pass -module MProc = IrMisc.MainProcess.Pass module Mono = IrMisc.Monomorphization.Pass module SetupLoop = IrMisc.SetupLoop.Pass +module MProc = IrMisc.SetupMain.Pass (* error handling *) open Monad.UseMonad(E) -let moduleToIR (m:Mir.out_body SailModule.t) (dump_decl:bool) (verify_ir:bool) : L.llmodule E.t = - let module Env = C.CodegenEnv in - let llc = L.create_context () in - let llm = L.create_module llc m.md.name in - let* decls = Env.get_declarations m llc llm in - if dump_decl then failwith "not done yet"; - - let env = C.CodegenEnv.SailEnv.empty decls in - - Env.DeclEnv.iter_decls (fun name m -> let func = C.Codegen_.methodToIR llc llm m env name in if verify_ir then Llvm_analysis.assert_valid_function func) (Self Method) decls >>= fun () -> - if verify_ir then - match Llvm_analysis.verify_module llm with - | None -> return llm - | Some reason -> E.throw @@ Error.make dummy_pos (Fmt.str "LLVM : %s" reason) - else return llm +let apply_passes (sail_module : SailParser.AstParser.statement SailModule.methods_processes SailModule.t) (comp_mode : Cli.comp_mode) : Mir.out_body SailModule.t E.t = + let open Pass.Progression in + let active_if cond p = if cond then p else Fun.id in + let passes = Fun.id + @> Hir.transform + @> active_if (comp_mode = Loop) SetupLoop.transform + @> Thir.transform + @> MCall.transform + @> Mir.transform + @> Imports.transform + (* @> Mono.transform *) + @> active_if (comp_mode <> Library) MProc.transform + @> finish + in run passes (return sail_module) + let set_target (llm : Llvm.llmodule) (triple:string) : Llvm_target.Target.t * Llvm_target.TargetMachine.t = @@ -135,42 +135,28 @@ let find_file_opt ?(maxdepth = 4) ?(paths = [Filename.current_dir_name]) (f:stri | None -> aux dir 0 ) None paths +let unmarshal_mir file = In_channel.with_open_bin file @@ fun c -> (Marshal.from_channel c : Mir.out_body SailModule.t) +let marshal_mir file m = Out_channel.with_open_bin file @@ fun c -> Marshal.to_channel c m [] let sailor (files: string list) (intermediate:bool) (jit:bool) (noopt:bool) (dump_decl:bool) () (force_comp:bool list) (paths:string list) (comp_mode : Cli.comp_mode) (clang_args: string) (verify_ir:bool) (target_triple:string) = - Llvm.enable_pretty_stacktrace (); - Llvm.install_fatal_error_handler (fun err -> print_string @@ Fmt.str "LLVM ERROR : '%s'\n" err); - - let apply_passes sail_module (comp_mode : Cli.comp_mode) : Mir.out_body SailModule.t E.t = - return sail_module - |> Hir.transform - |> (if comp_mode = Loop then SetupLoop.transform else Fun.id) - |> Thir.transform - |> MCall.transform - |> Mir.transform - |> Imports.transform - |> (if comp_mode <> Library then MProc.transform else Fun.id) - |> Mono.transform - in - - let compile sail_module basepath (comp_mode : Cli.comp_mode) : Mir.out_body SailModule.t E.t = + let compile sail_module basepath (comp_mode : Cli.comp_mode) : unit E.t = let* m = apply_passes sail_module comp_mode in (* Out_channel.with_open_text Filename.(concat basepath m.md.name ^ ".mir.debug") (fun f -> Format.fprintf (Format.formatter_of_out_channel f) "%a" Pp_mir.ppPrintModule m); *) - let+ llm = moduleToIR m dump_decl verify_ir in + let+ llm = C.Codegen_.moduleToIR m dump_decl verify_ir in (* only generate mir file if codegen succeeds *) - Out_channel.with_open_bin Filename.(concat basepath m.md.name ^ Const.mir_file_ext) (fun f -> Marshal.to_channel f m []); + marshal_mir Filename.(concat basepath m.md.name ^ Const.mir_file_ext) m; let tm = set_target llm target_triple in if not noopt && comp_mode <> Library then - begin - let open L.PassManager in - let pm = create () in add_opt_passes pm; - let res = run_module llm pm in - Logs.debug (fun m -> m "pass manager executed, module modified : %b" res); - dispose pm - end + L.PassManager.( + let pm = create () in add_opt_passes pm; + let res = run_module llm pm in + Logs.debug (fun m -> m "pass manager executed, module modified : %b" res); + dispose pm + ) ; if intermediate then L.print_module Filename.(concat basepath m.md.name ^ Const.llvm_ir_ext) llm; @@ -181,28 +167,29 @@ let sailor (files: string list) (intermediate:bool) (jit:bool) (noopt:bool) (dum let imports = object_files @ List.map (fun i -> i.dir ^ i.mname ^ Const.object_file_ext) @@ ImportSet.elements m.imports in let ret = link llm sail_module.md.name basepath imports libs tm ~is_lib:(comp_mode = Library) clang_args in if ret <> 0 then - (Fmt.str "clang couldn't execute properly (error %i)" ret |> failwith) + Fmt.(str_like stderr "clang couldn't execute properly (error %i)" ret) |> failwith end ; - if jit && comp_mode <> Library then execute llm else L.dispose_module llm; - m + if jit && comp_mode <> Library then execute llm else L.dispose_module llm in - let rec process_file f (treated: string list) (compiling: (string*loc) list) comp_mode : (string list * 'a SailModule.t) E.t = + let rec process_file f (treated: string list) (compiling: (string*loc) list) comp_mode : string list E.t = let mname = Filename.(basename f |> remove_extension) in let basepath = Filename.(dirname f) in if List.mem mname treated then - (Logs.debug (fun m -> m "skipping module '%s'" mname); - return (treated,SailModule.emptyModule)) + begin + Logs.debug (fun m -> m "skipping module '%s'" mname); + return treated + end else let treated = mname::treated in let add_imports_decls (curr_env: SailModule.DeclEnv.t ) (imports : ImportSet.t) = ImportSet.fold (fun i -> let file = i.dir ^ i.mname ^ Const.mir_file_ext in Logs.debug (fun m -> m "reading module '%s' from mir file %s" i.mname file); - let slmd : Mir.out_body SailModule.t = In_channel.with_open_bin file Marshal.from_channel in + let slmd = unmarshal_mir file in (* Logs.debug (fun m -> m "decls of import %s : \n %s" i.mname (SailModule.DeclEnv.string_of_env slmd.declEnv)); *) SailModule.DeclEnv.add_import_decls (i, slmd.declEnv) ) @@ -210,7 +197,7 @@ let sailor (files: string list) (intermediate:bool) (jit:bool) (noopt:bool) (dum in let* slmd = P.parse_program f in - let process_imports_and_compile () : (string list * 'a SailModule.t) E.t = + let process_imports_and_compile () : string list E.t = let open MakeOrderedFunctions(ImportCmp) in Logs.info (fun m -> m "======= processing module '%s' =======" slmd.md.name ); Logs.debug (fun m -> m "module hash : %s" (Digest.to_hex slmd.md.hash)); @@ -236,18 +223,13 @@ let sailor (files: string list) (intermediate:bool) (jit:bool) (noopt:bool) (dum let import = fun m -> {i with dir=Filename.(dirname m ^ dir_sep); proc_order=(List.length compiling)} in match find_file_opt source ~paths:(Filename.current_dir_name::paths),find_file_opt mir_name with - | Some s,Some m - when In_channel.with_open_bin m - (fun f -> - let mir : 'a SailModule.t = Marshal.from_channel f in - Digest.(equal mir.md.hash @@ file s) && - List.length force_comp < 2 && - mir.md.version = Const.sailor_version - ) - -> (* mir up-to-date with source -> use mir *) + | Some s,Some m when let mir = unmarshal_mir m in + Digest.(equal mir.md.hash @@ file s) && + List.length force_comp < 2 && + mir.md.version = Const.sailor_version -> (* mir up-to-date with source -> use mir *) return (treated,import m) | None, Some m -> (* mir but no source -> use mir *) - let mir :'a SailModule.t = In_channel.with_open_bin m Marshal.from_channel in + let mir = unmarshal_mir m in E.throw_if (Error.make dummy_pos @@ Printf.sprintf "module %s was compiled with sailor %s, current is %s" mir.md.name mir.md.version Const.sailor_version) (mir.md.version <> Const.sailor_version) @@ -256,38 +238,38 @@ let sailor (files: string list) (intermediate:bool) (jit:bool) (noopt:bool) (dum E.throw @@ Error.make i.loc "import not found" | Some s, _ -> (* source but no mir or mir not up-to-date -> compile *) begin - let+ treated',_mir = process_file s treated ((slmd.md.name,i.loc)::compiling) Cli.Library + let+ treated = process_file s treated ((slmd.md.name,i.loc)::compiling) Cli.Library in - treated',import s + treated,import s end ) treated slmd.imports in let declEnv = add_imports_decls slmd.declEnv imports in - let+ sm = compile {slmd with imports ; declEnv} basepath comp_mode in + let+ _sm = compile {slmd with imports ; declEnv} basepath comp_mode in Logs.info (fun m -> m "======= done processing module '%s' =======\n" slmd.md.name); - treated,sm + treated in let mir_file = Filename.(dirname f ^ dir_sep ^ slmd.md.name ^ Const.mir_file_ext) in (* if mir file exists, check hash, if same hash, no need to compile *) if Sys.file_exists mir_file && (List.length force_comp = 0) then - let mir : 'a SailModule.t = In_channel.with_open_bin mir_file Marshal.from_channel in + let mir = unmarshal_mir mir_file in let* () = E.throw_if (Error.make dummy_pos @@ Printf.sprintf "module %s was compiled with sailor %s, current is %s" mir.md.name mir.md.version Const.sailor_version) (mir.md.version <> Const.sailor_version) in if not @@ Digest.equal mir.md.hash slmd.md.hash then - process_imports_and_compile () + process_imports_and_compile () else begin Logs.app (fun m -> m "'%s' is up-to-date, use '-f' to force compilation" slmd.md.name); - return (treated,mir) + return treated end else - process_imports_and_compile () - in + process_imports_and_compile () + in try - match ListM.fold_left (fun t f -> let+ t,_ = process_file f t [] comp_mode in f::t) [] files with + match ListM.fold_left (fun t f -> let+ t = process_file f t [] comp_mode in f::t) [] files with | Ok treated,_ -> Logs.debug (fun m -> m "files processed : %s " @@ String.concat " " treated) ; `Ok () | Error e,errs -> Error.print_errors (e::errs); @@ -299,12 +281,11 @@ let sailor (files: string list) (intermediate:bool) (jit:bool) (noopt:bool) (dum Logs.warn (fun m -> m "backtrace recording is not turned on, only the exception name will be printed. To print the backtrace, run with 'OCAMLRUNPARAM=b'"); Printexc.to_string e) else Printexc.get_backtrace () in - `Error (false,msg) + `Error (false,msg) let () = - Llvm_all_backends.initialize (); (* init here to show targets from the cli *) - Cmdliner.Cmd.eval (Cli.cmd sailor) |> exit - - - \ No newline at end of file + Llvm_all_backends.initialize (); + L.enable_pretty_stacktrace (); + L.install_fatal_error_handler (fun err -> Logs.err (fun m -> m "LLVM ERROR : '%s'\n" err)); + Cmdliner.Cmd.eval (Cli.cmd sailor) |> exit \ No newline at end of file diff --git a/src/codegen/codegenEnv.ml b/src/codegen/codegenEnv.ml index 52fcd90..cd2527c 100644 --- a/src/codegen/codegenEnv.ml +++ b/src/codegen/codegenEnv.ml @@ -10,7 +10,7 @@ open MakeOrderedFunctions(ImportCmp) module Declarations = struct include SailModule.Declarations type process_decl = unit - type method_decl = {defn : IrMir.Mir.Pass.out_body method_defn ; llval : llvalue ; extern : bool} + type method_decl = {defn : IrMir.AstMir.mir_function method_defn ; llval : llvalue ; extern : bool} type struct_decl = {defn : struct_proto; ty : lltype} type enum_decl = unit end @@ -30,7 +30,6 @@ module SailEnv = VariableDeclEnv (Declarations)( open Declarations - let getLLVMBasicType f t llc llm : lltype = let rec aux = function | Bool -> i1_type llc @@ -80,7 +79,7 @@ let getLLVMBasicType f t llc llm : lltype = match type_by_name llm ("struct." ^ name) with | Some ty -> ty | None -> (let ty = named_struct_type llc ("struct." ^ name) in - struct_set_body ty elts false; ty) + struct_set_body ty elts false; ty) end | Some _ -> failwith "something is broken" | None -> failwith @@ Fmt.str "getLLVMType : %s '%s' not found in module '%s'" (string_of_decl d) name mname @@ -97,21 +96,32 @@ let llvm_proto_of_method_sig (m:method_sig) env llc llm = let method_t = if m.variadic then var_arg_function_type else function_type in declare_function m.name (method_t llvm_rt args_type ) llm +let collect_monos (sm: 'a SailModule.methods_processes SailModule.t) = + let open SailModule.DeclEnv in + let decls = get_own_decls sm.declEnv in + let m = List.filter (fun m -> m.m_proto.generics = []) sm.body.methods in + let s = StructSeq.(decls |> get_decls Struct |> to_seq |> Seq.filter (fun (_,(_,(s:struct_proto))) -> s.generics = []) |> of_seq) in + let e = EnumSeq.(decls |> get_decls Enum |> to_seq |> Seq.filter (fun (_,(_,(e:enum_proto))) -> e.generics = [] ) |> of_seq) in + let t = get_decls Type decls + in m,s,e,t let get_declarations (sm: IrMir.Mir.Pass.out_body SailModule.t) llc llm : DeclEnv.t E.t = let open Monad.MonadSyntax(E) in let open Monad.MonadOperator(E) in + let open SailModule.DeclEnv in + + let methods,structs,enums,types = collect_monos sm in + Logs.debug (fun m -> m "codegen of %i method(s), %i struct(s), %i type(s) and %i enum(s)" - (List.length sm.methods) - SailModule.DeclEnv.(get_own_decls sm.declEnv |> get_decls Struct |> container_length) - SailModule.DeclEnv.(get_own_decls sm.declEnv |> get_decls Type |> container_length) - SailModule.DeclEnv.(get_own_decls sm.declEnv |> get_decls Enum |> container_length) + (List.length methods) + (container_length structs) + (container_length types) + (container_length enums) ); let valueify_method_sig (m:method_sig) : method_sig = - let open Monad.MonadOperator(MonadOption.M) in let value = fun pos -> CompoundType{origin=None;name=(pos,"_value");generic_instances=[];decl_ty=None} in let rtype = m.rtype in (* keep the current type *) let params = List.map (fun (p:param) -> {p with ty=(value p.loc)}) m.params in @@ -120,8 +130,8 @@ let get_declarations (sm: IrMir.Mir.Pass.out_body SailModule.t) llc llm : DeclEn (* because the imports are at the mir stage, we also have to do some codegen for them *) - let load_methods methods is_import env = - ListM.fold_left ( fun d m -> + let load_methods (methods: IrMir.AstMir.mir_function method_defn list) is_import env = + ListM.fold_left ( fun d (m:IrMir.AstMir.mir_function method_defn) -> let extern,proto = if (Either.is_left m.m_body) then (* extern method, all parameters must be of type value *) true,valueify_method_sig m.m_proto @@ -142,13 +152,12 @@ let get_declarations (sm: IrMir.Mir.Pass.out_body SailModule.t) llc llm : DeclEn let module SEnv = MakeFromSequencable(SailModule.DeclEnv.StructSeq) in let module TEnv = MakeFromSequencable(SailModule.DeclEnv.TypeSeq) in - let load_types (sm: 'a SailModule.t) env = + let load_types types env = TEnv.fold (fun acc (id,d) -> DeclEnv.add_decl id d Type acc) - env - SailModule.DeclEnv.(get_own_decls sm.declEnv |> get_decls Type) + env types in - let load_structs (sm: 'a SailModule.t) write_env = + let load_structs structs write_env = SEnv.fold (fun acc (name,(_,defn)) -> let _,f_types = List.split defn.fields in let elts = List.map (fun (_,t,_) -> _getLLVMType sm.declEnv t llc llm) f_types |> Array.of_list in @@ -158,9 +167,7 @@ let get_declarations (sm: IrMir.Mir.Pass.out_body SailModule.t) llc llm : DeclEn struct_set_body ty elts false; ty in DeclEnv.add_decl name {defn;ty} Struct acc - ) - write_env - SailModule.DeclEnv.(get_own_decls sm.declEnv |> get_decls Struct) + ) write_env structs in let sorted_imports = (sm.imports |> ImportSet.elements |> List.sort (fun i1 i2 -> Int.compare i1.proc_order i2.proc_order)) in @@ -169,15 +176,15 @@ let get_declarations (sm: IrMir.Mir.Pass.out_body SailModule.t) llc llm : DeclEn let* decls = ListM.fold_left (fun (e:DeclEnv.t) (i:import) -> Logs.debug (fun m -> m "processing import %s" i.mname); - let (sm: 'a SailModule.t) = - In_channel.with_open_bin (i.dir ^ i.mname ^ Constants.mir_file_ext) Marshal.from_channel + let sm = In_channel.with_open_bin (i.dir ^ i.mname ^ Constants.mir_file_ext) @@ fun c -> (Marshal.from_channel c : IrMir.Mir.Pass.out_body SailModule.t) in (* putting import methods,types,structs and enums into mir env *) let empty_env = DeclEnv.(empty |> set_name i.mname |> replace_imports_with e) in - let+ import_env = load_types sm empty_env >>= load_structs sm >>= load_methods sm.methods true in + let methods,structs,_enums,types = collect_monos sm in + let+ import_env = load_types types empty_env >>= load_structs structs >>= load_methods methods true in (* Logs.debug (fun m -> m "import %s env : %s" i.mname @@ DeclEnv.string_of_env import_env); *) DeclEnv.add_import_decls (i,import_env) e ) DeclEnv.(empty |> set_name sm.md.name) sorted_imports in (* convert own decls, only after loading imports *) - load_types sm decls >>= load_structs sm >>= load_methods sm.methods false + load_types types decls >>= load_structs structs >>= load_methods methods false diff --git a/src/codegen/codegenUtils.ml b/src/codegen/codegenUtils.ml index d2d67ab..6532a0a 100644 --- a/src/codegen/codegenUtils.ml +++ b/src/codegen/codegenUtils.ml @@ -11,8 +11,7 @@ let mangle_method_name (name:string) (mname:string) (args: sailtype list ) : str (* Logs.debug (fun m -> m "renamed %s to %s" name res); *) res - -let getLLVMLiteral (l:literal) (llvm:llvm_args) : llvalue = +let getLLVMLiteral (l:literal) (llvm:llvm_args) : llvalue = match l with | LBool b -> const_int (i1_type llvm.c) (Bool.to_int b) | LInt i -> const_int_of_string (integer_type llvm.c i.size) (Z.to_string i.l) 10 diff --git a/src/codegen/codegen_.ml b/src/codegen/codegen_.ml index b7fc0d1..9b0e257 100644 --- a/src/codegen/codegen_.ml +++ b/src/codegen/codegen_.ml @@ -2,56 +2,53 @@ open CodegenUtils open CodegenEnv open Common open TypesCommon -open Llvm open IrMir - +open Monad.UseMonad(E) +module L = Llvm module E = Error.Logger -open Common.Monad.MonadSyntax(E) -open Common.Monad.MonadFunctions(E) - let get_type (e:AstMir.expression) = snd e.info -let rec eval_l (env:SailEnv.t) (llvm:llvm_args) (x: AstMir.expression) : llvalue = +let rec eval_l (env:SailEnv.t) (llvm:llvm_args) (x: AstMir.expression) : L.llvalue = match x.exp with | Variable x -> let _,v = match (SailEnv.get_var x env) with Some (_,n) -> n | None -> failwith @@ Fmt.str "var '%s' not found" x |> snd in v | Deref x -> eval_r env llvm x | ArrayRead (array_exp, index_exp) -> let array_val = eval_l env llvm array_exp in let index = eval_r env llvm index_exp in - let llvm_array = build_in_bounds_gep array_val [|(const_int (i64_type llvm.c) 0 ); index|] "" llvm.b in + let llvm_array = L.build_in_bounds_gep array_val [|L.(const_int (i64_type llvm.c) 0 ); index|] "" llvm.b in llvm_array | StructRead ((_,mname),struct_exp,(_,field)) -> let st = eval_l env llvm struct_exp in - let st_type_name = match struct_name (type_of st |> subtypes).(0) with + let st_type_name = match L.struct_name L.(type_of st |> subtypes).(0) with | None -> failwith "problem with structure type" | Some name -> String.split_on_char '.' name |> (List.nth |> Fun.flip) 1 in let fields = (SailEnv.get_decl st_type_name (Specific (mname,Struct)) env |> Option.get).defn.fields in let _,_,idx = List.assoc field fields in - build_struct_gep st idx "" llvm.b + L.build_struct_gep st idx "" llvm.b | StructAlloc (_,(_,name),fields) -> let _,fieldlist = fields |> List.split in - let strct_ty = match type_by_name llvm.m ("struct." ^ name) with + let strct_ty = match L.type_by_name llvm.m ("struct." ^ name) with | Some s -> s | None -> "unknown structure : " ^ ("struct." ^ name) |> failwith in - let struct_v = build_alloca strct_ty "" llvm.b in + let struct_v = L.build_alloca strct_ty "" llvm.b in List.iteri ( fun i f -> let v = eval_r env llvm f in - let v_f = build_struct_gep struct_v i "" llvm.b in - build_store v v_f llvm.b |> ignore + let v_f = L.build_struct_gep struct_v i "" llvm.b in + L.build_store v v_f llvm.b |> ignore ) fieldlist; struct_v | _ -> failwith "unexpected rvalue for codegen" -and eval_r (env:SailEnv.t) (llvm:llvm_args) (x:AstMir.expression) : llvalue = +and eval_r (env:SailEnv.t) (llvm:llvm_args) (x:AstMir.expression) : L.llvalue = let ty = get_type x in match x.exp with - | Variable _ | StructRead _ | ArrayRead _ | StructAlloc _ -> let v = eval_l env llvm x in build_load v "" llvm.b + | Variable _ | StructRead _ | ArrayRead _ | StructAlloc _ -> let v = eval_l env llvm x in L.build_load v "" llvm.b | Literal l -> getLLVMLiteral l llvm | UnOp (op,e) -> let l = eval_r env llvm e in unary op (ty_of_alias ty (snd env),l) llvm.b @@ -60,26 +57,26 @@ and eval_r (env:SailEnv.t) (llvm:llvm_args) (x:AstMir.expression) : llvalue = and l2 = eval_r env llvm e2 in binary op (ty_of_alias ty (snd env)) l1 l2 llvm.b | Ref (_,e) -> eval_l env llvm e - | Deref e -> let v = eval_l env llvm e in build_load v "" llvm.b + | Deref e -> let v = eval_l env llvm e in L.build_load v "" llvm.b | ArrayStatic elements -> begin let array_values = List.map (eval_r env llvm) elements in - let ty = List.hd array_values |> type_of in + let ty = List.hd array_values |> L.type_of in let array_values = Array.of_list array_values in - let array_type = array_type ty (List.length elements) in - let array = const_array array_type array_values in - let array = define_global "const_array" array llvm.m in - set_linkage Linkage.Private array; - set_unnamed_addr true array; - set_global_constant true array; - build_load array "" llvm.b + let array_type = L.array_type ty (List.length elements) in + let array = L.const_array array_type array_values in + let array = L.define_global "const_array" array llvm.m in + L.set_linkage L.Linkage.Private array; + L.set_unnamed_addr true array; + L.set_global_constant true array; + L.build_load array "" llvm.b end | EnumAlloc _ -> failwith "enum allocation unimplemented" | _ -> failwith "problem with thir" -and construct_call (name:string) ((_,mname):l_str) (args:AstMir.expression list) (env:SailEnv.t) (llvm:llvm_args) : llvalue = +and construct_call (name:string) ((_,mname):l_str) (args:AstMir.expression list) (env:SailEnv.t) (llvm:llvm_args) : L.llvalue = let args_type,llargs = List.map (fun arg -> get_type arg,eval_r env llvm arg) args |> List.split in (* let mname = mangle_method_name name origin.mname args_type in *) @@ -100,63 +97,63 @@ and construct_call (name:string) ((_,mname):l_str) (args:AstMir.expression list) List.map2 (fun t v -> let builder = match ty_of_alias t (snd env) with - | Bool | Int _ | Char -> build_zext - | Float -> build_bitcast - | _ -> build_ptrtoint + | Bool | Int _ | Char -> L.build_zext + | Float -> L.build_bitcast + | _ -> L.build_ptrtoint in - builder v (i64_type llvm.c) "" llvm.b + builder v (L.i64_type llvm.c) "" llvm.b ) args_type llargs else llargs in - build_call llval (Array.of_list args) "" llvm.b + L.build_call llval (Array.of_list args) "" llvm.b open AstMir -let cfgToIR (proto:llvalue) (decls,cfg: Mir.Pass.out_body) (llvm:llvm_args) (env :SailEnv.t) : unit = +let cfgToIR (proto:L.llvalue) (decls,cfg: mir_function) (llvm:llvm_args) (env :SailEnv.t) : unit = let declare_var (mut:bool) (name:string) (ty:sailtype) (exp:AstMir.expression option) (env:SailEnv.t) : SailEnv.t E.t= let _ = mut in (* todo manage mutable types *) - let entry_b = entry_block proto |> instr_begin |> builder_at llvm.c in + let entry_b = L.(entry_block proto |> instr_begin |> builder_at llvm.c) in let v = match exp with | Some e -> let t = get_type e and v = eval_r env llvm e in - let x = build_alloca (getLLVMType (snd env) t llvm.c llvm.m) name entry_b in - build_store v x llvm.b |> ignore; x + let x = L.build_alloca (getLLVMType (snd env) t llvm.c llvm.m) name entry_b in + L.build_store v x llvm.b |> ignore; x | None -> let t' = getLLVMType (snd env) ty llvm.c llvm.m in - build_alloca t' name entry_b + L.build_alloca t' name entry_b in SailEnv.declare_var name (dummy_pos,(mut,v)) env and assign_var (target:expression) (exp:expression) (env:SailEnv.t) = let lvalue = eval_l env llvm target in let rvalue = eval_r env llvm exp in - build_store rvalue lvalue llvm.b |> ignore + L.build_store rvalue lvalue llvm.b |> ignore in - let rec aux (lbl:label) (llvm_bbs : llbasicblock BlockMap.t) (env:SailEnv.t) : llbasicblock BlockMap.t = - match BlockMap.find_opt lbl llvm_bbs with - | None -> + let rec aux (lbl:label) (llvm_bbs : L.llbasicblock BlockMap.t) (env:SailEnv.t) : L.llbasicblock BlockMap.t = + if BlockMap.mem lbl llvm_bbs then llvm_bbs (* already treated, nothing to do *) + else begin let bb = BlockMap.find lbl cfg.blocks and bb_name = (Printf.sprintf "lbl%i" lbl) in - let llvm_bb = append_block llvm.c bb_name proto in + let llvm_bb = L.append_block llvm.c bb_name proto in let llvm_bbs = BlockMap.add lbl llvm_bb llvm_bbs in - position_at_end llvm_bb llvm.b; + L.position_at_end llvm_bb llvm.b; List.iter (fun x -> assign_var x.target x.expression env) bb.assignments; match bb.terminator with | Some (Return e) -> let ret = match e with - | Some r -> let v = eval_r env llvm r in build_ret v - | None -> build_ret_void + | Some r -> let v = eval_r env llvm r in L.build_ret v + | None -> L.build_ret_void in ret llvm.b |> ignore; llvm_bbs | Some (Goto lbl) -> let llvm_bbs = aux lbl llvm_bbs env in - position_at_end llvm_bb llvm.b; - build_br (BlockMap.find lbl llvm_bbs) llvm.b |> ignore; + L.position_at_end llvm_bb llvm.b; + L.build_br (BlockMap.find lbl llvm_bbs) llvm.b |> ignore; llvm_bbs @@ -164,54 +161,52 @@ let cfgToIR (proto:llvalue) (decls,cfg: Mir.Pass.out_body) (llvm:llvm_args) (env let c = construct_call f.id f.origin f.params env llvm in begin match f.target with - | Some id -> build_store c (let _,v = SailEnv.get_var id env |> Option.get |> snd in v) llvm.b |> ignore + | Some id -> L.build_store c (let _,v = SailEnv.get_var id env |> Option.get |> snd in v) llvm.b |> ignore | None -> () end; let llvm_bbs = aux f.next llvm_bbs env in - position_at_end llvm_bb llvm.b; - build_br (BlockMap.find f.next llvm_bbs) llvm.b |> ignore; + L.position_at_end llvm_bb llvm.b; + L.build_br (BlockMap.find f.next llvm_bbs) llvm.b |> ignore; llvm_bbs | Some (SwitchInt (e,cases,default)) -> let sw_val = eval_r env llvm e in - let sw_val = build_intcast sw_val (i32_type llvm.c) "" llvm.b (* for condition, expression val will be bool *) + let sw_val = L.build_intcast sw_val (L.i32_type llvm.c) "" llvm.b (* for condition, expression val will be bool *) and llvm_bbs = aux default llvm_bbs env in - position_at_end llvm_bb llvm.b; - let sw = build_switch sw_val (BlockMap.find default llvm_bbs) (List.length cases) llvm.b in + L.position_at_end llvm_bb llvm.b; + let sw = L.build_switch sw_val (BlockMap.find default llvm_bbs) (List.length cases) llvm.b in List.fold_left ( fun bm (n,lbl) -> - let n = const_int (i32_type llvm.c) n + let n = L.const_int (L.i32_type llvm.c) n and bm = aux lbl bm env - in add_case sw n (BlockMap.find lbl bm); + in L.add_case sw n (BlockMap.find lbl bm); bm ) llvm_bbs cases | None -> failwith "no terminator : mir is broken" (* can't happen *) | Some Break -> failwith "no break should be there" end - - | Some _ -> llvm_bbs (* already treated, nothing to do *) in ( let+ env = ListM.fold_left (fun e (d:declaration) -> declare_var d.mut d.id d.varType None e) env decls in - let init_bb = insertion_block llvm.b + let init_bb = L.insertion_block llvm.b and llvm_bbs = aux cfg.input BlockMap.empty env in - position_at_end init_bb llvm.b; - build_br (BlockMap.find cfg.input llvm_bbs) llvm.b + L.position_at_end init_bb llvm.b; + L.build_br (BlockMap.find cfg.input llvm_bbs) llvm.b ) |> ignore -let methodToIR (llc:llcontext) (llm:llmodule) (decl:Declarations.method_decl) (env:SailEnv.t) (name : string) : llvalue = +let methodToIR (llc:L.llcontext) (llm:L.llmodule) (decl:Declarations.method_decl) (env:SailEnv.t) (name : string) : L.llvalue = match Either.find_right decl.defn.m_body with | None -> decl.llval (* extern method *) | Some b -> Logs.info (fun m -> m "codegen of %s" name); - let builder = builder llc in - let llvm = {b=builder; c=llc ; m = llm; layout=Llvm_target.DataLayout.of_string (data_layout llm)} in + let builder = L.builder llc in + let llvm = {b=builder; c=llc ; m = llm; layout=Llvm_target.DataLayout.of_string (L.data_layout llm)} in - if block_begin decl.llval <> At_end decl.llval then failwith ("redefinition of function " ^ name); + if L.block_begin decl.llval <> At_end decl.llval then failwith ("redefinition of function " ^ name); - let bb = append_block llvm.c "" decl.llval in - position_at_end bb llvm.b; + let bb = L.append_block llvm.c "" decl.llval in + L.position_at_end bb llvm.b; let args = toLLVMArgs decl.defn.m_proto.params (snd env) llvm in @@ -219,12 +214,28 @@ let methodToIR (llc:llcontext) (llm:llmodule) (decl:Declarations.method_decl) (e fun env (m,_,v) -> ( let* env in - let+ new_env = SailEnv.declare_var (value_name v) (dummy_pos,(m,v)) env in + let+ new_env = SailEnv.declare_var (L.value_name v) (dummy_pos,(m,v)) env in new_env ),v ) (E.pure env) args - in Array.iteri (fun i arg -> build_store (param decl.llval i) arg llvm.b |> ignore ) args; + in Array.iteri (fun i arg -> L.build_store (L.param decl.llval i) arg llvm.b |> ignore ) args; (let+ new_env in cfgToIR decl.llval b llvm new_env) |> ignore; decl.llval +let moduleToIR (m:Mir.Pass.out_body SailModule.t) (dump_decl:bool) (verify_ir:bool) : L.llmodule E.t = + let llc = L.create_context () in + let llm = L.create_module llc m.md.name in + let* decls = get_declarations m llc llm in + + if dump_decl then failwith "not done yet"; + + let env = SailEnv.empty decls in + + DeclEnv.iter_decls (fun name m -> let func = methodToIR llc llm m env name in if verify_ir then Llvm_analysis.assert_valid_function func) (Self Method) decls >>= fun () -> + if verify_ir then + match Llvm_analysis.verify_module llm with + | None -> return llm + | Some reason -> E.throw @@ Error.make dummy_pos (Fmt.str "LLVM : %s" reason) + else return llm + \ No newline at end of file diff --git a/src/common/monadic/monad.ml b/src/common/monadic/monad.ml index 0d03317..9b322a0 100644 --- a/src/common/monadic/monad.ml +++ b/src/common/monadic/monad.ml @@ -228,6 +228,12 @@ module MonadFunctions (M : Monad) = struct | [] -> return x | h :: t -> f h x >>= fold_right f t + let rec fold_right2 (f : 'a -> 'b -> 'c -> 'c M.t) (l1 : 'a list) (l2 : 'b list) (x : 'c) : 'c M.t = + match l1,l2 with + | [],[] -> return x + | h1 :: t1,h2 :: t2 -> f h1 h2 x >>= fold_right2 f t1 t2 + | _ -> raise (Invalid_argument "ListM.fold_right2") + let sequence (l : 'a M.t list) : 'a list M.t = map Fun.id l end diff --git a/src/common/pass.ml b/src/common/pass.ml index aaa491d..d077855 100644 --- a/src/common/pass.ml +++ b/src/common/pass.ml @@ -15,6 +15,7 @@ module type Pass = sig val transform : input -> output end + module type ModulePass = sig type in_body type out_body @@ -22,6 +23,8 @@ module type ModulePass = sig include Pass with type input := in_body SailModule.t and type output := out_body SailModule.t Logger.t end + + module type S = sig type in_body type out_body @@ -30,60 +33,31 @@ end -(* module type AnalysisOutPass = sig - type body - type out_anl +module Progression = struct + type (_,_) t = + | Transform : ('a -> 'b) * ('b,'c) t -> ('a, 'c) t + | Done : ('a,'a) t - include Pass with type input := body SailModule.t and type output := out_anl Logger.t -end + let run p i = + let rec aux : type a b. (a,b) t -> a -> b = fun pipeline input -> + match pipeline with + | Done -> input + | Transform (f,tail) -> aux tail (f input) + in aux p i -module type SOut = sig - type body - type out_anl - include Pass with type input := body SailModule.t Logger.t and type output := (out_anl * body SailModule.t) Logger.t + let finish = Done + + let (@>) f pipeline = Transform (f,pipeline) end -module type AnalysisInPass = sig - type body - type in_anl - - include Pass with type input = in_anl * body SailModule.t and type output := body SailModule.t Logger.t -end - -module type SIn = sig - type body - type in_anl - - include Pass with type input := (in_anl * body SailModule.t) Logger.t and type output := body SailModule.t Logger.t -end -module MakeAnlIn (T: AnalysisInPass) : SIn with type body := T.body and type in_anl := T.in_anl = +module Make (T: ModulePass) : S with type in_body = T.in_body and type out_body = T.out_body = struct let name = T.name - let transform (m: (T.in_anl * T.body SailModule.t) Logger.t) : T.body SailModule.t Logger.t = - let* m = m |> Logger.fail in - Logs.info (fun m -> m "Lowering using analysis to '%s'" name); - T.transform m -end - -module MakeAnlOut (T: AnalysisOutPass) : SOut with type body := T.body and type out_anl := T.out_anl = -struct - let name = T.name - - let transform (m: T.body SailModule.t Logger.t) : (T.out_anl * T.body SailModule.t) Logger.t = - let* m = m |> Logger.fail in - Logs.info (fun m -> m "Analysis : '%s'" name); - let+ out = T.transform m in - out,m -end *) - - -module Make (T: ModulePass) : S with type in_body := T.in_body and type out_body := T.out_body = -struct - let name = T.name - + type in_body = T.in_body + type out_body = T.out_body let transform (sm: T.in_body SailModule.t Logger.t) : T.out_body SailModule.t Logger.t = let* sm = sm |> Logger.fail in Logs.info (fun m -> m "Lowering module '%s' to '%s'" sm.md.name name); @@ -105,6 +79,27 @@ type 'a function_type = } +let function_type_of_process p = + { + name=p.p_name; + body=p.p_body; + pos=p.p_pos; + ret=None; + bt=BProcess; + generics=p.p_generics + } + +let function_type_of_method m = + Either.map_right (fun b -> { + name=m.m_proto.name; + body=b; + pos=m.m_proto.pos; + ret=m.m_proto.rtype; + bt=BMethod; + generics=m.m_proto.generics + }) m.m_body + + module MakeFunctionPass (V : Env.Variable) (T: @@ -112,62 +107,49 @@ module MakeFunctionPass val name : string type in_body type out_body - val lower_function : in_body function_type -> SailModule.SailEnv(V).t -> in_body SailModule.t -> (out_body * SailModule.SailEnv(V).D.t) Logger.t - val preprocess : in_body SailModule.t -> in_body SailModule.t Logger.t + val lower_function : in_body function_type -> SailModule.SailEnv(V).t -> in_body SailModule.methods_processes SailModule.t -> (out_body * SailModule.SailEnv(V).D.t) Logger.t + val preprocess : in_body SailModule.methods_processes SailModule.t -> in_body SailModule.methods_processes SailModule.t Logger.t end) - : S with type in_body := T.in_body and type out_body = T.out_body = + : S with type in_body := T.in_body SailModule.methods_processes and type out_body = T.out_body SailModule.methods_processes = struct let name = T.name - type out_body = T.out_body + type out_body = T.out_body SailModule.methods_processes module VEnv = SailModule.SailEnv(V) - let lower_method (m:T.in_body method_defn) (sm : T.in_body SailModule.t) : (VEnv.D.t * T.out_body method_defn) Logger.t = + let lower_method (m:T.in_body method_defn) (sm : T.in_body SailModule.methods_processes SailModule.t) : (VEnv.D.t * T.out_body method_defn) Logger.t = let start_env = VEnv.get_start_env sm.declEnv m.m_proto.params in - match m.m_body with - | Right b -> - let decl = { - name=m.m_proto.name; - body=b; - pos=m.m_proto.pos; - ret=m.m_proto.rtype; - bt=BMethod; - generics=m.m_proto.generics - } in + let decl = function_type_of_method m in + match decl with + | Right f -> let* ve = start_env in - let+ b,d = T.lower_function decl ve sm in + let+ b,d = T.lower_function f ve sm in d,{ m with m_body=Either.right b } | Left x -> Logger.pure (sm.declEnv,{ m with m_body = Left x}) - let lower_process (p: T.in_body process_defn) (sm : T.in_body SailModule.t) : (VEnv.D.t * T.out_body process_defn ) Logger.t = + let lower_process (p: T.in_body process_defn) (sm : T.in_body SailModule.methods_processes SailModule.t) : (VEnv.D.t * T.out_body process_defn ) Logger.t = let start_env = VEnv.get_start_env sm.declEnv (fst p.p_interface) in - let decl = { - name=p.p_name; - body=p.p_body; - pos=p.p_pos; - ret=None; - bt=BProcess; - generics=p.p_generics - } in + let decl = function_type_of_process p in let* ve = start_env in let+ p_body,d = T.lower_function decl ve sm in d,{ p with p_body} - let transform (sm :T.in_body SailModule.t Logger.t) : T.out_body SailModule.t Logger.t = + let transform (sm :T.in_body SailModule.methods_processes SailModule.t Logger.t) : T.out_body SailModule.methods_processes SailModule.t Logger.t = let* sm = sm >>= T.preprocess in Logs.info (fun m -> m "Lowering module '%s' to '%s'" sm.md.name name); ( - let* declEnv,methods = ListM.fold_left_map (fun declEnv methd -> lower_method methd {sm with declEnv}) sm.declEnv sm.methods |> Logger.recover (sm.declEnv,[]) in - let+ declEnv,processes = ListM.fold_left_map (fun declEnv proccess -> lower_process proccess {sm with declEnv}) declEnv sm.processes |> Logger.recover (sm.declEnv,[]) in - - { sm with - processes; - methods; - declEnv - } + let* declEnv,methods = ListM.fold_left_map + (fun declEnv methd -> lower_method methd {sm with declEnv}) + sm.declEnv sm.body.methods |> Logger.recover (sm.declEnv,[]) + in + let+ declEnv,processes = ListM.fold_left_map + (fun declEnv proccess -> lower_process proccess {sm with declEnv}) + declEnv sm.body.processes |> Logger.recover (sm.declEnv,[]) in + + { sm with body=SailModule.{processes; methods} ; declEnv } ) |> Logger.fail end \ No newline at end of file diff --git a/src/common/ppCommon.ml b/src/common/ppCommon.ml index 6df2308..6bf3fbc 100644 --- a/src/common/ppCommon.ml +++ b/src/common/ppCommon.ml @@ -76,7 +76,6 @@ let pp_process (pp_process_body : int -> formatter -> 'a -> unit) (pf : formatte let pp_program (pp_method_body : int -> formatter -> (tag * tag list, 'a) Either.t -> unit) (pp_process_body : int -> formatter -> 'a -> unit) -((pf : formatter) : formatter) (p : 'a SailModule.t) = - List.iter (pp_method pp_method_body pf) p.methods; - List.iter (pp_process pp_process_body pf) p.processes - \ No newline at end of file +((pf : formatter) : formatter) (p : 'a SailModule.methods_processes SailModule.t) = + List.iter (pp_method pp_method_body pf) p.body.methods; + List.iter (pp_process pp_process_body pf) p.body.processes \ No newline at end of file diff --git a/src/common/sailModule.ml b/src/common/sailModule.ml index f1b6da5..eb5fbcf 100644 --- a/src/common/sailModule.ml +++ b/src/common/sailModule.ml @@ -1,4 +1,5 @@ open TypesCommon +module E = Error.Logger module Declarations = struct type process_decl = loc * function_proto @@ -12,31 +13,23 @@ module DeclEnv = Env.DeclarationsEnv(Declarations) module SailEnv = Env.VariableDeclEnv(Declarations) + +type 'a methods_processes = {methods : 'a method_defn list ; processes : 'a process_defn list; } + type 'a t = { declEnv: DeclEnv.t; - methods : 'a method_defn list ; - processes : 'a process_defn list; builtins : method_sig list ; + body : 'a; imports : ImportSet.t; md : metadata; } -type moduleSignature = unit t - -let signatureOfModule m = -{ - m with - methods = List.map (fun m -> {m with m_body=Either.right ()}) m.methods; - processes = List.map (fun p-> {p with p_body=()}) m.processes -} - -let emptyModule = +let emptyModule empty_content = { declEnv = DeclEnv.empty; - methods = []; - processes = []; builtins = []; + body = empty_content; imports = ImportSet.empty; md = { name = String.empty; @@ -56,11 +49,11 @@ let method_decl_of_defn (d : 'a method_defn) : Declarations.method_decl = ((pos,name),{ret;args;generics;variadic}) -open Monad.MonadSyntax(Error.Logger) -let method_of_process (m : 'a t) (name:string) : 'a method_defn Error.Logger.t = - let+ p = Error.Logger.throw_if_none +let method_of_process (m : 'a methods_processes t) (name:string) : 'a method_defn E.t = + let open Monad.MonadSyntax(E) in + let+ p = E.throw_if_none (Error.make dummy_pos @@ "module '" ^ m.md.name ^ "' : no '" ^ name ^ "' process found") - (List.find_opt (fun p -> p.p_name = name) m.processes) + (List.find_opt (fun p -> p.p_name = name) m.body.processes) in let m_proto = {pos=p.p_pos; name=String.lowercase_ascii p.p_name; generics = p.p_generics; params = fst p.p_interface; variadic=false; rtype=None} and m_body = Either.right p.p_body in diff --git a/src/ir/misc/dune b/src/ir/misc/dune index 1cd6d98..7360fb6 100644 --- a/src/ir/misc/dune +++ b/src/ir/misc/dune @@ -1,3 +1,4 @@ +(include_subdirs unqualified) (library (libraries irThir irMir common) (name irMisc)) diff --git a/src/ir/misc/imports.ml b/src/ir/misc/imports.ml index 728eea6..ea228b4 100644 --- a/src/ir/misc/imports.ml +++ b/src/ir/misc/imports.ml @@ -6,31 +6,30 @@ module E = Common.Error open Monad.MonadSyntax(E.Logger) open Monad.MonadFunctions(E.Logger) +let read_imports (imports : ImportSet.t) : (string * Mir.Pass.out_body SailModule.t) list = +List.map (fun i -> + Logs.debug (fun m -> m "reading mir for import '%s' (%s)" i.mname i.dir); + i.dir,In_channel.with_open_bin (i.dir ^ i.mname ^ Constants.mir_file_ext) @@ fun c -> (Marshal.from_channel c : Mir.Pass.out_body SailModule.t) +) (ImportSet.elements imports) module Pass = Pass.Make( struct - let name = "Resolve imports" - type in_body = Mir.Pass.out_body + let name = "Get imported modules imports" + type in_body = AstMir.mir_function SailModule.methods_processes type out_body = in_body - let read_imports (imports : ImportSet.t) : (string * in_body SailModule.t) list = - List.map (fun i -> - Logs.debug (fun m -> m "reading mir for import '%s' (%s)" i.mname i.dir); - i.dir,In_channel.with_open_bin (i.dir ^ i.mname ^ Constants.mir_file_ext) Marshal.from_channel - ) (ImportSet.elements imports) - - let set_fcall_source (m:in_body SailModule.t) : in_body SailModule.t E.Logger.t = + let set_fcall_source (m:in_body SailModule.t) : out_body SailModule.t E.Logger.t = let imports = read_imports m.imports in let+ libs,methods = ListM.fold_left_map (fun libs f -> match f.m_body with - | Right b -> - (libs,{m_proto={f.m_proto with name = "_" ^ m.md.name ^"_" ^ f.m_proto.name}; m_body=Either.Right b}) |> E.Logger.pure + | Right _ -> + (libs,f) |> E.Logger.pure | Left (realname,lib) -> (* extern method, give it its realname for codegen *) let m_proto = {f.m_proto with name=realname} in let libs = FieldSet.add_seq (List.to_seq lib) libs in return (libs,{f with m_proto}) (* add lib required by ffi *) - ) FieldSet.empty m.methods + ) FieldSet.empty m.body.methods in (* the imports of my imports are my imports and same goes for the libs *) let libs,imports = List.fold_left ( @@ -46,7 +45,7 @@ module Pass = Pass.Make( struct let imports = ImportSet.(diff m.imports imports |> union imports ) in - {m with methods ; imports; md={m.md with libs}} + {m with body = SailModule.{methods ; processes=m.body.processes}; imports; md={m.md with libs}} let transform (smdl : in_body SailModule.t) : out_body SailModule.t E.Logger.t = Logs.debug (fun m -> m "imports : %s" (String.concat " " (List.map (fun i -> i.mname) (ImportSet.elements smdl.imports)))); diff --git a/src/ir/misc/methodCall.ml b/src/ir/misc/methodCall.ml index 813d1f1..d18cfea 100644 --- a/src/ir/misc/methodCall.ml +++ b/src/ir/misc/methodCall.ml @@ -43,17 +43,16 @@ module ECSW = struct let get_decl id ty = ECS.bind ECS.get (fun e -> THIREnv.get_decl id ty e |> ECS.pure) |> lift end -let get_hint id env = - MonadOption.M.bind (List.nth_opt (THIREnv.get_closest id env) 0) (fun id -> Some (None,Printf.sprintf "Did you mean %s ?" id)) +let get_hint id env = Option.bind (List.nth_opt (THIREnv.get_closest id env) 0) (fun id -> Some (None,Printf.sprintf "Did you mean %s ?" id)) module Pass = Pass.MakeFunctionPass(V) ( struct - let name = "Extract method call out of expressions" + let name = "Extract method call out of expressions (fixme : should be in hir but requires type inference)" - type in_body = IrThir.Thir.Pass.out_body + type in_body = ThirUtils.statement type out_body = in_body open MonadFunctions(ECSW) @@ -91,7 +90,7 @@ module Pass = Pass.MakeFunctionPass(V) let+ m = ListM.map (pairMap2 aux) m in {info; exp=StructAlloc (o,id, m)} | EnumAlloc (id, el) -> let+ el = ListM.map aux el in {info;exp=EnumAlloc (id, el)} - | MethodCall ((l_id,id), ((_,mname) as origin), el) -> + | MethodCall ((l_id,id), ((_,mname) as origin), el) -> (* THIS IS THE PROBLEM : WE NEED TO KNOW THE RETURN TYPE !! *) let* m = ECSW.get_decl id (Specific (mname,Method)) in match m with | Some (_proto_loc,proto) -> @@ -111,11 +110,10 @@ module Pass = Pass.MakeFunctionPass(V) in aux e - let lower_function (f : in_body function_type) env _ : (out_body * THIREnv.D.t) E.t = + let lower_function (f : in_body function_type) env _ : (out_body* THIREnv.D.t) E.t = let open MonadSyntax(ECS) in let open MonadOperator(ECS) in - - let rec aux (s : statement) : out_body ECS.t = + let rec aux (s : statement) : statement ECS.t = let buildSeq s1 s2 = {info=dummy_pos; stmt = Seq (s1, s2)} in let buildStmt stmt = {info=dummy_pos;stmt} in diff --git a/src/ir/misc/monomorphization.ml b/src/ir/misc/monomorphization.ml deleted file mode 100644 index 5bfc9bf..0000000 --- a/src/ir/misc/monomorphization.ml +++ /dev/null @@ -1,18 +0,0 @@ -open Common - -module E = Common.Error -open Monad.MonadSyntax(E.Logger) - - -module Pass = Pass.Make( -struct - let name = "Monomorphization (todo)" - type in_body = IrMir.Mir.Pass.out_body - type out_body = in_body - - - let transform (smdl : in_body SailModule.t) : out_body SailModule.t E.Logger.t = - (* todo *) - return smdl -end -) diff --git a/src/ir/misc/monomorphization/monomorphization.ml b/src/ir/misc/monomorphization/monomorphization.ml new file mode 100644 index 0000000..73413e2 --- /dev/null +++ b/src/ir/misc/monomorphization/monomorphization.ml @@ -0,0 +1,262 @@ +open Common +open Monad +open TypesCommon +module E = Common.Error +open Monad.MonadSyntax (E.Logger) +open IrMir.AstMir +open MonomorphizationMonad +module M = MonoMonad +open MonomorphizationUtils + +open MonadSyntax(M) +open MonadOperator(M) +open MonadFunctions(M) + + +module Pass = Pass.Make (struct + let name = "Monomorphization" + + type in_body = MonomorphizationUtils.in_body SailModule.methods_processes + type out_body = in_body + + module Env = SailModule.DeclEnv + + let mono_fun (f : sailor_function) (sm : in_body SailModule.t) : unit M.t = + + let mono_exp (e : expression) : sailtype M.t = + let rec aux (e : expression) : sailtype M.t = + match e.exp with + | Variable s -> M.get_var s >>| fun v -> (v |> Option.get |> snd).ty + + | Literal l -> return (sailtype_of_literal l) + + | ArrayRead (e, idx) -> + begin + let* t = aux e in + match t with + | ArrayType (t, _) -> + let+ idx_t = aux idx in + let _ = resolveType idx_t (Int 32) [] [] in + t + | _ -> failwith "cannot happen" + end + | UnOp (_, e) -> aux e + + | BinOp (_, e1, e2) -> + let* t1 = aux e1 in + let+ t2 = aux e2 in + let _ = resolveType t1 t2 [] [] in + t1 + + | Ref (m, e) -> + let+ t = aux e in + RefType (t, m) + + | Deref e -> ( + let+ t = aux e in + match t with + | RefType _ -> t + | _ -> failwith "cannot happen" + ) + + | ArrayStatic (e :: h) -> + let* t = aux e in + let+ t = + ListM.fold_left (fun last_t e -> + let+ next_t = aux e in + let _ = resolveType next_t last_t [] [] in + next_t + ) t h + in + ArrayType (t, List.length (e :: h)) + + | ArrayStatic [] -> failwith "error : empty array" + | StructAlloc (_, _, _) -> failwith "todo: struct alloc" + | EnumAlloc (_, _) -> failwith "todo: enum alloc" + | StructRead (_, _, _) -> failwith "todo: struct read" + | MethodCall _ -> failwith "no method call at this stage" + in + aux e + in + + let construct_call (calle : string) (el : expression list) : sailtype option M.t = + (* we construct the types of the args (and collect extra new calls) *) + Logs.debug (fun m -> m "contructing call to %s from %s" calle f.m_proto.name); + let* monos = M.get_monos and* funs = M.get_funs in + Logs.debug (fun m -> m "current monos : %s" (String.concat ";" (List.map ( fun (g,(t:sailor_args)) -> g ^ " -> " ^ (List.map (fun (id,t) -> "(" ^ id ^ "," ^ string_of_sailtype (Some t) ^ ")") t |> String.concat "," )) monos))); + Logs.debug (fun m -> m "current funs : %s" (FieldMap.fold (fun name _ acc -> Fmt.str "%s;%s" name acc) funs "")); + + + let* call_args = + ListM.fold_left + (fun l e -> + Logs.debug (fun m -> m "analyze param expression"); + let* t = mono_exp e in + Logs.debug (fun m -> m "param is %s " @@ string_of_sailtype @@ Some t); + return (t :: l) + ) + [] el + in + + (*don't do anything if the function is already added *) + let mname = mangle_method_name calle call_args in + let* funs = M.get_funs in + match FieldMap.find_opt mname funs with + | Some f -> + Logs.debug (fun m -> m "function %s already discovered, skipping" calle); + return f.methd.m_proto.rtype + | None -> + begin + let* f = find_callable calle sm |> M.lift in + Logs.debug (fun m -> m "found call to %s, variadic : %b" f.m_proto.name f.m_proto.variadic ); + match f.m_body with + | Right _ -> + (* process and method + + we make sure they correspond to what the callable wants + if the callable is generic we check all the generic types are present at least once + + we build a (string*sailtype) list of generic to type correspondance + if the generic is not found in the list, we add it with the corresponding type + if the generic already exists with the same type as the new one, we are good else we fail + *) + let* resolved_generics = check_args call_args f |> M.lift in + List.iter (fun (n, t) -> Logs.debug (fun m -> m "resolved %s to %s " n (string_of_sailtype (Some t)))) resolved_generics; + + let* () = M.push_monos calle resolved_generics in + + let* rtype = + match f.m_proto.rtype with + | Some t -> Logs.warn (fun m -> m "TYPE BEFORE : %s" (string_of_sailtype (Some t))); let+ t = (degenerifyType t resolved_generics|> M.lift) in + Logs.warn (fun m -> m "TYPE AFTER : %s" (string_of_sailtype (Some t))); Some t + | None -> return None + in + + let params = List.map2 (fun (p:param) ty -> {p with ty}) f.m_proto.params call_args in + let name = mangle_method_name calle call_args in + let methd = { f with m_proto = { f.m_proto with rtype ; params } } in + let+ () = M.add_decl name ((dummy_pos,name),(defn_to_proto (Method methd))) Method in + rtype + | Left _ -> (* external method *) return f.m_proto.rtype + end + in + + let rec mono_body (lbl: label) (treated: LabelSet.t) (blocks : basicBlock BlockMap.t): LabelSet.t MonoMonad.t = + if LabelSet.mem lbl treated then return treated + else + begin + let treated = LabelSet.add lbl treated in + + let bb = BlockMap.find lbl blocks in + let* () = M.set_ve bb.env in + let* () = ListM.iter (fun assign -> mono_exp assign.target >>= fun _ty -> mono_exp assign.expression>>| fun _ty -> ()) bb.assignments + in + + match bb.terminator |> Option.get with + | Return e -> + let+ _ = begin + match e with + | Some e -> let+ t = mono_exp e in Some t + | None -> return None + end + in treated + + | Invoke new_f -> + let* _ = construct_call new_f.id new_f.params in + mono_body new_f.next treated blocks + + | Goto lbl -> mono_body lbl treated blocks + + | SwitchInt (e,cases,default) -> + let* _ = mono_exp e in + let* treated = mono_body default treated blocks in + ListM.fold_left ( fun treated (_,lbl) -> + mono_body lbl treated blocks + ) treated cases + + | Break -> failwith "no break should be there" + end + in + + match f.m_body with + | Right (_,cfg) -> mono_body cfg.input LabelSet.empty cfg.blocks >>= fun _ -> + let params = List.map (fun (p:param) -> p.ty) f.m_proto.params in + let name = mangle_method_name f.m_proto.name params in + let methd = { f with m_proto = f.m_proto} in + M.add_fun name {methd; generics=[]} + + | Left _ -> (* external *) return () + + + let analyse_functions (sm : in_body SailModule.t) : unit M.t = + + (* find the function, apply generic substitutions to its signature and monomorphize *) + let find_fun_and_mono (name, (g : sailor_args)) : unit M.t = + let* f = find_callable name sm |> M.lift in + + (* monomorphize signature with resolved generics (if any) *) + let* params = ListM.map (fun (p : param) -> let+ ty = degenerifyType p.ty g |> M.lift in {p with ty}) f.m_proto.params in + let* rtype = + match f.m_proto.rtype with + | Some t -> let+ t = degenerifyType t g |> M.lift in Some t + | None -> return None + in + (* update function signature *) + let f = { f with m_proto = { f.m_proto with params; rtype } } in + (* monomorphize, updating env with any new function calls found *) + mono_fun f sm + in + + let rec aux () : unit M.t = + let* empty = M.get_monos >>| (=) [] in + if not empty then (* runs until no more new monomorphic function is found *) + begin + let* name,args = M.pop_monos in + Logs.debug (fun m -> m "looking at function %s with args %s " name (List.map (fun (_,t) -> string_of_sailtype @@ Some t) args |> String.concat " ")); + + let mname = mangle_method_name name (List.split args |> snd) in + + (* we only look at untreated functions *) + let* funs = M.get_funs in + match FieldMap.find_opt mname funs with + | Some _ -> + Logs.debug (fun m -> m "%s already checked" mname); + return () + | None -> + Logs.debug (fun m -> m "analyzing monomorphic function %s" mname); + find_fun_and_mono (name, args) >>= aux + end + else return () + in + let* empty = M.get_monos >>| (=) [] in M.throw_if Error.(make dummy_pos "no monomorphic callable (no main?)") empty >>= aux + + + let transform (smdl : in_body SailModule.t) : out_body SailModule.t E.t = + (* fixme : all processes are converted into methods *) + + let add_if_mono name args gens = + let args = List.map (fun (p:param) -> p.id,p.ty) args in + if gens <> [] then M.pure () else M.push_monos name args + in + + let monos = + M.pure () + (* our entry points are non generic methods and processes *) + >>= fun () -> ListM.iter (fun m -> add_if_mono m.m_proto.name m.m_proto.params m.m_proto.generics) smdl.body.methods + >>= fun () -> ListM.iter (fun p -> add_if_mono p.p_name (fst p.p_interface) p.p_generics) smdl.body.processes + (* + analyze them, find and resolve calls to generic functions + IMPORTANT : we must keep the generic functions : if one of them + is called from an other module and we don't have a monomorphic versio, we must generate one using the generic version + *) + >>= fun () -> analyse_functions smdl + in + + let open MonadSyntax(E) in + let+ _,mono_env = M.run smdl.declEnv monos in + Logs.info (fun m -> m "generated %i monomorphic functions : " (List.length (FieldMap.bindings mono_env.functions))); + FieldMap.iter print_method_proto mono_env.functions; + let methods = List.filter (fun m -> Either.is_left m.m_body) smdl.body.methods |> FieldMap.fold (fun name f acc -> {f.methd with m_proto={f.methd.m_proto with name}}::acc) mono_env.functions in + + {smdl with body = SailModule.{methods;processes = []}} +end) \ No newline at end of file diff --git a/src/ir/misc/monomorphization/monomorphizationMonad.ml b/src/ir/misc/monomorphization/monomorphizationMonad.ml new file mode 100644 index 0000000..8d29858 --- /dev/null +++ b/src/ir/misc/monomorphization/monomorphizationMonad.ml @@ -0,0 +1,46 @@ +open Common +open Monad +open TypesCommon +open MonomorphizationUtils + +type env = {monos: monomorphics; functions : sailor_functions; env: varTypesMap} + +module MonoMonad = struct + module S = MonadState.T(Error.Logger)(struct type t = env end) + open MonadSyntax(S) + open MonadOperator(S) + include S + (* error *) + let throw e = E.throw e |> lift + let throw_if e c = E.throw_if e c |> lift + + let get_decl id ty = get >>| fun e -> Env.get_decl id ty e.env + let add_decl id decl ty = update (fun e -> E.bind (Env.add_decl id decl ty e.env) (fun env -> E.pure {e with env})) + let get_var id = get >>| fun e -> Env.get_var id e.env + let set_ve ve = update (fun e -> E.pure {e with env=(ve,snd e.env)}) + + + let add_fun mname (f: 'a sailor_method) = S.update (fun e -> E.pure {e with functions=FieldMap.add mname f e.functions}) + let get_funs = let+ e = S.get in e.functions + + let push_monos name generics = S.update (fun e -> E.pure {e with monos=(name,generics)::e.monos}) + let get_monos = let+ e = S.get in e.monos + let pop_monos = let* e = S.get in + match e.monos with + | [] -> throw Error.(make dummy_pos "empty_monos") + | h::monos -> S.set {e with monos} >>| fun () -> h + + + let run (decls:Env.D.t) (x: 'a t) : ('a * env) E.t = x {monos=[];functions=FieldMap.empty;env=Env.empty decls} + +end + + +let mangle_method_name (name : string) (args : sailtype list) : string = + let back = + List.fold_left (fun s t -> s ^ string_of_sailtype (Some t) ^ "_") "" args + in + let front = "_" ^ name ^ "_" in + let res = front ^ back in + Logs.debug (fun m -> m "renamed %s to %s" name res); + res \ No newline at end of file diff --git a/src/ir/misc/monomorphization/monomorphizationUtils.ml b/src/ir/misc/monomorphization/monomorphizationUtils.ml new file mode 100644 index 0000000..9fb95b0 --- /dev/null +++ b/src/ir/misc/monomorphization/monomorphizationUtils.ml @@ -0,0 +1,111 @@ +open Common +open TypesCommon +open Monad +module E = Error.Logger +module Env = SailModule.SailEnv(IrMir.AstMir.V) +open UseMonad(E) +type in_body = IrMir.AstMir.mir_function + +type sailor_args = sailtype dict +type varTypesMap = Env.t +type monomorphics = sailor_args dict +type sailor_function = in_body method_defn +type 'a sailor_method = { methd : 'a method_defn; generics : sailor_args } +type sailor_functions = in_body sailor_method FieldMap.t + +let print_method_proto (name : string) (methd : in_body sailor_method) = + let args_type = + List.map (fun (p : param) -> p.ty) methd.methd.m_proto.params + in + let args = + String.concat "," + (List.map (fun t -> string_of_sailtype (Some t)) args_type) + in + let methd_string = Printf.sprintf "method %s (%s)" name args in + Logs.debug (fun m -> m "%s" methd_string) + + + +let resolveType (arg : sailtype) (m_param : sailtype) (generics : string list) (resolved_generics : sailor_args) : (sailtype * sailor_args) E.t = + let rec aux (a : sailtype) (m : sailtype) (g : sailor_args) = + match (a, m) with + | Bool, Bool -> return (Bool, g) + | Int x, Int y when x = y -> return (Int x, g) + | Float, Float -> return (Float, g) + | Char, Char -> return (Char, g) + | String, String -> return (String, g) + | ArrayType (at, s), ArrayType (mt, _) -> let+ t,g = aux at mt g in ArrayType (t, s), g + | GenericType _g1, GenericType _g2 -> return (Int 32,g) + (* E.throw Error.(make dummy_pos @@ Fmt.str "resolveType between generic %s and %s" g1 g2) *) + | at, GenericType gt -> + let* () = E.throw_if Error.(make dummy_pos @@ Fmt.str "generic type %s not declared" gt) (not @@ List.mem gt generics) in + begin + match List.assoc_opt gt g with + | None -> return (at, (gt, at) :: g) + | Some t -> + E.throw_if + Error.(make dummy_pos @@ Fmt.str "generic type mismatch : %s -> %s vs %s" gt (string_of_sailtype (Some t)) (string_of_sailtype (Some at))) + (t <> at) + >>| fun () -> at, g + end + | RefType (at, _), RefType (mt, _) -> aux at mt g + + | CompoundType _, CompoundType _ -> failwith "todocompoundtype" + | Box _at, Box _mt -> failwith "todobox" + | _ -> E.throw Error.(make dummy_pos @@ Fmt.str "cannot happen : %s vs %s" (string_of_sailtype (Some a)) (string_of_sailtype (Some m))) + in + aux arg m_param resolved_generics + +let degenerifyType (t : sailtype) (generics : sailor_args) : sailtype E.t = + let rec aux = function + | Bool -> return Bool + | Int n -> return (Int n) + | Float -> return Float + | Char -> return Char + | String -> return String + | ArrayType (t, s) -> let+ t = aux t in ArrayType (t, s) + | Box t -> let+ t = aux t in Box t + | RefType (t, m) -> let+ t = aux t in RefType (t, m) + | GenericType _t when generics = [] -> + (* E.throw Error.(make dummy_pos @@ Fmt.str "generic type %s present but empty generics list" t) *) + return (Int 32) + + | GenericType _n -> + (* E.throw_if_none Error.(make dummy_pos @@ Fmt.str "generic type %s not present in the generics list" n) (List.assoc_opt n generics) *) + return (Int 32) + | CompoundType _ -> failwith "todo compoundtype" + in + aux t + +let check_args (caller_args : sailtype list) (f:sailor_function) : sailor_args E.t = + let margs = List.map (fun (p:param) -> p.ty) f.m_proto.params in + Logs.debug (fun m -> m "caller args : %s" + (List.fold_left (fun acc t ->Printf.sprintf "%s %s," acc (string_of_sailtype (Some t))) "" caller_args)); + Logs.debug (fun m -> + m "method args : %s" + (List.fold_left (fun acc t -> Printf.sprintf "%s %s," acc (string_of_sailtype (Some t))) "" margs)); + + let args = if f.m_proto.variadic then List.filteri (fun i _ -> i < (List.length margs)) caller_args else caller_args in + +let+ resolved_generics = ListM.fold_right2 (fun ca a g -> resolveType ca a f.m_proto.generics g >>| snd) args margs [] in + List.rev resolved_generics + +let find_callable (name : string) (sm : in_body SailModule.methods_processes SailModule.t) : sailor_function E.t = + (* fixme imports *) + Logs.debug (fun m -> m "looking for function %s" name); + Logs.debug (fun m -> m "name is %s" name); + Logs.debug (fun m -> m "%s" @@ SailModule.DeclEnv.string_of_env sm.declEnv); + match SailModule.DeclEnv.find_decl name (All (Filter [M (); P ()])) sm.declEnv with + | [_,P (_,_)] -> + let p = List.find_opt (fun (p: _ process_defn) -> p.p_name = name) sm.body.processes in + let+ p = E.throw_if_none Error.(make dummy_pos Fmt.(str "found callable '%s' but it's not in the module process" name)) p in + let m_proto = ({variadic=false;rtype=None;generics=p.p_generics;params=fst p.p_interface;pos=p.p_pos;name=p.p_name} : method_sig) in + let m_body = Either.right p.p_body in + {m_body;m_proto} + + | [_,M (_,_)] -> + let m = List.find_opt (fun m -> (* print_string m.m_proto.name; print_newline (); *) m.m_proto.name = name) sm.body.methods in + E.throw_if_none Error.(make dummy_pos @@ Fmt.str "found callable '%s' but it's not in the module methods" name) m + + | [] -> E.throw Error.(make dummy_pos @@ Fmt.str "%s not found" name) + | _ -> E.throw Error.(make dummy_pos @@ Fmt.str "multiple symbols for %s" name) \ No newline at end of file diff --git a/src/ir/misc/setupLoop.ml b/src/ir/misc/setupLoop.ml index 015e3ee..ddc80b1 100644 --- a/src/ir/misc/setupLoop.ml +++ b/src/ir/misc/setupLoop.ml @@ -6,16 +6,16 @@ open Monad.MonadSyntax(E.Logger) module Pass = Pass.Make( struct let name = "Setup / Loop for embedded devices" -type in_body = IrHir.Hir.Pass.out_body +type in_body = IrHir.HirUtils.statement SailModule.methods_processes type out_body = in_body open IrHir.AstHir - let bs = buildStmt dummy_pos +let bs = buildStmt dummy_pos - let createMainProcess (m: in_body SailModule.t) : out_body process_defn Error.Logger.t = + let createMainProcess (m: in_body SailModule.t) : IrHir.HirUtils.statement process_defn Error.Logger.t = let* setup = E.Logger.throw_if_none (E.make dummy_pos @@ "module '" ^ m.md.name ^ "' : no 'setup' function found" ) - (List.find_opt (fun m -> m.m_proto.name = "setup") m.methods) + (List.find_opt (fun m -> m.m_proto.name = "setup") m.body.methods) in let+ () = E.Logger.throw_if @@ -49,6 +49,6 @@ open IrHir.AstHir let loop_decl = method_decl_of_defn loop in let* declEnv = DeclEnv.add_decl loop.m_proto.name loop_decl Method m.declEnv in let+ main = createMainProcess m in - { m with methods = loop::m.methods ; processes = main :: m.processes ; declEnv} + { m with body={methods = loop::m.body.methods ; processes = main :: m.body.processes} ; declEnv} end ) diff --git a/src/ir/misc/mainProcess.ml b/src/ir/misc/setupMain.ml similarity index 64% rename from src/ir/misc/mainProcess.ml rename to src/ir/misc/setupMain.ml index 9aee424..727cdd3 100644 --- a/src/ir/misc/mainProcess.ml +++ b/src/ir/misc/setupMain.ml @@ -2,32 +2,31 @@ open Common open SailModule open TypesCommon -module E = Common.Error -open Monad.MonadSyntax(E.Logger) -open Monad.MonadOperator(E.Logger) - +module E = Common.Error.Logger +open Monad.UseMonad(E) +module Mir = IrMir.AstMir (* temporary pass, converts Main process into a method, throws error if not found or other processes exist *) module Pass = Pass.Make( struct let name = "Main Process to Method" - type in_body = IrMir.Mir.Pass.out_body + type in_body = Mir.mir_function SailModule.methods_processes type out_body = in_body - let add_return (m: in_body method_defn) : out_body method_defn = + let add_return (m: Mir.mir_function method_defn) : Mir.mir_function method_defn = let m_proto = {m.m_proto with rtype=Some (Int 32)} in let m_body = match m.m_body with | Right (decls,cfg) -> - let b = IrMir.AstMir.BlockMap.find cfg.output cfg.blocks in + let b = Mir.BlockMap.find cfg.output cfg.blocks in (* hardcode "return 0" at the end *) - let blocks = IrMir.AstMir.BlockMap.add cfg.output + let blocks = Mir.BlockMap.add cfg.output {b with terminator=Some (Return (Some {info=(dummy_pos,Int 32); exp=(Literal (LInt {l=Z.zero;size=32}))}))} cfg.blocks in Either.right (decls,{cfg with blocks}) | Left _ -> m.m_body in {m_proto;m_body} - let transform (m : in_body SailModule.t) : out_body SailModule.t E.Logger.t = + let transform (m : in_body SailModule.t) : out_body SailModule.t E.t = let+ main = method_of_process m "Main" <&> add_return in - { m with methods = main :: m.methods} + { m with body = {methods = main :: m.body.methods; processes=m.body.processes}} end ) \ No newline at end of file diff --git a/src/ir/sailHir/hir.ml b/src/ir/sailHir/hir.ml index 3f67565..bff5564 100644 --- a/src/ir/sailHir/hir.ml +++ b/src/ir/sailHir/hir.ml @@ -16,12 +16,11 @@ struct type in_body = AstParser.statement type out_body = statement - open MonadFunctions(ECSW) - open MonadOperator(ECSW) + open UseMonad(ECSW) open MakeOrderedFunctions(String) let get_hint id env = - MonadOption.M.bind (List.nth_opt (HIREnv.get_closest id env) 0) (fun id -> Some (None,Printf.sprintf "Did you mean %s ?" id)) + Option.bind (List.nth_opt (HIREnv.get_closest id env) 0) (fun id -> Some (None,Printf.sprintf "Did you mean %s ?" id)) let lower_expression (e : AstParser.expression) : expression ECSW.t = @@ -176,7 +175,7 @@ struct in ECS.run (aux c.body env) |> E.recover ({info=dummy_pos;stmt=Skip},snd env) - let preprocess (sm: 'a SM.t) : 'a SM.t E.t = + let preprocess (sm: 'a SM.methods_processes SM.t) : 'a SM.methods_processes SM.t E.t = let module ES = struct module S = MonadState.M(struct type t = D.t end) include Error.MakeTransformer(S) @@ -185,11 +184,9 @@ struct let get_env = S.get |> lift end in - let open MonadSyntax(ES) in - let open MonadOperator(ES) in - let module F = MonadFunctions(ES) in - let module TEnv = F.MakeFromSequencable(SM.DeclEnv.TypeSeq) in - let module SEnv = F.MakeFromSequencable(SM.DeclEnv.StructSeq) in + let open UseMonad(ES) in + let module TEnv = MakeFromSequencable(SM.DeclEnv.TypeSeq) in + let module SEnv = MakeFromSequencable(SM.DeclEnv.StructSeq) in (* let module MEnv = F.MakeFromSequencable(SM.DeclEnv.MethodSeq) in let module PEnv = F.MakeFromSequencable(SM.DeclEnv.ProcessSeq) in *) let open SM.DeclEnv in @@ -216,7 +213,7 @@ struct let* () = SEnv.iter ( fun (id,(l,{fields; generics})) -> - let* fields = F.ListM.map ( + let* fields = ListM.map ( fun (name,(l,t,n)) -> let* env = ES.get_env in let* t,env = (follow_type t env) |> ES.S.lift in @@ -229,7 +226,7 @@ struct ) (get_own_decls env |> get_decls Struct) in - let* methods = F.ListM.map ( + let* methods = ListM.map ( fun ({m_proto;m_body} as m) -> let* rtype = match m_proto.rtype with | None -> return None @@ -238,7 +235,7 @@ struct let* t,env = (follow_type t env) |> ES.S.lift in let+ () = ES.set_env env in Some t in - let* params = F.ListM.map ( + let* params = ListM.map ( fun (({ty;_}:param) as p) -> let* env = ES.get_env in let* ty,env = (follow_type ty env) |> ES.S.lift in @@ -248,11 +245,11 @@ struct let true_name = (match m_body with Left (sname,_) -> sname | Right _ -> m_proto.name) in let+ () = ES.update_env (update_decl m_proto.name ((m_proto.pos,true_name), defn_to_proto (Method m)) (Self Method)) in m - ) sm.methods in + ) sm.body.methods in - let* processes = F.ListM.map ( + let* processes = ListM.map ( fun ({p_interface=p,s;p_name;p_pos;_} as pr) -> - let* p = F.ListM.map ( + let* p = ListM.map ( fun (({ty;_}:param) as p) -> let* env = ES.get_env in let* ty,env = (follow_type ty env) |> ES.S.lift in @@ -261,7 +258,7 @@ struct let p = {pr with p_interface=p,s} in let+ () = ES.update_env (update_decl p_name (p_pos, defn_to_proto (Process p)) (Self Process)) in p - ) sm.processes in + ) sm.body.processes in (* at this point, all types must have an origin *) @@ -270,7 +267,7 @@ struct let+ () = SEnv.iter (fun (id,proto) -> check_non_cyclic_struct id proto declEnv |> ES.S.lift) (get_own_decls declEnv |> get_decls Struct) in (* Logs.debug (fun m -> m "%s" @@ string_of_declarations declEnv); *) - {sm with methods; processes; declEnv} + {sm with body=SM.{methods; processes}; declEnv} ) sm.declEnv |> fst in sm end diff --git a/src/ir/sailHir/hirUtils.ml b/src/ir/sailHir/hirUtils.ml index 5b215a6..f64842f 100644 --- a/src/ir/sailHir/hirUtils.ml +++ b/src/ir/sailHir/hirUtils.ml @@ -31,8 +31,7 @@ match import with else let+ t = E.throw_if_none (Error.make iloc ~hint:(Some (None,Fmt.str "try importing the module with 'import %s'" name)) @@ "unknown module " ^ name) - (List.find_opt (fun {mname;_} -> mname = name) (D.get_imports env)) >>= - fun _ -> + (List.find_opt (fun {mname;_} -> mname = name) (D.get_imports env)) >>= fun _ -> E.throw_if_none (Error.make loc @@ "declaration " ^ id ^ " not found in module " ^ name) (D.find_decl id (Specific (name, Filter filt)) env) in @@ -50,7 +49,7 @@ match import with | _ as choice -> E.throw @@ Error.make loc ~hint:(Some (None,"specify one with '::' annotation")) @@ Fmt.str "multiple definitions for declaration %s : \n\t%s" id - (List.map (fun (i,def) -> match def with T def -> Fmt.str "from %s : %s" i.mname (string_of_sailtype (def.ty)) | _ -> "") choice |> String.concat "\n\t") + (List.map (fun (i,def) -> match def with T def -> Fmt.str "from %s : %s" i.mname (string_of_sailtype (def.ty)) | _ -> "") choice |> String.concat "\n\t") end let follow_type ty env : (sailtype * D.t) E.t = diff --git a/src/ir/sailMir/mir.ml b/src/ir/sailMir/mir.ml index ab87dfd..9ca049f 100644 --- a/src/ir/sailMir/mir.ml +++ b/src/ir/sailMir/mir.ml @@ -6,9 +6,7 @@ open Monad open MirMonad open MirUtils -open MonadSyntax(ESC) -open MonadOperator(ESC) -open MonadFunctions(ESC) +open UseMonad(ESC) open Pass @@ -17,7 +15,7 @@ module Pass = MakeFunctionPass(V)( struct let name = "MIR" - type in_body = Thir.Pass.out_body + type in_body = Thir.statement type out_body = mir_function let rec lexpr (e : Thir.expression) : expression ESC.t = @@ -47,7 +45,7 @@ struct | ArrayStatic el -> let+ el' = ListM.map rexpr el in buildExp lt (ArrayStatic el') | StructRead (origin,struct_exp,field) -> let+ exp = rexpr struct_exp in - buildExp lt (StructRead (origin,exp,field)) + buildExp lt (StructRead (origin,exp,field)) | StructAlloc (origin,id, fields) -> let+ fields = ListM.map (pairMap2 (rexpr)) fields in @@ -61,7 +59,7 @@ struct open MonadSyntax(E) - let lower_function decl env (_sm:in_body SailModule.t) : (out_body * SailModule.DeclEnv.t) E.t = + let lower_function decl env (_sm:in_body SailModule.methods_processes SailModule.t) : (out_body * SailModule.DeclEnv.t) E.t = let _check_function (_,cfg : out_body) : unit E.t = let* ret,unreachable_blocks = cfg_returns cfg in if Option.is_some ret && decl.ret <> None then diff --git a/src/ir/sailMir/pp_mir.ml b/src/ir/sailMir/pp_mir.ml index a501862..6194a1e 100644 --- a/src/ir/sailMir/pp_mir.ml +++ b/src/ir/sailMir/pp_mir.ml @@ -102,14 +102,14 @@ let ppPrintCfg (pf : Format.formatter) (cfg : cfg) : unit = Format.fprintf pf "%a" (fun x -> ppPrintBasicBlock x lbl) bb) (BlockMap.bindings cfg.blocks) -let ppPrintMethodSig (pf : Format.formatter) (s : Common.TypesCommon.method_sig) : unit = +let ppPrintMethodSig (pf : Format.formatter) (s : TypesCommon.method_sig) : unit = match s.rtype with None -> fprintf pf "%s(%a)" s.name (pp_print_list ~pp_sep:pp_comma (pp_field pp_type)) s.params | Some t -> fprintf pf "%s(%a) -> %a" s.name (pp_print_list ~pp_sep:pp_comma (pp_field pp_type)) s.params pp_type t -let ppPrintMethod (pf : Format.formatter) (m: (declaration list * cfg) Common.TypesCommon.method_defn) : unit = +let ppPrintMethod (pf : Format.formatter) (m: (declaration list * cfg) TypesCommon.method_defn) : unit = match m.m_body with | Right (decls,cfg) -> fprintf pf "fn %a{\n%a\n%a}\n" ppPrintMethodSig m.m_proto (pp_print_list ~pp_sep:pp_semicr ppPrintDeclaration) decls ppPrintCfg cfg | Left _ -> fprintf pf "extern fn %a\n" ppPrintMethodSig m.m_proto @@ -119,7 +119,7 @@ let ppPrintProcess (pf : Format.formatter) (p : (declaration list * cfg) Common. fprintf pf "proc %s() {\n%a\n%a}\n" p.p_name (pp_print_list ~pp_sep:pp_semicr ppPrintDeclaration) (fst p.p_body) ppPrintCfg (snd p.p_body) -let ppPrintModule (pf : Format.formatter) (m : (declaration list * cfg) Common.SailModule.t ) : unit = +let ppPrintModule (pf : Format.formatter) (m : (declaration list * cfg) SailModule.methods_processes SailModule.t ) : unit = fprintf pf "// Sail MIR Representation: %s\n%a \n%a" m.md.name - (pp_print_list ppPrintMethod) m.methods - (pp_print_list ~pp_sep:pp_comma ppPrintProcess) m.processes \ No newline at end of file + (pp_print_list ppPrintMethod) m.body.methods + (pp_print_list ~pp_sep:pp_comma ppPrintProcess) m.body.processes \ No newline at end of file diff --git a/src/ir/sailThir/thir.ml b/src/ir/sailThir/thir.ml index 68c9ca3..fde005d 100644 --- a/src/ir/sailThir/thir.ml +++ b/src/ir/sailThir/thir.ml @@ -20,29 +20,28 @@ type statement = ThirUtils.statement module Pass = Pass.MakeFunctionPass(V)( struct let name = "THIR" - type in_body = Hir.Pass.out_body + type in_body = HirUtils.statement type out_body = statement - let rec lower_lexp (generics : string list) (e : Hir.expression) : expression ES.t = + let rec lower_lexp (e : Hir.expression) : expression ES.t = let rec aux (e:Hir.expression) : expression ES.t = let loc = e.info in match e.exp with | Variable id -> - let+ (_,(_,t)) = ES.get_var id >>= - ES.throw_if_none (Error.make loc @@ Printf.sprintf "unknown variable %s" id) in + let+ (_,(_,t)) = ES.get_var id >>= ES.throw_if_none (Error.make loc @@ Printf.sprintf "unknown variable %s" id) in buildExp (loc,t) @@ Variable id - | Deref e -> let* e = lower_rexp generics e in + | Deref e -> let* e = lower_rexp e in (* return @@ Deref((l,extract_exp_loc_ty e |> snd), e) *) begin match e.exp with | Ref (_,r) -> return @@ buildExp r.info @@ Deref e | _ -> return e end - | ArrayRead (array_exp,idx) -> let* array_exp = aux array_exp and* idx = lower_rexp generics idx in + | ArrayRead (array_exp,idx) -> let* array_exp = aux array_exp and* idx = lower_rexp idx in begin match snd array_exp.info with | ArrayType (t,sz) -> - let* _ = matchArgParam (idx.info) (Int 32) generics [] in + let* _ = matchArgParam (idx.info) (Int 32) in begin (* can do a simple oob check if the type is an int literal *) match idx.exp with @@ -56,7 +55,7 @@ struct | _ -> ES.throw (Error.make loc "not an array !") end | StructRead (origin,e,(fl,field)) -> - let* e = lower_lexp generics e in + let* e = lower_lexp e in let+ origin,t = begin match e.info with @@ -76,7 +75,7 @@ struct | _ -> ES.throw (Error.make loc "not a lvalue !") in aux e - and lower_rexp (generics : string list) (e : Hir.expression) : expression ES.t = + and lower_rexp (e : Hir.expression) : expression ES.t = let rec aux (e:Hir.expression) : expression ES.t = let loc = e.info in match e.exp with | Variable id -> @@ -105,7 +104,7 @@ struct let+ t = check_binop op lt rt |> ES.recover (snd lt) in buildExp (loc,t) @@ BinOp (op,le,re) - | Ref (mut,e) -> let+ e = lower_lexp generics e in + | Ref (mut,e) -> let+ e = lower_lexp e in let t = RefType (snd e.info,mut) in buildExp (loc,t) @@ Ref(mut, e) | ArrayStatic el -> @@ -113,29 +112,29 @@ struct let first_t = snd first_t.info in let* el = ListM.map ( fun e -> let+ e = aux e in - matchArgParam e.info first_t [] [] >>| fun _ -> e + matchArgParam e.info first_t >>| fun _ -> e ) el in let+ el = ListM.sequence el in let t = ArrayType (first_t, List.length el) in buildExp (loc,t) (ArrayStatic el) | MethodCall ((l,name) as lid,source,el) -> - let* (el: expression list) = ListM.map (lower_rexp generics) el in + let* (el: expression list) = ListM.map lower_rexp el in let* mod_loc,(_realname,m) = find_function_source e.info None lid source el in let+ ret = ES.throw_if_none (Error.make e.info "methods in expressions should return a value") m.ret in buildExp (loc,ret) (MethodCall ((l,name),mod_loc,el)) - | ArrayRead _ -> lower_lexp generics e (* todo : some checking *) - | Deref _ -> lower_lexp generics e (* todo : some checking *) - | StructRead _ -> lower_lexp generics e (* todo : some checking *) + | ArrayRead _ -> lower_lexp e (* todo : some checking *) + | Deref _ -> lower_lexp e (* todo : some checking *) + | StructRead _ -> lower_lexp e (* todo : some checking *) | StructAlloc (origin,name,fields) -> let* origin,(_l,strct) = find_struct_source name origin in let struct_fields = List.to_seq strct.fields in let fields = FieldMap.(merge ( fun n f1 f2 -> match f1,f2 with - | Some _, Some e -> Some(let+ e = lower_rexp generics e in (n,e)) + | Some _, Some e -> Some(let+ e = lower_rexp e in (n,e)) | None,None -> None | None, Some (e:Hir.expression) -> Some (ES.throw @@ Error.make e.info @@ Fmt.str "no field '%s' in struct '%s'" n (snd name)) | Some _, None -> Some (ES.throw @@ Error.make loc @@ Fmt.str "missing field '%s' from struct '%s'" n (snd name)) @@ -145,13 +144,12 @@ struct let* fields = SeqM.sequence (Seq.map snd fields) in - let+ () = SeqM.iter2 (fun (_name1,(e:expression)) (_name2,(_,t,_)) -> - let+ _ = matchArgParam e.info t [] [] in ()) + let+ () = SeqM.iter2 (fun (_name1,(e:expression)) (_name2,(_,t,_)) -> matchArgParam e.info t >>| fun _ -> ()) fields struct_fields in let ty = CompoundType {origin= Some origin;decl_ty=Some (S ()); name; generic_instances=[]} in - (buildExp (loc,ty) (StructAlloc (origin,name, List.of_seq fields))) + (buildExp (loc,ty) (StructAlloc (origin,name, List.of_seq fields))) | EnumAlloc _ -> ES.throw (Error.make loc "todo enum alloc ") in aux e @@ -161,7 +159,7 @@ struct let log_and_skip e = ES.log e >>| fun () -> buildStmt e.where Skip in - let rec aux (s:in_body) : out_body ES.t = + let rec aux s : out_body ES.t = let loc = s.info in let buildStmt = buildStmt loc in match s.stmt with @@ -170,10 +168,10 @@ struct begin match opt_t,opt_exp with | Some t, Some e -> - let* e = lower_rexp decl.generics e in - matchArgParam e.info t decl.generics [] >>| fun _ -> t,Some e + let* e = lower_rexp e in + matchArgParam e.info t >>| fun _ -> t,Some e | None,Some e -> - let+ e = lower_rexp decl.generics e in + let+ e = lower_rexp e in (snd e.info),Some e | Some t,None -> return (t,None) | None,None -> ES.throw (Error.make loc "can't infere type with no expression") @@ -184,9 +182,9 @@ struct | Assign(e1, e2) -> - let* e1 = lower_lexp decl.generics e1 - and* e2 = lower_rexp decl.generics e2 in - matchArgParam e2.info (snd e1.info) [] [] >>| + let* e1 = lower_lexp e1 + and* e2 = lower_rexp e2 in + matchArgParam e2.info (snd e1.info) >>| fun _ -> buildStmt (Assign(e1, e2)) | Seq(c1, c2) -> @@ -196,8 +194,8 @@ struct | If(cond_exp, then_s, else_s) -> - let* cond_exp = lower_rexp decl.generics cond_exp in - let* _ = matchArgParam cond_exp.info Bool [] [] in + let* cond_exp = lower_rexp cond_exp in + let* _ = matchArgParam cond_exp.info Bool in let* res = aux then_s in begin match else_s with @@ -212,12 +210,12 @@ struct | Break -> return (buildStmt Break) | Case(e, _cases) -> - let+ e = lower_rexp decl.generics e in + let+ e = lower_rexp e in buildStmt (Case (e, [])) | Invoke (var, mod_loc, id, el) -> (* todo: handle var *) - let* el = ListM.map (lower_rexp decl.generics) el in + let* el = ListM.map lower_rexp el in let* origin,_ = find_function_source s.info var id mod_loc el in buildStmt (Invoke(var,origin, id,el)) |> return @@ -229,14 +227,14 @@ struct if decl.bt <> Pass.BMethod then log_and_skip (Error.make loc @@ Printf.sprintf "process %s : processes can't return non-void type" decl.name) else - let* e = lower_rexp decl.generics e in + let* e = lower_rexp e in let _,t as lt = e.info in begin match decl.ret with | None -> log_and_skip (Error.make loc @@ Printf.sprintf "returns %s but %s doesn't return anything" (string_of_sailtype (Some t)) decl.name) | Some r -> - let+ _ = matchArgParam lt r decl.generics [] in + matchArgParam lt r >>| fun _ -> buildStmt (Return (Some e)) end @@ -252,7 +250,7 @@ struct | Await s -> return (buildStmt (When (s, buildStmt Skip))) | When (s, c) -> let+ res = aux c in buildStmt (When (s, res)) | Run (id, el) -> - let* el = ListM.map (lower_rexp decl.generics) el in + let* el = ListM.map lower_rexp el in (* let* _ = check_call (snd id) "" el loc in *) buildStmt (Run (id, el)) |> return @@ -272,4 +270,4 @@ struct let preprocess = Logger.pure end -) \ No newline at end of file +) diff --git a/src/ir/sailThir/thirUtils.ml b/src/ir/sailThir/thirUtils.ml index f47993a..a4c9ffe 100644 --- a/src/ir/sailThir/thirUtils.ml +++ b/src/ir/sailThir/thirUtils.ml @@ -12,28 +12,6 @@ open MonadFunctions(ES) type expression = (loc * sailtype, l_str) AstHir.expression type statement = (loc,l_str,expression) AstHir.statement -let degenerifyType (t: sailtype) (generics: sailtype dict) loc : sailtype ES.t = - let rec aux = function - | Bool -> return Bool - | Int n -> return (Int n) - | Float -> return Float - | Char -> return Char - | String -> return String - | ArrayType (t,s) -> let+ t = aux t in ArrayType (t, s) - | CompoundType _ -> return t (* todo *) - | Box t -> let+ t = aux t in Box t - | RefType (t,m) -> let+ t = aux t in RefType (t,m) - | GenericType t when generics = [] -> ES.throw @@ Error.make loc (Printf.sprintf "generic type %s present but empty generics list" t) - | GenericType n -> - begin - match List.assoc_opt n generics with - | Some GenericType t -> return (GenericType t) - | Some t -> aux t - | None -> ES.throw @@ Error.make loc (Printf.sprintf "generic type %s not present in the generics list" n) - end - in - aux t - let rec resolve_alias loc : sailtype -> (sailtype,string) Either.t ES.t = function | CompoundType {origin;name=(_,name);decl_ty=Some (T ());_} -> let* (_,mname) = ES.throw_if_none (Error.make loc @@ "unknown type '" ^ name ^ "' , all types must have an origin (problem with HIR)") origin in @@ -69,81 +47,68 @@ let string_of_sailtype_thir (t : sailtype option) : string ES.t = in (string_of_sailtype t) ^ res -let matchArgParam (l,arg: loc * sailtype) (m_param : sailtype) (generics : string list) (resolved_generics: sailtype dict) : (sailtype * sailtype dict) ES.t = +let matchArgParam (l,arg: loc * sailtype) (m_param : sailtype) : sailtype ES.t = let open MonadSyntax(ES) in - let rec aux (a:sailtype) (m:sailtype) (g: sailtype dict) = + let rec aux (a:sailtype) (m:sailtype) = let* lt = resolve_alias l a in let* rt = resolve_alias l m in match lt,rt with - | Left Bool,Left Bool -> return (Bool,g) - | Left (Int i1), Left (Int i2) when i1 = i2 -> return ((Int i1),g) - | Left Float,Left Float -> return (Float,g) - | Left Char,Left Char -> return (Char,g) - | Left String,Left String -> return (String,g) + | Left Bool,Left Bool -> return Bool + | Left (Int i1), Left (Int i2) when i1 = i2 -> return (Int i1) + | Left Float,Left Float -> return Float + | Left Char,Left Char -> return Char + | Left String,Left String -> return String | Left ArrayType (at,s),Left ArrayType (mt,s') -> if s = s' then - let+ t,g = aux at mt g in ArrayType (t,s),g + let+ t = aux at mt in ArrayType (t,s) else ES.throw @@ Error.make l (Printf.sprintf "array length mismatch : wants %i but %i provided" s' s) | Right name, Right name' -> let+ () = ES.throw_if (Error.make l @@ Fmt.str "want abstract type %s but abstract type %s provided" name name') (name <> name') in - arg,g + arg | Left Box _at, Left Box _mt -> ES.throw (Error.make l "todo box") - | Left RefType (at,am), Left RefType (mt,mm) -> if am <> mm then ES.throw (Error.make l "different mutability") else aux at mt g - | Left at,Left GenericType gt -> - begin - if List.mem gt generics then - match List.assoc_opt gt g with - | None -> return (at,(gt,at)::g) - | Some t -> if t = at then return (at,g) else ES.throw (Error.make l "generic type mismatch") - else - ES.throw @@ Error.make l (Printf.sprintf "generic type %s not declared" gt) - end + | Left RefType (at,am), Left RefType (mt,mm) -> if am <> mm then ES.throw (Error.make l "different mutability") else aux at mt + | Left at,Left GenericType _ |Left GenericType _,Left at -> return at | Left CompoundType {name=(_,name1);origin=_;_}, Left CompoundType {name=(_,name2);_} when name1 = name2 -> - return (arg,g) + return arg | _ -> let* param = string_of_sailtype_thir (Some m_param) and* arg = string_of_sailtype_thir (Some arg) in ES.throw @@ Error.make l @@ Printf.sprintf "wants %s but %s provided" param arg - in aux arg m_param resolved_generics + in aux arg m_param let check_binop op l r : sailtype ES.t = let open MonadSyntax(ES) in match op with | Lt | Le | Gt | Ge | Eq | NEq -> - let+ _ = matchArgParam r (snd l) [] [] in Bool + let+ _ = matchArgParam r (snd l) in Bool | And | Or -> - let+ _ = matchArgParam l Bool [] [] - and* _ = matchArgParam r Bool [] [] in Bool - | Plus | Mul | Div | Minus | Rem -> - let+ _ = matchArgParam r (snd l) [] [] in snd l + let+ _ = matchArgParam l Bool + and* _ = matchArgParam r Bool in Bool + | Plus | Mul | Div | Minus | Rem -> + let+ _ = matchArgParam r (snd l) in snd l -let check_call (name:string) (f : function_proto) (args: expression list) loc : sailtype option ES.t = +let check_call (name:string) (f : function_proto) (args: expression list) loc : unit ES.t = (* if variadic, we just make sure there is at least minimum number of arguments needed *) let args = if f.variadic then List.filteri (fun i _ -> i < (List.length f.args)) args else args in let nb_args = List.length args and nb_params = List.length f.args in ES.throw_if (Error.make loc (Printf.sprintf "unexpected number of arguments passed to %s : expected %i but got %i" name nb_params nb_args)) (nb_args <> nb_params) >>= fun () -> - let* resolved_generics = List.fold_left2 + ListM.iter2 ( - fun g (ca:expression) ({ty=a;_}:param) -> - let* g in - let+ x = matchArgParam ca.info a f.generics g in - snd x - ) (return []) args f.args - in - match f.ret with - | Some r -> let+ r = degenerifyType r resolved_generics loc in Some r - | None -> return None + fun (ca:expression) ({ty=a;_}:param) -> + let+ _ = matchArgParam ca.info a in () + ) args f.args + diff --git a/src/parsing/astParser.ml b/src/parsing/astParser.ml index 3b51ef3..032439e 100644 --- a/src/parsing/astParser.ml +++ b/src/parsing/astParser.ml @@ -75,7 +75,7 @@ type defn = module E = Error.Logger -let mk_program (md:metadata) (imports: ImportSet.t) l : statement SailModule.t E.t = +let mk_program (md:metadata) (imports: ImportSet.t) l : statement SailModule.methods_processes SailModule.t E.t = let open SailModule in let open Monad.MonadSyntax(E) in let open Monad.MonadOperator(E) in @@ -118,5 +118,5 @@ let mk_program (md:metadata) (imports: ImportSet.t) l : statement SailModule.t in let+ (declEnv,methods,processes) = aux l in let builtins = Builtins.get_builtins () in - {md; imports; declEnv ; methods;processes;builtins} + {md; imports; declEnv ; body={methods;processes};builtins} diff --git a/src/parsing/parser.mly b/src/parsing/parser.mly index c65f518..9636331 100644 --- a/src/parsing/parser.mly +++ b/src/parsing/parser.mly @@ -68,7 +68,7 @@ %nonassoc ")" %nonassoc ELSE -%start statement SailModule.t E.t> sailModule +%start statement SailModule.methods_processes SailModule.t E.t> sailModule %% diff --git a/src/parsing/parsing.ml b/src/parsing/parsing.ml index 4053c82..f73fa53 100644 --- a/src/parsing/parsing.ml +++ b/src/parsing/parsing.ml @@ -20,7 +20,7 @@ let print_error_position lexbuf = -let fastParse filename : (string * AstParser.statement SailModule.t Error.Logger.t, string) Result.t = +let fastParse filename : (string * AstParser.statement SailModule.methods_processes SailModule.t Error.Logger.t, string) Result.t = let text, lexbuf = L.read filename in let hash = Digest.string text in @@ -86,7 +86,7 @@ let slowParse filename text = -let parse_program filename : AstParser.statement SailModule.t Logger.t = +let parse_program filename : AstParser.statement SailModule.methods_processes SailModule.t Logger.t = match fastParse filename with | Result.Ok (_,sm) -> sm | Result.Error txt -> slowParse filename txt