From ae51fae3e3df44b866502a17797bdf580e183a44 Mon Sep 17 00:00:00 2001 From: tibvdm Date: Wed, 2 Oct 2024 13:31:56 +0200 Subject: [PATCH] add parentheses to fix explicit typing + remove explicit typing in feedback --- .gitignore | 1 + tested/languages/haskell/config.py | 12 ++++++++--- tested/languages/haskell/generators.py | 21 +++++++++---------- tested/manual.py | 4 ++-- .../haskell/evaluation/ndeElement.yaml | 16 ++++++++++++++ .../exercises/haskell/solution/ndeElement.hs | 2 ++ 6 files changed, 40 insertions(+), 16 deletions(-) create mode 100644 tests/exercises/haskell/evaluation/ndeElement.yaml create mode 100644 tests/exercises/haskell/solution/ndeElement.hs diff --git a/.gitignore b/.gitignore index fca52d7c..06e07f0b 100644 --- a/.gitignore +++ b/.gitignore @@ -82,3 +82,4 @@ venv-*/ .venv/ node_modules/ result/ +.data/ diff --git a/tested/languages/haskell/config.py b/tested/languages/haskell/config.py index 1ec48433..30cae896 100644 --- a/tested/languages/haskell/config.py +++ b/tested/languages/haskell/config.py @@ -1,6 +1,6 @@ import re from pathlib import Path -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from tested.datatypes import AllTypes from tested.dodona import AnnotateCode, Message @@ -28,6 +28,10 @@ class Haskell(Language): + def __init__(self, config: Optional["GlobalConfig"]): + super().__init__(config) + self.clean_types_regex = re.compile(r"\(([^:\s]*)\s*::\s*([A-Z][a-zA-Z0-9]*)\)") + def initial_dependencies(self) -> list[str]: return ["Values.hs", "EvaluationUtils.hs"] @@ -111,7 +115,7 @@ def linter(self, remaining: float) -> tuple[list[Message], list[AnnotateCode]]: return linter.run_hlint(self.config.dodona, remaining) def cleanup_description(self, statement: str) -> str: - return cleanup_description(self, statement) + return cleanup_description(self, self.clean_types_regex.sub(r'\1', statement)) def cleanup_stacktrace(self, stacktrace: str) -> str: filename = submission_file(self) @@ -165,11 +169,13 @@ def cleanup_stacktrace(self, stacktrace: str) -> str: def generate_statement(self, statement: Statement) -> str: from tested.languages.haskell import generators - return generators.convert_statement(statement) + return self.clean_types_regex.sub(r'\1', generators.convert_statement(statement)) def generate_execution_unit(self, execution_unit: "PreparedExecutionUnit") -> str: from tested.languages.haskell import generators + print(generators.convert_execution_unit(execution_unit)) + return generators.convert_execution_unit(execution_unit) def generate_selector(self, contexts: list[str]) -> str: diff --git a/tested/languages/haskell/generators.py b/tested/languages/haskell/generators.py index c2897db7..c6d8df9b 100644 --- a/tested/languages/haskell/generators.py +++ b/tested/languages/haskell/generators.py @@ -40,7 +40,6 @@ def convert_arguments(arguments: list[Expression]) -> str: return ", ".join(convert_statement(arg) for arg in arguments) - def convert_value(value: Value) -> str: # Handle some advanced types. if value.type == AdvancedSequenceTypes.TUPLE: @@ -48,37 +47,37 @@ def convert_value(value: Value) -> str: return f"({convert_arguments(value.data)})" elif isinstance(value.type, AdvancedNumericTypes): if not isinstance(value.data, SpecialNumbers): - return f"{value.data} :: {convert_declaration(value.type)}" + return f"({value.data} :: {convert_declaration(value.type)})" elif value.data == SpecialNumbers.NOT_A_NUMBER: - return f"(0/0) :: {convert_declaration(value.type)}" + return f"((0/0) :: {convert_declaration(value.type)})" elif value.data == SpecialNumbers.POS_INFINITY: - return f"(1/0) :: {convert_declaration(value.type)}" + return f"((1/0) :: {convert_declaration(value.type)})" else: assert value.data == SpecialNumbers.NEG_INFINITY - return f"(-1/0) :: {convert_declaration(value.type)}" + return f"((-1/0) :: {convert_declaration(value.type)})" elif value.type == AdvancedStringTypes.CHAR: assert isinstance(value, StringType) return "'" + value.data.replace("'", "\\'") + "'" # Handle basic types value = as_basic_type(value) if value.type == BasicNumericTypes.INTEGER: - return f"{value.data} :: Int" + return f"({value.data} :: Int)" elif value.type == BasicNumericTypes.REAL: if not isinstance(value.data, SpecialNumbers): - return f"{value.data} :: Double" + return f"({value.data} :: Double)" elif value.data == SpecialNumbers.NOT_A_NUMBER: - return "(0/0) :: Double" + return "((0/0) :: Double)" elif value.data == SpecialNumbers.POS_INFINITY: - return "(1/0) :: Double" + return "((1/0) :: Double)" else: assert SpecialNumbers.NEG_INFINITY - return "(-1/0) :: Double" + return "((-1/0) :: Double)" elif value.type == BasicStringTypes.TEXT: return json.dumps(value.data) elif value.type == BasicBooleanTypes.BOOLEAN: return str(value.data) elif value.type == BasicNothingTypes.NOTHING: - return "Nothing :: Maybe Integer" + return "(Nothing :: Maybe Integer)" elif value.type == BasicSequenceTypes.SEQUENCE: assert isinstance(value, SequenceType) return f"[{convert_arguments(value.data)}]" diff --git a/tested/manual.py b/tested/manual.py index 7a355cb9..d7d64e6d 100644 --- a/tested/manual.py +++ b/tested/manual.py @@ -24,10 +24,10 @@ def read_config() -> DodonaConfig: programming_language=SupportedLanguage("haskell"), natural_language="nl", resources=Path(exercise_dir, "evaluation"), - source=Path(exercise_dir, "solution/voorlaatste.hs"), + source=Path(exercise_dir, "solution/ndeElement.hs"), judge=Path("."), workdir=Path("workdir"), - test_suite="voorlaatste.yaml", + test_suite="ndeElement.yaml", options=Options( linter=False, ), diff --git a/tests/exercises/haskell/evaluation/ndeElement.yaml b/tests/exercises/haskell/evaluation/ndeElement.yaml new file mode 100644 index 00000000..7a045c3f --- /dev/null +++ b/tests/exercises/haskell/evaluation/ndeElement.yaml @@ -0,0 +1,16 @@ +tabs: + - tab: geefNde + testcases: + - expression: geefNde(0, [1, 2, 3, 4]) + description: + description: geefNde 0 [1, 2, 3, 4] + format: haskell + return: 1 + - expression: geefNde(0, [1.0, 2.0, 3.0, 4.0]) + return: 1.0 + - expression: geefNde(0, ['a', 'b', 'c', 'd']) + return: a + - expression: geefNde(1, [(1, 2), (3, 4), (5, 6), (7, 8)]) + return: !tuple [3, 4] + - expression: geefNde(1, [(1.0, 2.0), (3.0, 4.0), (5.0, 6.0), (7.0, 8.0)]) + return: !tuple [3.0, 4.0] diff --git a/tests/exercises/haskell/solution/ndeElement.hs b/tests/exercises/haskell/solution/ndeElement.hs new file mode 100644 index 00000000..f7072810 --- /dev/null +++ b/tests/exercises/haskell/solution/ndeElement.hs @@ -0,0 +1,2 @@ +geefNde :: Int -> [a] -> a +geefNde n l = l !! n