refactor: Syntax with unit tests

This commit is contained in:
Lucàs
2024-07-08 16:44:42 +02:00
parent 6df363c78d
commit 2e76ccf9fc
39 changed files with 460 additions and 771 deletions
-11
View File
@@ -1,11 +0,0 @@
;test/ast/dune
(test
(name print)
(libraries alcotest ast)
)
(test
(name typecheck)
(libraries alcotest ast)
)
-180
View File
@@ -1,180 +0,0 @@
(* test/ast/print.ml *)
open Alcotest
open Ast.Syntax
module To_test = struct
let _type = Ast.Print.string_of_type
let literal = Ast.Print.string_of_literal
let binary_operator = Ast.Print.string_of_binary_operator
let unary_operator = Ast.Print.string_of_unary_operator
let expression = Ast.Print.string_of_expression
let variable_declaration = Ast.Print.string_of_variable_declaration
let statement = Ast.Print.string_of_statement
let source_file = Ast.Print.string_of_source_file
end
let test_string_of_type () =
let tests =
[
("int", "IntegerType", IntegerType);
("float", "FloatType", FloatType);
("char", "CharacterType", CharacterType);
("string", "StringType", StringType);
("bool", "BooleanType", BooleanType);
("void", "VoidType", VoidType);
]
in
List.iter
(fun (name, expected, actual) ->
(check string) name expected (To_test._type actual))
tests
let test_string_of_literal () =
let tests =
[
("42", "Integer(42)", Integer 42);
("3.14", "Float(3.14)", Float 3.14);
("true", "Boolean(true)", Boolean true);
("false", "Boolean(false)", Boolean false);
("hello", "String(\"hello\")", String "hello");
("c", "Character('c')", Character 'c');
("null", "Null", Null);
]
in
List.iter
(fun (name, expected, actual) ->
(check string) name expected (To_test.literal actual))
tests
let test_string_of_binary_operator () =
let tests =
[
("+", "Add", Add);
("-", "Subtract", Subtract);
("*", "Multiply", Multiply);
("/", "Divide", Divide);
("&&", "AmpersandAmpersand", AmpersandAmpersand);
("||", "BarBar", BarBar);
("==", "EqualsEquals", EqualsEquals);
("!=", "ExclamationEquals", ExclamationEquals);
("<", "LessThan", LessThan);
("<=", "LessThanEquals", LessThanEquals);
(">", "GreaterThan", GreaterThan);
(">=", "GreaterThanEquals", GreaterThanEquals);
("=", "Assign", Assign);
]
in
List.iter
(fun (name, expected, actual) ->
(check string) name expected (To_test.binary_operator actual))
tests
let test_string_of_unary_operator () =
let tests = [ ("-", "Negate", Negate); ("!", "Not", Not) ] in
List.iter
(fun (name, expected, actual) ->
(check string) name expected (To_test.unary_operator actual))
tests
let test_string_of_expression () =
let tests =
[
("42", "Literal(Integer(42))", Literal (Integer 42));
( "1 + 2",
"BinaryExpression(Add, Literal(Integer(1)), Literal(Integer(2)))",
BinaryExpression (Add, Literal (Integer 1), Literal (Integer 2)) );
( "-42",
"UnaryExpression(Negate, Literal(Integer(42)))",
UnaryExpression (Negate, Literal (Integer 42)) );
("x", "Identifier(\"x\")", Identifier "x");
]
in
List.iter
(fun (name, expected, actual) ->
(check string) name expected (To_test.expression actual))
tests
let test_string_of_variable_declaration () =
let tests =
[
( "var x: int = 42;",
"VariableDeclaration(IntegerType, Identifier(\"x\"), \
Literal(Integer(42)))",
VariableDeclaration (IntegerType, Identifier "x", Literal (Integer 42))
);
]
in
List.iter
(fun (name, expected, actual) ->
(check string) name expected (To_test.variable_declaration actual))
tests
let test_string_of_statement () =
let tests =
[
( "42;",
"ExpressionStatement(Literal(Integer(42)))",
ExpressionStatement (Literal (Integer 42)) );
( "var x: int;",
"VariableStatement([VariableDeclaration(IntegerType, \
Identifier(\"x\"), Literal(Null))])",
VariableStatement
[ VariableDeclaration (IntegerType, Identifier "x", Literal Null) ] );
( "var x: int = 42;",
"VariableStatement([VariableDeclaration(IntegerType, \
Identifier(\"x\"), Literal(Integer(42)))])",
VariableStatement
[
VariableDeclaration
(IntegerType, Identifier "x", Literal (Integer 42));
] );
]
in
List.iter
(fun (name, expected, actual) ->
(check string) name expected (To_test.statement actual))
tests
let test_string_of_source_file () =
let tests =
[
( "1; 2 + 3;",
"SourceFile([ExpressionStatement(Literal(Integer(1))), \
ExpressionStatement(BinaryExpression(Add, Literal(Integer(2)), \
Literal(Integer(3))))])",
SourceFile
[
ExpressionStatement (Literal (Integer 1));
ExpressionStatement
(BinaryExpression (Add, Literal (Integer 2), Literal (Integer 3)));
] );
]
in
List.iter
(fun (name, expected, actual) ->
(check string) name expected (To_test.source_file actual))
tests
let () =
run "ast.print"
[
("string_of_type", [ test_case "type" `Quick test_string_of_type ]);
( "string_of_literal",
[ test_case "literal" `Quick test_string_of_literal ] );
( "string_of_unary_operator",
[ test_case "unary_operator" `Quick test_string_of_unary_operator ] );
( "string_of_binary_operator",
[ test_case "binary_operator" `Quick test_string_of_binary_operator ] );
( "string_of_expression",
[ test_case "expression" `Quick test_string_of_expression ] );
( "string_of_variable_declaration",
[
test_case "variable_declaration" `Quick
test_string_of_variable_declaration;
] );
( "string_of_statement",
[ test_case "statement" `Quick test_string_of_statement ] );
( "string_of_source_file",
[ test_case "source_file" `Quick test_string_of_source_file ] );
]
-75
View File
@@ -1,75 +0,0 @@
(* test/ast/typecheck.ml *)
open Alcotest
open Ast.Syntax
open Ast.Typecheck
let should_be_valid function_to_test tests =
List.iter
(fun (name, expected, source) ->
let actual = function_to_test source in
check (of_pp Fmt.nop) name expected actual)
tests
let test_type_of_literal () =
let tests =
[
("1", IntegerType, Integer 1);
("1.0", FloatType, Float 1.0);
("true", BooleanType, Boolean true);
("false", BooleanType, Boolean false);
("\"hello\"", StringType, String "hello");
("'c'", CharacterType, Character 'c');
("null", VoidType, Null);
]
in
should_be_valid type_of_literal tests
let test_type_of_expression () =
let tests =
[
("42", IntegerType, Literal (Integer 42));
("foo", StringType, Identifier "foo");
(* TODO Add tests *)
]
and env : environment = { variables = [ ("foo", StringType) ] } in
should_be_valid (type_of_expression env) tests
(* TODO Tests errors *)
let test_type_of_variable_declaration () =
let tests =
[
( "var bar: booleen = true;",
{ variables = [ ("bar", BooleanType) ] },
VariableDeclaration
(BooleanType, Identifier "bar", Literal (Boolean true)) );
]
and env : environment = { variables = [] } in
should_be_valid (type_of_variable_declaration env) tests
(* TODO check other case should return an error *)
let test_type_of_statement () =
let tests = [ (* TODO Add Tests *) ] and env = { variables = [] } in
should_be_valid (type_of_statement env) tests
let test_type_of_source_file () =
let tests = [ (* TODO Add Tests *) ] in
should_be_valid type_of_source_file tests
let () =
run "ast.typecheck"
[
( "type_of_literal",
[ test_case "type_of_literal" `Quick test_type_of_literal ] );
( "type_of_expression",
[ test_case "type_of_expression" `Quick test_type_of_expression ] );
( "type_of_variable_declaration",
[
test_case "type_of_variable_declaration" `Quick
test_type_of_variable_declaration;
] );
( "type_of_statement",
[ test_case "type_of_statement" `Quick test_type_of_statement ] );
( "type_of_source_file",
[ test_case "type_of_source_file" `Quick test_type_of_source_file ] );
]
-1
View File
@@ -1 +0,0 @@
;test/dune
+33 -1
View File
@@ -1 +1,33 @@
var a : caractere = '';
1 + 1;
4 * 0;
/*
Root(
SequenceStatement(
ExpressionStatement(
BinaryExpression(
Add,
Literal(
Integer(1)
),
Literal(
Integer(1)
)
)
),
ExpressionStatement(
BinaryExpression(
Multiply,
Literal(
Integer(4)
),
Literal(
Integer(0)
)
)
)
)
)
*/
+20
View File
@@ -0,0 +1,20 @@
open Alcotest
open Syntax.BinaryOperators
let test_pp_binary_operators () =
let to_check =
[
("Should return \"Add\"", "Add", Add);
("Should return \"Subtract\"", "Subtract", Subtract);
("Should return \"Multiply\"", "Multiply", Multiply);
("Should return \"Divide\"", "Divide", Divide);
]
in
List.iter
(fun (msg, expected, actual) ->
check string msg expected (pp_binary_operators actual))
to_check
let tests =
( "BinaryOperators",
[ test_case "pp_binary_operators" `Quick test_pp_binary_operators ] )
+29
View File
@@ -0,0 +1,29 @@
open Alcotest
open Syntax
let test_pp_expressions () =
let to_check =
[
( "Should return \"Literal(...)\"",
"Literal(Integer(1))",
Expressions.Literal (Literals.Integer 1) );
( "Should return \"UnaryExpression(...)\"",
"UnaryExpression(ArithmeticNegation, Literal(Integer(2)))",
Expressions.UnaryExpression
( UnaryOperators.ArithmeticNegation,
Expressions.Literal (Literals.Integer 2) ) );
( "Should return \"BinaryExpression(...)\"",
"BinaryExpression(Add, Literal(Integer(5)), Literal(Integer(10)))",
Expressions.BinaryExpression
( BinaryOperators.Add,
Expressions.Literal (Literals.Integer 5),
Expressions.Literal (Literals.Integer 10) ) );
]
in
List.iter
(fun (msg, expected, actual) ->
check string msg expected (Expressions.pp_expressions actual))
to_check
let tests =
("Expressions", [ test_case "pp_expressions" `Quick test_pp_expressions ])
+22
View File
@@ -0,0 +1,22 @@
open Alcotest
open Syntax.Literals
let test_pp_literals () =
let to_check =
[
("Should return \"Integer(1)\"", "Integer(1)", Integer 1);
("Should return \"Float(1.000000)\"", "Float(1.000000)", Float 1.0);
( "Should return \"String(\\\"Hello, World!\\\")\"",
"String(\"Hello, World!\")",
String "Hello, World!" );
("Should return \"Character('c')\"", "Character('c')", Character 'c');
("Should return \"Boolean(true)\"", "Boolean(true)", Boolean true);
("Should return \"Boolean(false)\"", "Boolean(false)", Boolean false);
]
in
List.iter
(fun (msg, expected, actual) ->
check string msg expected (pp_literals actual))
to_check
let tests = ("Literals", [ test_case "pp_literals" `Quick test_pp_literals ])
+24
View File
@@ -0,0 +1,24 @@
open Alcotest
open Syntax
let test_pp_source_files () =
let to_check =
[
( "Should return \"SourceFile(...)\"",
"SourceFile(ExpressionStatement(BinaryExpression(Add, \
Literal(Integer(1)), Literal(Integer(2)))))",
SourceFiles.SourceFile
(Statements.ExpressionStatement
(Expressions.BinaryExpression
( BinaryOperators.Add,
Expressions.Literal (Literals.Integer 1),
Expressions.Literal (Literals.Integer 2) ))) );
]
in
List.iter
(fun (name, expected, actual) ->
check string name expected (SourceFiles.pp_source_files actual))
to_check
let tests =
("SourceFiles", [ test_case "pp_source_files" `Quick test_pp_source_files ])
+27
View File
@@ -0,0 +1,27 @@
open Alcotest
open Syntax
let test_pp_statements () =
let to_check =
[
( "Should return \"ExpressionStatement(...)\"",
"ExpressionStatement(Literal(Integer(1)))",
Statements.ExpressionStatement
(Expressions.Literal (Literals.Integer 1)) );
( "Should return \"SequenceStatement(...)\"",
"SequenceStatement(ExpressionStatement(Literal(Integer(1))), \
ExpressionStatement(Literal(Float(1.000000))))",
Statements.SequenceStatement
( Statements.ExpressionStatement
(Expressions.Literal (Literals.Integer 1)),
Statements.ExpressionStatement
(Expressions.Literal (Literals.Float 1.0)) ) );
]
in
List.iter
(fun (name, expected, actual) ->
check string name expected (Statements.pp_statements actual))
to_check
let tests =
("Statements", [ test_case "pp_statements" `Quick test_pp_statements ])
+13
View File
@@ -0,0 +1,13 @@
open Alcotest
let () =
run "Syntax"
[
TestTypes.tests;
TestLiterals.tests;
TestUnaryOperators.tests;
TestBinaryOperators.tests;
TestExpressions.tests;
TestStatements.tests;
TestSourceFiles.tests;
]
+18
View File
@@ -0,0 +1,18 @@
open Alcotest
open Syntax.Types
let test_pp_types () =
let to_check =
[
("Should return \"IntegerType\"", "IntegerType", IntegerType);
("Should return \"BooleanType\"", "BooleanType", BooleanType);
("Should return \"StringType\"", "StringType", StringType);
("Should return \"CharacterType\"", "CharacterType", CharacterType);
("Should return \"VoidType\"", "VoidType", VoidType);
]
in
List.iter
(fun (msg, expected, input) -> check string msg expected (pp_types input))
to_check
let tests = ("Types", [ test_case "pp_types" `Quick test_pp_types ])
+19
View File
@@ -0,0 +1,19 @@
open Alcotest
open Syntax.UnaryOperators
let test_pp_unary_operators () =
let to_check =
[
( "Should return \"ArithmeticNegation\"",
ArithmeticNegation,
"ArithmeticNegation" );
]
in
List.iter
(fun (msg, unary_operator, expected) ->
check string msg expected (pp_unary_operators unary_operator))
to_check
let tests =
( "UnaryOperators",
[ test_case "pp_unary_operators" `Quick test_pp_unary_operators ] )
+4
View File
@@ -0,0 +1,4 @@
(test
(name TestSyntax)
(libraries Syntax alcotest)
)