Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/grader/grading.ml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,38 @@ let get_grade
Toploop_ext.use_string ~print_outcome ~ppf_answer
"module Report = Learnocaml_report" ;
set_progress [%i"Launching the test bench."] ;

let () =

let mods : (string * string) list = (* list of pairs (path, content) *)
let open Learnocaml_exercise in
let files = File.dependencies (access File.depend exo) in
List.map (fun f -> let path = File.key f
and content = decipher f exo in
(path,content)) files
in
let ml_files, mli_files =
List.partition (fun (s,_) -> match Filename.extension s with
| ".ml" -> true
| ".mli" -> false
| _ -> failwith "depend.txt (1)") mods
in
let insert_dependencies_in_env (current_path,structure) =
let name = String.capitalize_ascii (Filename.(remove_extension (basename current_path))) in
handle_error (internal_error [%i"while loading users dependencies"]) @@
match List.find_opt (fun (path,_) -> path = current_path ^ "i") mli_files with
| Some (_,signature) -> Toploop_ext.use_mod_string ~print_outcome ~ppf_answer
~modname:name
~sig_code:signature
structure
| None -> Toploop_ext.use_mod_string ~print_outcome ~ppf_answer
~modname:name
structure
in
List.iter insert_dependencies_in_env ml_files

in

handle_error (internal_error [%i"while testing your solution"]) @@
Toploop_ext.use_string ~print_outcome ~ppf_answer ~filename:(file "test.ml")
(Learnocaml_exercise.(decipher File.test exo)) ;
Expand Down
54 changes: 45 additions & 9 deletions src/repo/learnocaml_exercise.ml
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,28 @@ type t =
test : string ;
solution : string ;
max_score : int ;
depend : string ;
dependencies : string list;
}

let encoding =
let open Json_encoding in
conv
(fun { id; prelude; template; descr; prepare; test; solution; max_score } ->
id, prelude, template, descr, prepare, test, solution, max_score)
(fun (id, prelude, template, descr, prepare, test, solution, max_score) ->
{ id ; prelude ; template ; descr ; prepare ; test ; solution ; max_score })
(obj8
(fun { id; prelude; template; descr; prepare; test; solution; max_score; depend; dependencies} ->
id, prelude, template, descr, prepare, test, solution, max_score,depend, dependencies)
(fun (id, prelude, template, descr, prepare, test, solution, max_score,depend, dependencies) ->
{ id ; prelude ; template ; descr ; prepare ; test ; solution ; max_score ; depend ; dependencies})
(obj10
(req "id" string)
(req "prelude" string)
(req "template" string)
(req "descr" (list (tup2 string string)))
(req "prepare" string)
(req "test" string)
(req "solution" string)
(req "max-score" int))
(req "max-score" int)
(req "depend" string)
(req "dependencies" (list string)))

(* let meta_from_string m =
* Ezjsonm.from_string m
Expand Down Expand Up @@ -179,6 +183,29 @@ module File = struct
update = (fun solution ex -> { ex with solution })
}

let depend =
{ key = "../depend.txt" ; ciphered = false ; (* does'nt work with ciphered = true *)
decode = (fun v -> v) ; encode = (fun v -> v) ;
field = (fun ex -> ex.depend) ;
update = (fun depend ex -> { ex with depend })
}

let dependencies dep =
let extract_depend dep =
(String.split_on_char '\n' dep)
|> (List.map String.trim)
|> List.filter (fun s -> String.length s > 0 && s.[0] <> '#')
in
List.mapi (fun i lib_name ->
({ key = lib_name ; ciphered = true ;
decode = (fun v -> v) ; encode = (fun v -> v) ;
field = (fun ex -> List.nth ex.dependencies i) ;
update = (fun _ _ -> failwith "Learnocaml_exercise.dependencies")
}))
(extract_depend dep)

let key f = f.key

module MakeReader (Concur : Concur) = struct
let read ~read_field ?id: ex_id ?(decipher = true) () =
let open Concur in
Expand Down Expand Up @@ -292,7 +319,10 @@ module File = struct
read_file prepare ;
read_file solution ;
read_file test ;
read_file depend ;
(* read_max_score () *) ] >>= fun () ->
join (let dep = try get depend !ex with Missing_file _ -> "" in
List.map read_file (dependencies dep)) >>= fun () ->
return !ex
end

Expand Down Expand Up @@ -324,7 +354,6 @@ let cipher f v ex =
else
f.update (f.encode v) ex


let field_from_file file files =
try File.(StringMap.find file.key files |> file.decode)
with Not_found -> raise File.(Missing_file file.key)
Expand All @@ -335,6 +364,7 @@ module MakeReaderAnddWriter (Concur : Concur) = struct
let open Concur in
FileReader.read ~read_field ?id ?decipher () >>= fun ex ->
try
let dep = try field_from_file File.depend ex with File.(Missing_file _) -> "" in
return
{ id = field_from_file File.id ex;
(* meta = field_from_file File.meta ex; *)
Expand All @@ -345,6 +375,8 @@ module MakeReaderAnddWriter (Concur : Concur) = struct
test = field_from_file File.test ex ;
solution = field_from_file File.solution ex ;
max_score = 0 ;
depend = dep ;
dependencies = List.map (fun f -> field_from_file f ex) (File.dependencies dep) ;
}
with File.Missing_file _ as e -> fail e

Expand All @@ -366,8 +398,9 @@ module MakeReaderAnddWriter (Concur : Concur) = struct
acc := nacc ;
return ()
with Not_found -> Concur.return () in
let d = decipher File.depend ex in
join
[ write_field id ;
([ write_field id ;
(* write_field meta ;
* write_field title ; *)
write_field prelude ;
Expand All @@ -376,7 +409,10 @@ module MakeReaderAnddWriter (Concur : Concur) = struct
write_field prepare ;
write_field solution ;
write_field test ;
(* write_field max_score *) ] >>= fun () ->
write_field depend ;
(* write_field max_score *) ]
@ (List.map write_field (dependencies d)) )
>>= fun () ->
return !acc
end

Expand Down
8 changes: 8 additions & 0 deletions src/repo/learnocaml_exercise.mli
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ module File : sig
(** Returns the (public) [descr.html] *)
val descr: (string * string) list file

(** Returns the (public) [../depend.txt] *)
val depend: string file

(** Returns the (public) dependencies *)
val dependencies: string -> string file list

(** Returns the key of a file *)
val key : 'a file -> string
end

(** Access a field from the exercise, using the [t] representation, without **
Expand Down