mirror of
https://github.com/LucasVbr/croissant.git
synced 2026-05-16 09:06:17 +00:00
refactor: Syntax with unit tests
This commit is contained in:
@@ -1,11 +0,0 @@
|
||||
;test/ast/dune
|
||||
|
||||
(test
|
||||
(name print)
|
||||
(libraries alcotest ast)
|
||||
)
|
||||
|
||||
(test
|
||||
(name typecheck)
|
||||
(libraries alcotest ast)
|
||||
)
|
||||
@@ -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 ] );
|
||||
]
|
||||
@@ -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 ] );
|
||||
]
|
||||
+33
-1
@@ -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)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
*/
|
||||
@@ -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 ] )
|
||||
@@ -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 ])
|
||||
@@ -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 ])
|
||||
@@ -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 ])
|
||||
@@ -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 ])
|
||||
@@ -0,0 +1,13 @@
|
||||
open Alcotest
|
||||
|
||||
let () =
|
||||
run "Syntax"
|
||||
[
|
||||
TestTypes.tests;
|
||||
TestLiterals.tests;
|
||||
TestUnaryOperators.tests;
|
||||
TestBinaryOperators.tests;
|
||||
TestExpressions.tests;
|
||||
TestStatements.tests;
|
||||
TestSourceFiles.tests;
|
||||
]
|
||||
@@ -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 ])
|
||||
@@ -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 ] )
|
||||
@@ -0,0 +1,4 @@
|
||||
(test
|
||||
(name TestSyntax)
|
||||
(libraries Syntax alcotest)
|
||||
)
|
||||
Reference in New Issue
Block a user