Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Open sidebar
OCamlPro
tryocaml
Commits
fbf98a85
Commit
fbf98a85
authored
Mar 21, 2022
by
Louis Gesbert
Browse files
foo
parent
4d1e2859
Changes
43
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
161 additions
and
135 deletions
+161
-135
demo-repository/exercises/demo/prepare.ml
demo-repository/exercises/demo/prepare.ml
+2
-0
demo-repository/exercises/demo/solution.ml
demo-repository/exercises/demo/solution.ml
+2
-0
demo-repository/exercises/demo/test.ml
demo-repository/exercises/demo/test.ml
+9
-9
demo-repository/exercises/demo2/descr.md
demo-repository/exercises/demo2/descr.md
+0
-8
demo-repository/exercises/demo2/meta.json
demo-repository/exercises/demo2/meta.json
+0
-2
demo-repository/exercises/demo2/prelude.ml
demo-repository/exercises/demo2/prelude.ml
+0
-2
demo-repository/exercises/demo2/prepare.ml
demo-repository/exercises/demo2/prepare.ml
+0
-0
demo-repository/exercises/demo2/solution.ml
demo-repository/exercises/demo2/solution.ml
+0
-4
demo-repository/exercises/demo2/template.ml
demo-repository/exercises/demo2/template.ml
+0
-6
demo-repository/exercises/demo2/test.ml
demo-repository/exercises/demo2/test.ml
+0
-26
demo-repository/exercises/index.json
demo-repository/exercises/index.json
+1
-1
dune
dune
+1
-1
dune-project
dune-project
+1
-1
src/app/learnocaml_description_main.ml
src/app/learnocaml_description_main.ml
+1
-1
src/app/learnocaml_exercise_main.ml
src/app/learnocaml_exercise_main.ml
+19
-11
src/grader/dune
src/grader/dune
+49
-19
src/grader/grader_cli.ml
src/grader/grader_cli.ml
+2
-1
src/grader/grader_jsoo_worker.ml
src/grader/grader_jsoo_worker.ml
+2
-2
src/grader/grading.ml
src/grader/grading.ml
+71
-40
src/grader/grading.mli
src/grader/grading.mli
+1
-1
No files found.
demo-repository/exercises/demo/prepare.ml
View file @
fbf98a85
let
()
=
prerr_endline
(
greetings
^
"1"
)
let
prepared
=
"prepared "
^
greetings
demo-repository/exercises/demo/solution.ml
View file @
fbf98a85
let
()
=
print_endline
prepared
let
plus
=
(
+
)
let
plus_tests
=
[((
1
,
1
)
,
2
)]
...
...
demo-repository/exercises/demo/test.ml
View file @
fbf98a85
(* auto-inserted !! *)
open
Pre_test
module
Test_lib
=
Test_lib
.
Make
(
struct
let
results
=
results
let
set_progress
=
set_progress
let
timeout
=
timeout
module
Introspection
=
Introspection
end
)
module
Report
=
Learnocaml_report
module
Introspection
=
Introspection
(*
open Pre_test
*
module Test_lib = Test_lib.Make(struct
*
let results = results
*
let set_progress = set_progress
*
let timeout = timeout
*
module Introspection = Introspection
*
end)
*
module Report = Learnocaml_report
*
module Introspection = Introspection
*)
(* test.ml start *)
...
...
demo-repository/exercises/demo2/descr.md
deleted
100644 → 0
View file @
4d1e2859
The following example link will open another tab/window:
[
OCaml
](
https://ocaml.org
"External link"
)
This exercise is just another demo for the exercise environment.
<a
href=
""
onclick=
"top.location='/exercises/demo/';"
>
Test
</a>
<details>
<summary>
Hint
</summary>
Use an indirection.
</details>
demo-repository/exercises/demo2/meta.json
deleted
100644 → 0
View file @
4d1e2859
{
"learnocaml_version"
:
"1"
,
"kind"
:
"exercise"
,
"stars"
:
0
,
"title"
:
"Demo of the exercise environment (MD version)"
}
demo-repository/exercises/demo2/prelude.ml
deleted
100644 → 0
View file @
4d1e2859
(* Some code is loaded in the toplevel before your code. *)
let
greetings
=
"Hello world!"
demo-repository/exercises/demo2/prepare.ml
deleted
100644 → 0
View file @
4d1e2859
demo-repository/exercises/demo2/solution.ml
deleted
100644 → 0
View file @
4d1e2859
let
plus
=
(
+
)
let
times
=
(
*
)
let
minus
=
(
-
)
let
divide
=
(
/
)
demo-repository/exercises/demo2/template.ml
deleted
100644 → 0
View file @
4d1e2859
let
plus
x
y
=
x
+
y
;;
let
minus
x
y
=
y
-
x
;;
let
times
x
y
=
x
*
demo-repository/exercises/demo2/test.ml
deleted
100644 → 0
View file @
4d1e2859
open
Test_lib
open
Report
let
()
=
set_result
@@
ast_sanity_check
code_ast
@@
fun
()
->
[
Section
([
Text
"Function:"
;
Code
"plus"
]
,
test_function_2_against_solution
[
%
ty
:
int
->
int
->
int
]
"plus"
[
(
1
,
1
)
;
(
2
,
2
)
;
(
10
,
-
10
)
])
;
Section
([
Text
"Function:"
;
Code
"minus"
]
,
test_function_2_against_solution
[
%
ty
:
int
->
int
->
int
]
"minus"
[
(
1
,
1
)
;
(
4
,
-
2
)
;
(
0
,
10
)
])
;
Section
([
Text
"Function:"
;
Code
"times"
]
,
test_function_2_against_solution
[
%
ty
:
int
->
int
->
int
]
"times"
[
(
1
,
3
)
;
(
2
,
4
)
;
(
3
,
0
)
])
;
Section
([
Text
"Function:"
;
Code
"divide"
]
,
test_function_2_against_solution
[
%
ty
:
int
->
int
->
int
]
"divide"
[
(
12
,
4
)
;
(
12
,
5
)
;
(
3
,
0
)
])
]
demo-repository/exercises/index.json
View file @
fbf98a85
...
...
@@ -2,4 +2,4 @@
"groups"
:
{
"demo"
:
{
"title"
:
"Demo exercise pack"
,
"exercises"
:
[
"demo"
,
"demo2"
]
}
}
}
"exercises"
:
[
"demo"
]
}
}
}
dune
View file @
fbf98a85
...
...
@@ -7,7 +7,7 @@
)
(env
(release (flags -safe-string -w +a-4-42-44-45-48-3-58)
(release (flags -safe-string -w +a-4-42-44-45-48-3-58
-32-33
)
(ocamlc_flags)
(ocamlopt_flags))
)
dune-project
View file @
fbf98a85
(lang dune 2.
3
)
(lang dune 2.
4
)
(name learn-ocaml)
(version 0.13.2)
(allow_approximate_merlin)
src/app/learnocaml_description_main.ml
View file @
fbf98a85
...
...
@@ -71,7 +71,7 @@ let () =
init_tabs
()
;
exercise_fetch
>>=
fun
(
ex_meta
,
exo
,
_deadline
)
->
(* display exercise questions and prelude *)
setup_tab_text_prelude_pane
Learnocaml_exercise
.(
decipher
File
.
prelude
exo
);
setup_tab_text_prelude_pane
Learnocaml_exercise
.(
decipher
File
.
prelude
_ml
exo
);
let
text_iframe
=
Dom_html
.
createIframe
Dom_html
.
document
in
Manip
.
replaceChildren
title_container
Tyxml_js
.
Html5
.[
h1
[
txt
ex_meta
.
title
]
];
...
...
src/app/learnocaml_exercise_main.ml
View file @
fbf98a85
...
...
@@ -123,16 +123,24 @@ let () =
in
let
after_init
top
=
exercise_fetch
>>=
fun
(
_meta
,
exo
,
_deadline
)
->
begin
match
Learnocaml_exercise
.(
decipher
File
.
prelude
exo
)
with
|
""
->
Lwt
.
return
true
|
prelude
->
Learnocaml_toplevel
.
load
~
print_outcome
:
true
top
~
message
:
[
%
i
"loading the prelude..."
]
prelude
end
>>=
fun
r1
->
Learnocaml_toplevel
.
load
~
print_outcome
:
false
top
(
Learnocaml_exercise
.(
decipher
File
.
prepare
exo
))
>>=
fun
r2
->
if
not
r1
||
not
r2
then
failwith
[
%
i
"error in prelude"
]
;
let
exercise_js
=
Learnocaml_exercise
.(
decipher
File
.
exercise_js
exo
)
in
Learnocaml_toplevel
.
load_cmi_from_string
top
Learnocaml_exercise
.(
decipher
File
.
prelude_cmi
exo
)
>>=
fun
_
->
Learnocaml_toplevel
.
load_cmi_from_string
top
Learnocaml_exercise
.(
decipher
File
.
prepare_cmi
exo
)
>>=
fun
_
->
(* Toploop_ext.load_cmi_from_string
* Learnocaml_exercise.(decipher File.prepare_cmi exo); (\* FIXME was this present ?? *\) *)
Learnocaml_toplevel
.
load_js
~
print_outcome
:
true
top
(* FIXME: loading the prelude used to have print_outcome=true *)
~
message
:
[
%
i
"loading the prelude..."
]
exercise_js
>>=
fun
r
->
if
not
r
then
(* failwith [%i"error in prelude"] *)
debug
"FAILED TO LOAD PRELUDE (1)"
;
Learnocaml_toplevel
.
load
top
"open! Prelude ;;"
>>=
fun
r
->
if
not
r
then
(* failwith [%i"error in prelude"] *)
debug
"FAILED TO LOAD PRELUDE (2)"
;
Learnocaml_toplevel
.
load
top
"include Prepare ;;"
>>=
fun
r
->
if
not
r
then
(* failwith [%i"error in prelude"] *)
debug
"FAILED TO LOAD PRELUDE (3)"
;
(* FIXME: remove Prelude, Prepare modules from the env ? *)
Learnocaml_toplevel
.
set_checking_environment
top
>>=
fun
()
->
Lwt
.
return
()
in
let
toplevel_launch
=
...
...
@@ -188,7 +196,7 @@ let () =
EB
.
eval
top
select_tab
;
let
typecheck
=
typecheck
top
ace
editor
in
(*------------- prelude -----------------*)
setup_prelude_pane
ace
Learnocaml_exercise
.(
decipher
File
.
prelude
exo
);
setup_prelude_pane
ace
Learnocaml_exercise
.(
decipher
File
.
prelude
_ml
exo
);
Js
.
Opt
.
case
(
text_iframe
##.
contentDocument
)
(
fun
()
->
failwith
"cannot edit iframe document"
)
...
...
src/grader/dune
View file @
fbf98a85
...
...
@@ -13,8 +13,30 @@
(action (run odoc compile --package learn-ocaml %{deps} -o %{targets}))
)
;; needs to be a separate lib because the module is shared between evaluator
;; parts (Grading) and dynamic parts (Test_lib)
(library
(name testing)
(name introspection_intf)
(wrapped false)
(modules introspection_intf)
(modules_without_implementation introspection_intf)
(libraries learnocaml_report ty))
;; dynamic part, on which Test_lib depends
(library
(name pre_test)
(wrapped false)
(modules pre_test)
(modules_without_implementation pre_test)
;; hack: pre_test actually does have an implementation, but it is dynamically
;; generated and injected in the environment during grading. We are interested
;; in pre_test.cmi to compile test_lib.cmo, then test_lib.cmo should only be
;; loaded in the specific grading toplevel env.
(libraries compiler-libs learnocaml_report introspection_intf))
;; dynamic (but pre-compiled) part
(library
(name testing_dyn)
(wrapped false)
(modes byte)
(library_flags :standard -linkall)
...
...
@@ -24,18 +46,21 @@
learnocaml_ppx_metaquot_lib
ocplib-json-typed
learnocaml_report
learnocaml_repository)
(modules Introspection_intf
Introspection
Test_lib
Mutation_test)
(modules_without_implementation Introspection_intf)
learnocaml_repository
introspection_intf
pre_test ;; dynamic dependency
)
(modules Test_lib Mutation_test)
(preprocess (pps learnocaml_ppx_metaquot))
)
(rule
(target testing_dyn.js)
(deps testing_dyn.cma)
(action (run js_of_ocaml %{deps})))
(rule
(targets test_lib.odoc)
(deps .testing.objs/byte/test_lib.cmti)
(deps .testing
_dyn
.objs/byte/test_lib.cmti)
(action (run odoc compile --package learn-ocaml %{deps} -o %{targets}))
)
...
...
@@ -46,8 +71,6 @@
(run odoc html %{dep:test_lib.odoc} -o %{workspace_root}/_doc/_html)))
)
(rule
(targets embedded_cmis.ml)
(deps
...
...
@@ -115,8 +138,8 @@
%{ocaml-config:standard_library}/std_exit.cmi
%{ocaml-config:standard_library}/topdirs.cmi)
(:local_cmis
../toplevel/.learnocaml_toplevel_pp.objs/byte/learnocaml_toplevel_pp.cmi
)
../toplevel/.learnocaml_toplevel_pp.objs/byte/learnocaml_toplevel_pp.cmi
../grader/.pre_test.objs/byte/pre_test.cmi)
(:lib_cmis
%{lib:re:re.cmi}
%{lib:gg:gg.cmi}
...
...
@@ -151,10 +174,14 @@
(:generated-cmis
../ppx-metaquot/.ty.objs/byte/ty.cmi
../ppx-metaquot/.fun_ty.objs/byte/fun_ty.cmi
.testing.objs/byte/introspection_intf.cmi
.introspection_intf.objs/byte/introspection_intf.cmi
.pre_test.objs/byte/pre_test.cmi
.learnocaml_report.objs/byte/learnocaml_report.cmi
.testing.objs/byte/test_lib.cmi
.testing.objs/byte/mutation_test.cmi))
.testing_dyn.objs/byte/test_lib.cmi
.testing_dyn.objs/byte/mutation_test.cmi
testing_dyn.cma ;; Alright the lib name is no longer adequate
testing_dyn.js
))
(action (with-stdout-to %{targets}
(run ocp-ocamlres -format ocamlres %{compiler-cmis} %{generated-cmis})))
)
...
...
@@ -164,13 +191,16 @@
(wrapped false)
(modes byte)
(library_flags :standard -linkall)
(libraries testing
learnocaml_ppx_metaquot
(libraries learnocaml_ppx_metaquot
ocplib-ocamlres.runtime
toploop
introspection_intf
embedded_cmis
ocplib_i18n
learnocaml_report)
(modules Embedded_grading_cmis
learnocaml_report
learnocaml_repository)
(modules Introspection
Embedded_grading_cmis
Grading)
(preprocess (per_module ((pps ppx_ocplib_i18n learnocaml_ppx_metaquot) Grading)))
)
...
...
src/grader/grader_cli.ml
View file @
fbf98a85
...
...
@@ -53,7 +53,8 @@ let grade ?(print_result=false) ?dirname meta exercise output_json =
let
code_to_grade
=
match
!
grade_student
with
|
Some
path
->
read_student_file
(
Sys
.
getcwd
()
)
path
|
None
->
Lwt
.
return
(
Learnocaml_exercise
.(
decipher
File
.
solution
exercise
))
in
read_student_file
Learnocaml_exercise
.(
"demo-repository/exercises/"
^
decipher
File
.
id
exercise
)
"solution.ml"
(* FIXME *)
(* Lwt.return (Learnocaml_exercise.(decipher File.solution exercise)) *)
in
let
callback
=
if
!
display_callback
then
Some
(
Printf
.
eprintf
"[ %s ]%!
\r\027
[K"
)
else
None
in
let
timeout
=
!
individual_timeout
in
...
...
src/grader/grader_jsoo_worker.ml
View file @
fbf98a85
...
...
@@ -34,10 +34,10 @@ let get_grade ?callback exo solution =
let
divert
name
chan
cb
=
let
redirection
=
Toploop_jsoo
.
redirect_channel
name
chan
cb
in
fun
()
->
Toploop_jsoo
.
stop_channel_redirection
redirection
in
let
load_code
js
_code
=
let
load_code
compiled
_code
=
prerr_endline
(
"USE_JS_STRING"
);
try
Toploop_jsoo
.
use_compiled_string
js_code
;
Toploop_jsoo
.
use_compiled_string
compiled_code
.
Learnocaml_exercise
.
js
;
flush_all
()
;
Toploop_ext
.
Ok
(
true
,
[]
)
with
exn
->
...
...
src/grader/grading.ml
View file @
fbf98a85
...
...
@@ -41,6 +41,7 @@ let user_code_error err =
let
get_grade
?
callback
?
timeout
?
(
dirname
=
""
)
~
divert
~
load_code
(
exo
:
Learnocaml_exercise
.
t
)
code
=
prerr_endline
"GET_GRADE"
;
let
file
f
=
String
.
concat
Filename
.
dir_sep
[
dirname
;
f
]
in
...
...
@@ -93,60 +94,82 @@ let get_grade
fail
err
in
let
result
=
try
handle_error
(
internal_error
[
%
i
"while preparing the tests"
])
@@
handle_error
(
internal_error
[
%
i
"while preparing the tests
(1)
"
])
@@
Toploop_ext
.
use_string
~
print_outcome
~
ppf_answer
{
|
let
print_html
_
=
assert
false
|
};
set_progress
[
%
i
"Loading the prelude."
]
;
handle_error
(
internal_error
[
%
i
"while loading the prelude"
])
@@
Toploop_ext
.
use_string
~
print_outcome
~
ppf_answer
~
filename
:
(
file
"prelude.ml"
)
(
Learnocaml_exercise
.(
decipher
File
.
prelude
exo
))
;
set_progress
[
%
i
"Preparing the test environment."
]
;
handle_error
(
internal_error
[
%
i
"while preparing the tests"
])
@@
load_code
(
Learnocaml_exercise
.(
decipher
File
.
prepare
exo
))
;
Toploop_ext
.
load_cmi_from_string
(
Learnocaml_exercise
.(
decipher
File
.
prelude_cmi
exo
))
;
Toploop_ext
.
load_cmi_from_string
(
Learnocaml_exercise
.(
decipher
File
.
prepare_cmi
exo
))
;
handle_error
(
internal_error
[
%
i
"while preparing the tests (2)"
])
@@
load_code
Learnocaml_exercise
.{
cma
=
decipher
File
.
exercise_cma
exo
;
js
=
decipher
File
.
exercise_js
exo
;
};
handle_error
(
internal_error
[
%
i
"while preparing the tests (3)"
])
@@
Toploop_ext
.
use_string
~
print_outcome
~
ppf_answer
{
|
open
!
Prepare
|
};
prerr_endline
"XX0"
;
set_progress
[
%
i
"Loading your code."
]
;
handle_error
user_code_error
@@
Toploop_ext
.
use_mod_string
~
print_outcome
~
ppf_answer
~
modname
:
"Code"
~
filename
:
(
file
"solution.ml"
)
code
;
set_progress
[
%
i
"Loading the solution."
]
;
handle_error
(
internal_error
[
%
i
"while loading the solution"
])
@@
load_code
(* FIXME use_js_mod_string *)
(
Learnocaml_exercise
.(
decipher
File
.
solution
exo
))
;
Toploop_ext
.
load_cmi_from_string
(
Learnocaml_exercise
.(
decipher
File
.
solution_cmi
exo
))
;
set_progress
[
%
i
"Preparing to launch the tests."
]
;
Introspection
.
allow_introspection
~
divert
;
Introspection
.
insert_mod_ast_in_env
~
var_name
:
"code_ast"
code
;
let
get_result
=
Introspection
.
create_ref
"results"
[
%
ty
:
Learnocaml_report
.
t
option
]
None
in
Introspection
.
register_callback
"set_progress"
[
%
ty
:
string
]
set_progress
;
Introspection
.
insert_in_env
"timeout"
[
%
ty
:
int
option
]
timeout
;
handle_error
(
internal_error
[
%
i
"while preparing the tests"
])
@@
Toploop_ext
.
use_string
~
print_outcome
~
ppf_answer
"module Test_lib = Test_lib.Make(struct
\n
\
\
let results = results
\n
\
\
let set_progress = set_progress
\n
\
\
let timeout = timeout
\n
\
\
module Introspection = Introspection
\n
\
end)"
;
handle_error
(
internal_error
[
%
i
"while preparing the tests"
])
@@
Toploop_ext
.
use_string
~
print_outcome
~
ppf_answer
"module Report = Learnocaml_report"
;
(* The following 3 lines are just a workaround for issue #457 *)
handle_error
(
internal_error
[
%
i
"while preparing the tests"
])
@@
Toploop_ext
.
use_string
~
print_outcome
~
ppf_answer
"
module Introspection
= Introspection"
;
set_progress
[
%
i
"Launching the test bench."
]
;
let
module
Intro_inner
=
(
val
Introspection
.
allow_introspection
~
divert
)
in
prerr_endline
"XX1"
;
let
code_ast
=
Introspection
.
get_mod_ast
~
var_name
:
"code_ast"
code
in
prerr_endline
"XX2"
;
let
results
:
Learnocaml_report
.
t
option
ref
=
ref
None
in
let
get_result
()
=
!
results
in
let
()
=
let
module
Pre_test
:
Introspection_intf
.
PRE_TEST
=
struct
module
Introspection
=
Intro_inner
let
code_ast
=
code_ast
let
results
=
results
let
set_progress
=
set_progress
let
timeout
=
timeout
end
in
prerr_endline
"XX3"
;
(* Toploop_ext.load_cmi_from_string OCamlRes.(Res.find (Path.of_string "pre_test.cmi")
* Embedded_grading_cmis.root) ; FIXME: load here and not from loadpath *)
(* Hack: register Pre_test as a compilation unit usable by the compiled
modules loaded later-on *)
Introspection
.
inject_global
"Pre_test"
(
Obj
.
repr
(
module
Pre_test
:
Introspection_intf
.
PRE_TEST
))
;
prerr_endline
"XX3b"
;
(* Symtable.update_global_table () *)
(* Introspection.insert_in_env "Pre_test"
* [%ty: (
module Introspection
_intf.PRE_TEST)]
* (module Pre_test: Introspection_intf.PRE_TEST); *)
in
prerr_endline
"XX4"
;
handle_error
(
internal_error
[
%
i
"while preparing the tests (4)"
])
@@
load_code
{
Learnocaml_exercise
.
cma
=
OCamlRes
.(
Res
.
find
(
Path
.
of_string
"testing_dyn.cma"
)
Embedded_grading_cmis
.
root
)
;
js
=
OCamlRes
.(
Res
.
find
(
Path
.
of_string
"testing_dyn.js"
)
Embedded_grading_cmis
.
root
)
};
(* handle_error (internal_error [%i"while preparing the tests (5)"]) @@
* Toploop_ext.use_string ~print_outcome ~ppf_answer
* "module Report = Learnocaml_report" ; *)
(* (\* The following 3 lines are just a workaround for issue #457 *\)
* handle_error (internal_error [%i"while preparing the tests (6)"]) @@
* Toploop_ext.use_string ~print_outcome ~ppf_answer
* "module Introspection = Introspection" ; *)
prerr_endline
"XX5"
;
(* FIXME: reimplement "depend.txt" support [{
let () =
let open Learnocaml_exercise in
let files = File.dependencies (access File.depend exo) in
if files <> [] then set_progress [%i"Loading test bench dependencies."] ;
let rec load_dependencies signatures = function
| [] -> () (* signatures without implementation are ignored *)
| file::fs ->
...
...
@@ -186,11 +209,19 @@ let get_grade
"\", file extension expected : .ml or .mli") in
load_dependencies [] files
in
}] *)
handle_error
(
internal_error
[
%
i
"while preparing the tests (3)"
])
@@
Toploop_ext
.
use_string
~
print_outcome
~
ppf_answer
{
|
open
!
Test_lib
|
};
prerr_endline
"XX0"
;
prerr_endline
"XX6"
;
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
))
;
load_code
Learnocaml_exercise
.{
cma
=
decipher
File
.
test_cma
exo
;
js
=
decipher
File
.
test_js
exo
;
};
prerr_endline
"XX6"
;
(* Memory cleanup... *)
Toploop
.
initialize_toplevel_env
()
;
(* TODO: Also clear the object table, once the OCaml's Toploop allows to. *)
...
...
src/grader/grading.mli
View file @
fbf98a85
...
...
@@ -23,7 +23,7 @@ val get_grade:
?
timeout
:
int
->
?
dirname
:
string
->
divert
:
(
string
->
out_channel
->
(
string
->
unit
)
->
(
unit
->
unit
))
->
load_code
:
(
string
->
bool
Toploop_ext
.
toplevel_result
)
->
load_code
:
(
Learnocaml_exercise
.
compiled_lib
->
bool
Toploop_ext
.
toplevel_result
)
->
Learnocaml_exercise
.
t
->
string
->
(
Learnocaml_report
.
t
,
exn
)
result
*
string
*
string
*
string
(** Returns user-friendly messages when called on [Internal_error] or
...
...
Prev
1
2
3
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment