Skip to content

Commit

Permalink
Add OCaml template for programming exercises (ls1intum#3045)
Browse files Browse the repository at this point in the history
  • Loading branch information
sleiss authored Mar 23, 2021
1 parent 4487961 commit ec81ec4
Show file tree
Hide file tree
Showing 32 changed files with 253 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .jhipster/ProgrammingExercise.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
{
"fieldName": "programmingLanguage",
"fieldType": "ProgrammingLanguage",
"fieldValues": "JAVA,PYTHON,C,HASKELL,KOTLIN,VHDL,ASSEMBLER,SWIFT"
"fieldValues": "JAVA,PYTHON,C,HASKELL,KOTLIN,VHDL,ASSEMBLER,SWIFT,OCAML"
},
{
"fieldName": "packageName",
Expand Down
3 changes: 2 additions & 1 deletion artemis.jh
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ enum ProgrammingLanguage {
KOTLIN,
VHDL,
ASSEMBLER,
SWIFT
SWIFT,
OCAML
}

entity ModelingExercise { //extends Exercise
Expand Down
4 changes: 4 additions & 0 deletions docs/user/exercises/programming-exercise-setup.inc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ Instructors can still use those templates to generate programming exercises and
+----------------------+--------+---------+
| Swift | yes | no |
+----------------------+--------+---------+
| OCaml | yes | no |
+----------------------+--------+---------+

- Not all ``templates`` support the same feature set.
Depending on the feature set, some options might not be available during the creation of the programming exercise.
Expand All @@ -55,6 +57,8 @@ Instructors can still use those templates to generate programming exercises and
+----------------------+----------------------+----------------------+------------------+--------------+--------------+------------------------------+
| Swift | no | no | no | no | no | no |
+----------------------+----------------------+----------------------+------------------+--------------+--------------+------------------------------+
| OCaml | no | no | no | no | no | no |
+----------------------+----------------------+----------------------+------------------+--------------+--------------+------------------------------+

- *Sequential Test Runs*: ``Artemis`` can generate a build plan which first executes structural and then behavioral tests. This feature can help students to better concentrate on the immediate challenge at hand.
- *Static Code Analysis*: ``Artemis`` can generate a build plan which additionally executes static code analysis tools.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
* The ProgrammingLanguage enumeration.
*/
public enum ProgrammingLanguage {
JAVA, PYTHON, C, HASKELL, KOTLIN, VHDL, ASSEMBLER, SWIFT
JAVA, PYTHON, C, HASKELL, KOTLIN, VHDL, ASSEMBLER, SWIFT, OCAML
}
4 changes: 4 additions & 0 deletions src/main/java/de/tum/in/www1/artemis/service/FileService.java
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,10 @@ public void copyResources(Resource[] resources, String prefix, String targetDire
if (targetFilePath.endsWith("classpath.file")) {
targetFilePath = targetFilePath.replace("classpath.file", ".classpath");
}
// special case for 'dune' files which would not be included in the build otherwise
if (targetFilePath.endsWith("dune.file")) {
targetFilePath = targetFilePath.replace("dune.file", "dune");
}

Path copyPath = Paths.get(targetDirectoryPath + targetFilePath);
File parentFolder = copyPath.toFile().getParentFile();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ enum RepositoryCheckoutPath implements CustomizableCheckoutPath {
@Override
public String forProgrammingLanguage(ProgrammingLanguage language) {
return switch (language) {
case JAVA, PYTHON, C, HASKELL, KOTLIN, VHDL, ASSEMBLER, SWIFT -> Constants.ASSIGNMENT_CHECKOUT_PATH;
case JAVA, PYTHON, C, HASKELL, KOTLIN, VHDL, ASSEMBLER, SWIFT, OCAML -> Constants.ASSIGNMENT_CHECKOUT_PATH;
};
}
},
Expand All @@ -251,7 +251,7 @@ public String forProgrammingLanguage(ProgrammingLanguage language) {
@Override
public String forProgrammingLanguage(ProgrammingLanguage language) {
return switch (language) {
case JAVA, PYTHON, HASKELL, KOTLIN, SWIFT -> "";
case JAVA, PYTHON, HASKELL, KOTLIN, SWIFT, OCAML -> "";
case C, VHDL, ASSEMBLER -> Constants.TESTS_CHECKOUT_PATH;
};
}
Expand Down Expand Up @@ -295,6 +295,7 @@ static String getDockerImageName(ProgrammingLanguage language) {
case VHDL -> "tizianleonhardt/era-artemis-vhdl:latest";
case ASSEMBLER -> "tizianleonhardt/era-artemis-assembler:latest";
case SWIFT -> "norionomura/swiftlint:0.41.0_swift-5.3.1";
case OCAML -> "ls1tum/artemis-ocaml-docker:latest";
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ private Stage createBuildStage(ProgrammingLanguage programmingLanguage, final bo
defaultStage.jobs(defaultJob);
return defaultStage;
}
case HASKELL -> {
case HASKELL, OCAML -> {
return createDefaultStage(programmingLanguage, sequentialBuildRuns, checkoutTask, defaultStage, defaultJob, "**/test-reports/*.xml");
}
case VHDL, ASSEMBLER -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ public BambooProgrammingLanguageFeatureService() {
programmingLanguageFeatures.put(VHDL, new ProgrammingLanguageFeature(VHDL, false, false, false, false, false, List.of()));
programmingLanguageFeatures.put(ASSEMBLER, new ProgrammingLanguageFeature(ASSEMBLER, false, false, false, false, false, List.of()));
programmingLanguageFeatures.put(SWIFT, new ProgrammingLanguageFeature(SWIFT, false, true, false, true, false, List.of()));
programmingLanguageFeatures.put(OCAML, new ProgrammingLanguageFeature(OCAML, false, false, false, false, false, List.of()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ private JenkinsXmlConfigBuilder builderFor(ProgrammingLanguage programmingLangua
case JAVA, KOTLIN, PYTHON, C, HASKELL, SWIFT -> jenkinsBuildPlanCreator;
case VHDL -> throw new UnsupportedOperationException("VHDL templates are not available for Jenkins.");
case ASSEMBLER -> throw new UnsupportedOperationException("Assembler templates are not available for Jenkins.");
case OCAML -> throw new UnsupportedOperationException("OCaml templates are not available for Jenkins.");
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public TemplateUpgradePolicy(JavaTemplateUpgradeService javaRepositoryUpgradeSer
public TemplateUpgradeService getUpgradeService(ProgrammingLanguage programmingLanguage) {
return switch (programmingLanguage) {
case JAVA -> javaRepositoryUpgradeService;
case KOTLIN, PYTHON, C, HASKELL, VHDL, ASSEMBLER, SWIFT -> defaultRepositoryUpgradeService;
case KOTLIN, PYTHON, C, HASKELL, VHDL, ASSEMBLER, SWIFT, OCAML -> defaultRepositoryUpgradeService;
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# the build process is specified in `run.sh` in the test repository
chmod +x run.sh
./run.sh
42 changes: 42 additions & 0 deletions src/main/resources/templates/ocaml/exercise/git.attributes.file
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Handle line endings automatically for files detected as text
# and leave all files detected as binary untouched.
* text=auto

#
# The above will handle all files NOT found below
#
# These files are text and should be normalized (Convert crlf => lf)
*.bash text eol=lf
*.css text diff=css
*.df text
*.htm text diff=html
*.html text diff=html
*.hs text
*.java text diff=java
*.js text
*.json text
*.jsp text
*.jspf text
*.jspx text
*.properties text
*.sh text eol=lf
*.tld text
*.txt text
*.tag text
*.tagx text
*.xml text
*.yml text

# These files are binary and should be left untouched
# (binary is a macro for -text -diff)
*.class binary
*.dll binary
*.ear binary
*.gif binary
*.ico binary
*.jar binary
*.jpg binary
*.jpeg binary
*.png binary
*.so binary
*.war binary
8 changes: 8 additions & 0 deletions src/main/resources/templates/ocaml/exercise/git.ignore.file
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# OCaml output files
*.out
*.exe
*.cmi
*.cmo

# Dune output
_build
7 changes: 7 additions & 0 deletions src/main/resources/templates/ocaml/exercise/src/assignment.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
let add a b = failwith "TODO add"

let filter p xs = failwith "TODO filter"

let starts_with haystack hay = failwith "TODO starts_with"

let starts_with2 haystack hay = failwith "TODO starts_with2"
15 changes: 15 additions & 0 deletions src/main/resources/templates/ocaml/readme
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Arithemtic, Lists and Using Libraries

In this exercise, you will use basic features of the OCaml programming language for arithemtic, list and string operations.

1. [task][add](test suite for sum:0:add 0 0,test suite for sum:1:add 2 1)
Implement the function `add` that takes two values of type `int` and returns their sum.

2. [task][filter](test suite for sum:2:filter even [1;2])
Implement the generic and recursive function `filter` that that takes a predicate of type `'a -> bool` and a list of type `'a list`. The function should return the list of elements contained in the input list that fulfill the predicate. The elements in the returned list must appear in the same order as in the input list.

3. [task][starts_with](test suite for sum:4:starts_with false, test suite for sum:3:starts_with true)
Implement the function `starts_with` that takes two `string`s and returns `true` if, and only if, the second string is a prefix of the first. Use the appropriate library function provided by the `BatString` module from the "batteries" library.

3. [task][starts_with2](test suite for sum:5:starts_with2 true , test suite for sum:6:starts_with2 false)
Implement the function `starts_with2` which has the same specification as `starts_with`, but now, use the appropriate library function provided by the `Base.String` module from the "core" library.
42 changes: 42 additions & 0 deletions src/main/resources/templates/ocaml/solution/git.attributes.file
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Handle line endings automatically for files detected as text
# and leave all files detected as binary untouched.
* text=auto

#
# The above will handle all files NOT found below
#
# These files are text and should be normalized (Convert crlf => lf)
*.bash text eol=lf
*.css text diff=css
*.df text
*.htm text diff=html
*.html text diff=html
*.hs text
*.java text diff=java
*.js text
*.json text
*.jsp text
*.jspf text
*.jspx text
*.properties text
*.sh text eol=lf
*.tld text
*.txt text
*.tag text
*.tagx text
*.xml text
*.yml text

# These files are binary and should be left untouched
# (binary is a macro for -text -diff)
*.class binary
*.dll binary
*.ear binary
*.gif binary
*.ico binary
*.jar binary
*.jpg binary
*.jpeg binary
*.png binary
*.so binary
*.war binary
8 changes: 8 additions & 0 deletions src/main/resources/templates/ocaml/solution/git.ignore.file
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# OCaml output files
*.out
*.exe
*.cmi
*.cmo

# Dune output
_build
9 changes: 9 additions & 0 deletions src/main/resources/templates/ocaml/solution/src/assignment.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
let add a b = a + b

let rec filter p = function
| [] -> []
| a :: t -> if p a then a :: (filter p t) else filter p t

let starts_with = BatString.starts_with

let starts_with2 haysteck hay = Base.String.is_prefix haysteck ~prefix:hay
4 changes: 4 additions & 0 deletions src/main/resources/templates/ocaml/test/.merlin
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
B _build
PKG oUnit
PKG batteries
PKG core
9 changes: 9 additions & 0 deletions src/main/resources/templates/ocaml/test/dune.file
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
(include_subdirs unqualified)

(test
(name test)
(flags (:standard -warn-error -A))
(libraries ounit2 batteries core)
;;; results will appear in _build/results.xml
(action (run %{test} -output-junit-file "../results.xml"))
)
42 changes: 42 additions & 0 deletions src/main/resources/templates/ocaml/test/git.attributes.file
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Handle line endings automatically for files detected as text
# and leave all files detected as binary untouched.
* text=auto

#
# The above will handle all files NOT found below
#
# These files are text and should be normalized (Convert crlf => lf)
*.bash text eol=lf
*.css text diff=css
*.df text
*.htm text diff=html
*.html text diff=html
*.hs text
*.java text diff=java
*.js text
*.json text
*.jsp text
*.jspf text
*.jspx text
*.properties text
*.sh text eol=lf
*.tld text
*.txt text
*.tag text
*.tagx text
*.xml text
*.yml text

# These files are binary and should be left untouched
# (binary is a macro for -text -diff)
*.class binary
*.dll binary
*.ear binary
*.gif binary
*.ico binary
*.jar binary
*.jpg binary
*.jpeg binary
*.png binary
*.so binary
*.war binary
6 changes: 6 additions & 0 deletions src/main/resources/templates/ocaml/test/git.ignore.file
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
dune-project
test-reports
_build
*.exe
*.cmi
*.cmo
10 changes: 10 additions & 0 deletions src/main/resources/templates/ocaml/test/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash

OUTPUT_FOLDER="test-reports"

eval $(opam env)

if [ ! -d "$OUTPUT_FOLDER" ]; then
mkdir $OUTPUT_FOLDER
fi
(dune runtest --build-dir=$OUTPUT_FOLDER || exit 0)
18 changes: 18 additions & 0 deletions src/main/resources/templates/ocaml/test/test/test.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
open OUnit2
open Assignment

let even i = i mod 2 == 0

let tests = "test suite for sum" >::: [
(* Test add, use string_of_int for output in failur case *)
"add 0 0" >:: (fun _ -> assert_equal 0 (add 0 0) ~printer:string_of_int);
"add 2 1" >:: (fun _ -> assert_equal 3 (add 2 1) ~printer:string_of_int);
"filter even [1;2]" >:: (fun _ -> assert_equal [2] (filter even [1;2]));
"starts_with true" >:: (fun _ -> assert_bool "starts_with should return true" (starts_with "hallo" "hal"));
"starts_with false" >:: (fun _ -> assert_bool "starts_with should return false" (not (starts_with "hallo" "allo")));
"starts_with2 true " >:: (fun _ -> assert_bool "starts_with2 should return true" (starts_with2 "hallo" "hal"));
"starts_with2 false" >:: (fun _ -> assert_bool "starts_with2 should return false" (not (starts_with2 "hallo" "allo")));
]

let _ =
run_test_tt_main tests
1 change: 1 addition & 0 deletions src/main/webapp/app/entities/programming-exercise.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export enum ProgrammingLanguage {
VHDL = 'VHDL',
ASSEMBLER = 'ASSEMBLER',
SWIFT = 'SWIFT',
OCAML = 'OCAML',
}

export enum ProjectType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h4 *ngIf="isImport" id="jhi-programming-exercise-heading-import" jhiTranslate="
<option value="VHDL" *ngIf="supportsVHDL">VHDL</option>
<option value="ASSEMBLER" *ngIf="supportsAssembler">Assembler</option>
<option value="SWIFT" *ngIf="supportsSwift">Swift</option>
<option value="OCAML" *ngIf="supportsOCaml">OCaml</option>
</select>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export class ProgrammingExerciseUpdateComponent implements OnInit {
public supportsVHDL = false;
public supportsAssembler = false;
public supportsSwift = false;
public supportsOCaml = false;

public packageNameRequired = true;
public staticCodeAnalysisAllowed = false;
Expand Down Expand Up @@ -243,6 +244,7 @@ export class ProgrammingExerciseUpdateComponent implements OnInit {
this.supportsVHDL = this.programmingLanguageFeatureService.supportsProgrammingLanguage(ProgrammingLanguage.VHDL);
this.supportsAssembler = this.programmingLanguageFeatureService.supportsProgrammingLanguage(ProgrammingLanguage.ASSEMBLER);
this.supportsSwift = this.programmingLanguageFeatureService.supportsProgrammingLanguage(ProgrammingLanguage.SWIFT);
this.supportsOCaml = this.programmingLanguageFeatureService.supportsProgrammingLanguage(ProgrammingLanguage.OCAML);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'brace/ext/modelist';
import 'brace/mode/java';
import 'brace/mode/markdown';
import 'brace/mode/haskell';
import 'brace/mode/ocaml';
import 'brace/mode/c_cpp';
import 'brace/mode/python';
import 'brace/mode/swift';
Expand Down
Loading

0 comments on commit ec81ec4

Please sign in to comment.