├── .clang-format ├── .gitignore ├── .travis.yml ├── CMakeLists.cmsl ├── CMakeLists.txt ├── CMakeLists.txt.in ├── LICENSE ├── README.md ├── cmake ├── cmsl_cmake_utils.cmake ├── cmsl_directories.cmsl ├── test_utils.cmsl └── test_utils.dcmsl ├── cmake_integration └── cmake_changes.patch ├── doc ├── CMakeLists.txt ├── DeveloperGuide.md ├── Doxyfile.in ├── UserGuide.md └── builtin │ ├── .gitignore │ ├── bool.cmsl │ ├── cmake.cmsl │ ├── decl.cmsl │ ├── double.cmsl │ ├── executable.cmsl │ ├── extern.cmsl │ ├── int.cmsl │ ├── library.cmsl │ ├── list.cmsl │ ├── option.cmsl │ ├── project.cmsl │ ├── string.cmsl │ ├── version.cmsl │ └── void.cmsl ├── examples ├── CMakeLists.cmsl ├── CMakeLists.txt ├── add_declarative_file │ ├── CMakeLists.cmsl │ ├── README.md │ ├── lib.cpp │ ├── lib.dcmsl │ └── main.cpp ├── add_subdirectory_declarative │ ├── CMakeLists.cmsl │ ├── README.md │ ├── lib │ │ ├── CMakeLists.dcmsl │ │ └── lib.cpp │ └── main.cpp ├── cmake_variables_accessor │ ├── CMakeLists.cmsl │ ├── README.md │ ├── exe.dcmsl │ ├── main.cpp │ └── msg.cpp ├── cmsl_example │ ├── CMakeLists.cmsl │ ├── lib │ │ ├── CMakeLists.cmsl │ │ └── lib.cpp │ └── main.cpp ├── complete.c ├── custom_component │ ├── CMakeLists.dcmsl │ ├── README.md │ └── main.cpp ├── declarative_root_cmakelists │ ├── CMakeLists.dcmsl │ ├── README.md │ └── main.cpp ├── index.c └── module_import │ ├── CMakeLists.dcmsl │ ├── README.md │ ├── main.cpp │ └── my_fancy_exe.dcmsl ├── external └── googletest │ ├── .clang-format │ ├── .gitignore │ ├── .travis.yml │ ├── BUILD.bazel │ ├── CMakeLists.txt │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── Makefile.am │ ├── README.md │ ├── WORKSPACE │ ├── appveyor.yml │ ├── ci │ ├── build-linux-autotools.sh │ ├── build-linux-bazel.sh │ ├── build-platformio.sh │ ├── env-linux.sh │ ├── env-osx.sh │ ├── get-nprocessors.sh │ ├── install-linux.sh │ ├── install-osx.sh │ ├── install-platformio.sh │ ├── log-config.sh │ └── travis.sh │ ├── configure.ac │ ├── googlemock │ ├── CMakeLists.txt │ ├── CONTRIBUTORS │ ├── LICENSE │ ├── Makefile.am │ ├── README.md │ ├── cmake │ │ ├── gmock.pc.in │ │ └── gmock_main.pc.in │ ├── configure.ac │ ├── docs │ │ ├── CheatSheet.md │ │ ├── CookBook.md │ │ ├── DesignDoc.md │ │ ├── Documentation.md │ │ ├── ForDummies.md │ │ ├── FrequentlyAskedQuestions.md │ │ └── KnownIssues.md │ ├── include │ │ └── gmock │ │ │ ├── gmock-actions.h │ │ │ ├── gmock-cardinalities.h │ │ │ ├── gmock-function-mocker.h │ │ │ ├── gmock-generated-actions.h │ │ │ ├── gmock-generated-actions.h.pump │ │ │ ├── gmock-generated-function-mockers.h │ │ │ ├── gmock-generated-function-mockers.h.pump │ │ │ ├── gmock-generated-matchers.h │ │ │ ├── gmock-generated-matchers.h.pump │ │ │ ├── gmock-matchers.h │ │ │ ├── gmock-more-actions.h │ │ │ ├── gmock-more-matchers.h │ │ │ ├── gmock-nice-strict.h │ │ │ ├── gmock-spec-builders.h │ │ │ ├── gmock.h │ │ │ └── internal │ │ │ ├── custom │ │ │ ├── README.md │ │ │ ├── gmock-generated-actions.h │ │ │ ├── gmock-generated-actions.h.pump │ │ │ ├── gmock-matchers.h │ │ │ └── gmock-port.h │ │ │ ├── gmock-generated-internal-utils.h │ │ │ ├── gmock-generated-internal-utils.h.pump │ │ │ ├── gmock-internal-utils.h │ │ │ ├── gmock-port.h │ │ │ └── gmock-pp.h │ ├── msvc │ │ ├── 2005 │ │ │ ├── gmock.sln │ │ │ ├── gmock.vcproj │ │ │ ├── gmock_config.vsprops │ │ │ ├── gmock_main.vcproj │ │ │ └── gmock_test.vcproj │ │ ├── 2010 │ │ │ ├── gmock.sln │ │ │ ├── gmock.vcxproj │ │ │ ├── gmock_config.props │ │ │ ├── gmock_main.vcxproj │ │ │ └── gmock_test.vcxproj │ │ └── 2015 │ │ │ ├── gmock.sln │ │ │ ├── gmock.vcxproj │ │ │ ├── gmock_config.props │ │ │ ├── gmock_main.vcxproj │ │ │ └── gmock_test.vcxproj │ ├── scripts │ │ ├── fuse_gmock_files.py │ │ ├── generator │ │ │ ├── LICENSE │ │ │ ├── README │ │ │ ├── README.cppclean │ │ │ ├── cpp │ │ │ │ ├── __init__.py │ │ │ │ ├── ast.py │ │ │ │ ├── gmock_class.py │ │ │ │ ├── gmock_class_test.py │ │ │ │ ├── keywords.py │ │ │ │ ├── tokenize.py │ │ │ │ └── utils.py │ │ │ └── gmock_gen.py │ │ ├── gmock-config.in │ │ ├── gmock_doctor.py │ │ ├── upload.py │ │ └── upload_gmock.py │ ├── src │ │ ├── gmock-all.cc │ │ ├── gmock-cardinalities.cc │ │ ├── gmock-internal-utils.cc │ │ ├── gmock-matchers.cc │ │ ├── gmock-spec-builders.cc │ │ ├── gmock.cc │ │ └── gmock_main.cc │ └── test │ │ ├── BUILD.bazel │ │ ├── gmock-actions_test.cc │ │ ├── gmock-cardinalities_test.cc │ │ ├── gmock-function-mocker_nc.cc │ │ ├── gmock-function-mocker_nc_test.py │ │ ├── gmock-function-mocker_test.cc │ │ ├── gmock-generated-actions_test.cc │ │ ├── gmock-generated-function-mockers_test.cc │ │ ├── gmock-generated-internal-utils_test.cc │ │ ├── gmock-generated-matchers_test.cc │ │ ├── gmock-internal-utils_test.cc │ │ ├── gmock-matchers_test.cc │ │ ├── gmock-more-actions_test.cc │ │ ├── gmock-nice-strict_test.cc │ │ ├── gmock-port_test.cc │ │ ├── gmock-pp-string_test.cc │ │ ├── gmock-pp_test.cc │ │ ├── gmock-spec-builders_test.cc │ │ ├── gmock_all_test.cc │ │ ├── gmock_ex_test.cc │ │ ├── gmock_leak_test.py │ │ ├── gmock_leak_test_.cc │ │ ├── gmock_link2_test.cc │ │ ├── gmock_link_test.cc │ │ ├── gmock_link_test.h │ │ ├── gmock_output_test.py │ │ ├── gmock_output_test_.cc │ │ ├── gmock_output_test_golden.txt │ │ ├── gmock_stress_test.cc │ │ ├── gmock_test.cc │ │ └── gmock_test_utils.py │ ├── googletest │ ├── CMakeLists.txt │ ├── CONTRIBUTORS │ ├── LICENSE │ ├── Makefile.am │ ├── README.md │ ├── cmake │ │ ├── Config.cmake.in │ │ ├── gtest.pc.in │ │ ├── gtest_main.pc.in │ │ └── internal_utils.cmake │ ├── codegear │ │ ├── gtest.cbproj │ │ ├── gtest.groupproj │ │ ├── gtest_all.cc │ │ ├── gtest_link.cc │ │ ├── gtest_main.cbproj │ │ └── gtest_unittest.cbproj │ ├── configure.ac │ ├── docs │ │ ├── Pkgconfig.md │ │ ├── PumpManual.md │ │ ├── XcodeGuide.md │ │ ├── advanced.md │ │ ├── faq.md │ │ ├── primer.md │ │ └── samples.md │ ├── include │ │ └── gtest │ │ │ ├── gtest-death-test.h │ │ │ ├── gtest-matchers.h │ │ │ ├── gtest-message.h │ │ │ ├── gtest-param-test.h │ │ │ ├── gtest-param-test.h.pump │ │ │ ├── gtest-printers.h │ │ │ ├── gtest-spi.h │ │ │ ├── gtest-test-part.h │ │ │ ├── gtest-typed-test.h │ │ │ ├── gtest.h │ │ │ ├── gtest_pred_impl.h │ │ │ ├── gtest_prod.h │ │ │ └── internal │ │ │ ├── custom │ │ │ ├── README.md │ │ │ ├── gtest-port.h │ │ │ ├── gtest-printers.h │ │ │ └── gtest.h │ │ │ ├── gtest-death-test-internal.h │ │ │ ├── gtest-filepath.h │ │ │ ├── gtest-internal.h │ │ │ ├── gtest-param-util-generated.h │ │ │ ├── gtest-param-util-generated.h.pump │ │ │ ├── gtest-param-util.h │ │ │ ├── gtest-port-arch.h │ │ │ ├── gtest-port.h │ │ │ ├── gtest-string.h │ │ │ ├── gtest-type-util.h │ │ │ └── gtest-type-util.h.pump │ ├── m4 │ │ ├── acx_pthread.m4 │ │ └── gtest.m4 │ ├── msvc │ │ └── 2010 │ │ │ ├── gtest-md.sln │ │ │ ├── gtest-md.vcxproj │ │ │ ├── gtest-md.vcxproj.filters │ │ │ ├── gtest.sln │ │ │ ├── gtest.vcxproj │ │ │ ├── gtest.vcxproj.filters │ │ │ ├── gtest_main-md.vcxproj │ │ │ ├── gtest_main-md.vcxproj.filters │ │ │ ├── gtest_main.vcxproj │ │ │ ├── gtest_main.vcxproj.filters │ │ │ ├── gtest_prod_test-md.vcxproj │ │ │ ├── gtest_prod_test-md.vcxproj.filters │ │ │ ├── gtest_prod_test.vcxproj │ │ │ ├── gtest_prod_test.vcxproj.filters │ │ │ ├── gtest_unittest-md.vcxproj │ │ │ ├── gtest_unittest-md.vcxproj.filters │ │ │ ├── gtest_unittest.vcxproj │ │ │ └── gtest_unittest.vcxproj.filters │ ├── samples │ │ ├── prime_tables.h │ │ ├── sample1.cc │ │ ├── sample1.h │ │ ├── sample10_unittest.cc │ │ ├── sample1_unittest.cc │ │ ├── sample2.cc │ │ ├── sample2.h │ │ ├── sample2_unittest.cc │ │ ├── sample3-inl.h │ │ ├── sample3_unittest.cc │ │ ├── sample4.cc │ │ ├── sample4.h │ │ ├── sample4_unittest.cc │ │ ├── sample5_unittest.cc │ │ ├── sample6_unittest.cc │ │ ├── sample7_unittest.cc │ │ ├── sample8_unittest.cc │ │ └── sample9_unittest.cc │ ├── scripts │ │ ├── common.py │ │ ├── fuse_gtest_files.py │ │ ├── gen_gtest_pred_impl.py │ │ ├── gtest-config.in │ │ ├── pump.py │ │ ├── release_docs.py │ │ ├── upload.py │ │ └── upload_gtest.py │ ├── src │ │ ├── gtest-all.cc │ │ ├── gtest-death-test.cc │ │ ├── gtest-filepath.cc │ │ ├── gtest-internal-inl.h │ │ ├── gtest-matchers.cc │ │ ├── gtest-port.cc │ │ ├── gtest-printers.cc │ │ ├── gtest-test-part.cc │ │ ├── gtest-typed-test.cc │ │ ├── gtest.cc │ │ └── gtest_main.cc │ ├── test │ │ ├── BUILD.bazel │ │ ├── googletest-break-on-failure-unittest.py │ │ ├── googletest-break-on-failure-unittest_.cc │ │ ├── googletest-catch-exceptions-test.py │ │ ├── googletest-catch-exceptions-test_.cc │ │ ├── googletest-color-test.py │ │ ├── googletest-color-test_.cc │ │ ├── googletest-death-test-test.cc │ │ ├── googletest-death-test_ex_test.cc │ │ ├── googletest-env-var-test.py │ │ ├── googletest-env-var-test_.cc │ │ ├── googletest-filepath-test.cc │ │ ├── googletest-filter-unittest.py │ │ ├── googletest-filter-unittest_.cc │ │ ├── googletest-json-outfiles-test.py │ │ ├── googletest-json-output-unittest.py │ │ ├── googletest-list-tests-unittest.py │ │ ├── googletest-list-tests-unittest_.cc │ │ ├── googletest-listener-test.cc │ │ ├── googletest-message-test.cc │ │ ├── googletest-options-test.cc │ │ ├── googletest-output-test-golden-lin.txt │ │ ├── googletest-output-test.py │ │ ├── googletest-output-test_.cc │ │ ├── googletest-param-test-invalid-name1-test.py │ │ ├── googletest-param-test-invalid-name1-test_.cc │ │ ├── googletest-param-test-invalid-name2-test.py │ │ ├── googletest-param-test-invalid-name2-test_.cc │ │ ├── googletest-param-test-test.cc │ │ ├── googletest-param-test-test.h │ │ ├── googletest-param-test2-test.cc │ │ ├── googletest-port-test.cc │ │ ├── googletest-printers-test.cc │ │ ├── googletest-shuffle-test.py │ │ ├── googletest-shuffle-test_.cc │ │ ├── googletest-test-part-test.cc │ │ ├── googletest-test2_test.cc │ │ ├── googletest-throw-on-failure-test.py │ │ ├── googletest-throw-on-failure-test_.cc │ │ ├── googletest-uninitialized-test.py │ │ ├── googletest-uninitialized-test_.cc │ │ ├── gtest-typed-test2_test.cc │ │ ├── gtest-typed-test_test.cc │ │ ├── gtest-typed-test_test.h │ │ ├── gtest-unittest-api_test.cc │ │ ├── gtest_all_test.cc │ │ ├── gtest_assert_by_exception_test.cc │ │ ├── gtest_environment_test.cc │ │ ├── gtest_help_test.py │ │ ├── gtest_help_test_.cc │ │ ├── gtest_json_test_utils.py │ │ ├── gtest_list_output_unittest.py │ │ ├── gtest_list_output_unittest_.cc │ │ ├── gtest_main_unittest.cc │ │ ├── gtest_no_test_unittest.cc │ │ ├── gtest_pred_impl_unittest.cc │ │ ├── gtest_premature_exit_test.cc │ │ ├── gtest_prod_test.cc │ │ ├── gtest_repeat_test.cc │ │ ├── gtest_skip_test.cc │ │ ├── gtest_sole_header_test.cc │ │ ├── gtest_stress_test.cc │ │ ├── gtest_test_macro_stack_footprint_test.cc │ │ ├── gtest_test_utils.py │ │ ├── gtest_testbridge_test.py │ │ ├── gtest_testbridge_test_.cc │ │ ├── gtest_throw_on_failure_ex_test.cc │ │ ├── gtest_unittest.cc │ │ ├── gtest_xml_outfile1_test_.cc │ │ ├── gtest_xml_outfile2_test_.cc │ │ ├── gtest_xml_outfiles_test.py │ │ ├── gtest_xml_output_unittest.py │ │ ├── gtest_xml_output_unittest_.cc │ │ ├── gtest_xml_test_utils.py │ │ ├── production.cc │ │ └── production.h │ └── xcode │ │ ├── Config │ │ ├── DebugProject.xcconfig │ │ ├── FrameworkTarget.xcconfig │ │ ├── General.xcconfig │ │ ├── ReleaseProject.xcconfig │ │ ├── StaticLibraryTarget.xcconfig │ │ └── TestTarget.xcconfig │ │ ├── Resources │ │ └── Info.plist │ │ ├── Samples │ │ └── FrameworkSample │ │ │ ├── Info.plist │ │ │ ├── WidgetFramework.xcodeproj │ │ │ └── project.pbxproj │ │ │ ├── runtests.sh │ │ │ ├── widget.cc │ │ │ ├── widget.h │ │ │ └── widget_test.cc │ │ ├── Scripts │ │ ├── runtests.sh │ │ └── versiongenerate.py │ │ └── gtest.xcodeproj │ │ └── project.pbxproj │ ├── library.json │ └── platformio.ini ├── facade ├── cmake_facade.hpp └── visibility.hpp ├── scripts ├── build_cmake.sh └── builtin_token_providers_generator.py ├── source ├── CMakeLists.cmsl ├── CMakeLists.txt ├── ast │ ├── CMakeLists.cmsl │ ├── CMakeLists.dcmsl │ ├── CMakeLists.txt │ ├── ast_node.hpp │ ├── ast_node_visitor.hpp │ ├── block_node.cpp │ ├── block_node.hpp │ ├── break_node.cpp │ ├── break_node.hpp │ ├── class_node.cpp │ ├── class_node.hpp │ ├── conditional_node.cpp │ ├── conditional_node.hpp │ ├── designated_initializers_node.cpp │ ├── designated_initializers_node.hpp │ ├── enum_node.cpp │ ├── enum_node.hpp │ ├── escaped_string_builder.hpp │ ├── for_node.cpp │ ├── for_node.hpp │ ├── if_else_node.cpp │ ├── if_else_node.hpp │ ├── import_node.cpp │ ├── import_node.hpp │ ├── infix_nodes.hpp │ ├── namespace_node.cpp │ ├── namespace_node.hpp │ ├── parameter_declaration.hpp │ ├── parse_errors_observer.hpp │ ├── parser.cpp │ ├── parser.hpp │ ├── parser_utils.cpp │ ├── parser_utils.hpp │ ├── qualified_name.cpp │ ├── qualified_name.hpp │ ├── return_node.cpp │ ├── return_node.hpp │ ├── ternary_operator_node.cpp │ ├── ternary_operator_node.hpp │ ├── translation_unit_node.cpp │ ├── translation_unit_node.hpp │ ├── type_parser.cpp │ ├── type_parser.hpp │ ├── type_parsing_result.hpp │ ├── type_representation.cpp │ ├── type_representation.hpp │ ├── user_function_node.cpp │ ├── user_function_node.hpp │ ├── variable_declaration_node.cpp │ ├── variable_declaration_node.hpp │ ├── while_node.cpp │ └── while_node.hpp ├── common │ ├── CMakeLists.cmsl │ ├── CMakeLists.dcmsl │ ├── CMakeLists.txt │ ├── algorithm.hpp │ ├── assert.hpp │ ├── dumper_utils.cpp │ ├── dumper_utils.hpp │ ├── enum_class_utils.hpp │ ├── int_alias.hpp │ ├── overloaded.hpp │ ├── source_location.hpp │ ├── source_view.cpp │ ├── source_view.hpp │ ├── string.hpp │ ├── strings_container.hpp │ ├── strings_container_impl.cpp │ └── strings_container_impl.hpp ├── decl_ast │ ├── CMakeLists.dcmsl │ ├── CMakeLists.txt │ ├── ast_node.hpp │ ├── ast_node_visitor.hpp │ ├── ast_nodes.hpp │ ├── parse_errors_reporter.cpp │ ├── parse_errors_reporter.hpp │ ├── parser.cpp │ └── parser.hpp ├── decl_sema │ ├── CMakeLists.dcmsl │ ├── CMakeLists.txt │ ├── builtin_decl_namespace_context.cpp │ ├── builtin_decl_namespace_context.hpp │ ├── component_creation_sema_function.hpp │ ├── decl_namespace_types_accessor.hpp │ ├── declarative_import_handler.hpp │ ├── sema_builder_ast_visitor.cpp │ ├── sema_builder_ast_visitor.hpp │ ├── sema_node_visitor.hpp │ └── sema_nodes.hpp ├── errors │ ├── CMakeLists.cmsl │ ├── CMakeLists.dcmsl │ ├── CMakeLists.txt │ ├── error.hpp │ ├── errors_observer.cpp │ └── errors_observer.hpp ├── exec │ ├── CMakeLists.cmsl │ ├── CMakeLists.dcmsl │ ├── CMakeLists.txt │ ├── builtin_function_caller.cpp │ ├── builtin_function_caller.hpp │ ├── builtin_identifiers_observer.cpp │ ├── builtin_identifiers_observer.hpp │ ├── compiled_source.cpp │ ├── compiled_source.hpp │ ├── cross_translation_unit_static_variables.cpp │ ├── cross_translation_unit_static_variables.hpp │ ├── cross_translation_unit_static_variables_accessor.hpp │ ├── declarative_component_instance_creator.cpp │ ├── declarative_component_instance_creator.hpp │ ├── declarative_component_property_instances_collecting_visitor.cpp │ ├── declarative_component_property_instances_collecting_visitor.hpp │ ├── declarative_source_compiler.cpp │ ├── declarative_source_compiler.hpp │ ├── execution.cpp │ ├── execution.hpp │ ├── execution_context.cpp │ ├── execution_context.hpp │ ├── expression_evaluation_context.hpp │ ├── expression_evaluation_visitor.cpp │ ├── expression_evaluation_visitor.hpp │ ├── extern_argument_parser.cpp │ ├── extern_argument_parser.hpp │ ├── function_caller.hpp │ ├── global_executor.cpp │ ├── global_executor.hpp │ ├── identifiers_context.hpp │ ├── instance │ │ ├── complex_unnamed_instance.cpp │ │ ├── complex_unnamed_instance.hpp │ │ ├── enum_constant_value.hpp │ │ ├── extern_value.cpp │ │ ├── extern_value.hpp │ │ ├── instance.hpp │ │ ├── instance_factory.cpp │ │ ├── instance_factory.hpp │ │ ├── instance_reference.cpp │ │ ├── instance_reference.hpp │ │ ├── instance_value_accessor.cpp │ │ ├── instance_value_accessor.hpp │ │ ├── instance_value_alternative.hpp │ │ ├── instance_value_observer.hpp │ │ ├── instance_value_variant.cpp │ │ ├── instance_value_variant.hpp │ │ ├── instances_holder.cpp │ │ ├── instances_holder.hpp │ │ ├── instances_holder_interface.hpp │ │ ├── list_value.cpp │ │ ├── list_value.hpp │ │ ├── list_value_utils.cpp │ │ ├── list_value_utils.hpp │ │ ├── observable_instance.cpp │ │ ├── observable_instance.hpp │ │ ├── option_value.cpp │ │ ├── option_value.hpp │ │ ├── project_value.cpp │ │ ├── project_value.hpp │ │ ├── simple_unnamed_instance.cpp │ │ ├── simple_unnamed_instance.hpp │ │ ├── target_value.cpp │ │ ├── target_value.hpp │ │ ├── version_value.cpp │ │ └── version_value.hpp │ ├── module_sema_tree_provider.hpp │ ├── module_static_variables_initializer.hpp │ ├── parameter_alternatives_getter.hpp │ ├── scope_context.cpp │ ├── scope_context.hpp │ ├── source_compiler.cpp │ ├── source_compiler.hpp │ └── static_variables_initializer.hpp ├── lexer │ ├── CMakeLists.cmsl │ ├── CMakeLists.dcmsl │ ├── CMakeLists.txt │ ├── lexer.cpp │ ├── lexer.hpp │ ├── source_location_manipulator.cpp │ ├── source_location_manipulator.hpp │ ├── token.cpp │ ├── token.hpp │ ├── token_type.cpp │ └── token_type.hpp ├── parse │ ├── CMakeLists.cmsl │ ├── CMakeLists.dcmsl │ ├── CMakeLists.txt │ ├── parse_errors_observer.hpp │ ├── parser_utils.cpp │ └── parser_utils.hpp └── sema │ ├── CMakeLists.cmsl │ ├── CMakeLists.txt │ ├── add_declarative_file_semantic_handler.hpp │ ├── add_subdirectory_semantic_handler.hpp │ ├── block_node_manipulator.cpp │ ├── block_node_manipulator.hpp │ ├── builtin_cmake_namespace_context.cpp │ ├── builtin_cmake_namespace_context.hpp │ ├── builtin_context_base.cpp │ ├── builtin_context_base.hpp │ ├── builtin_function_kind.hpp │ ├── builtin_sema_context.cpp │ ├── builtin_sema_context.hpp │ ├── builtin_sema_function.hpp │ ├── builtin_token_provider.cpp │ ├── builtin_token_provider.hpp │ ├── builtin_types_accessor.hpp │ ├── cmake_namespace_types_accessor.hpp │ ├── dumper.cpp │ ├── dumper.hpp │ ├── enum_creator.cpp │ ├── enum_creator.hpp │ ├── enum_type.hpp │ ├── enum_values_context.cpp │ ├── enum_values_context.hpp │ ├── factories.cpp │ ├── factories.hpp │ ├── factories_provider.cpp │ ├── factories_provider.hpp │ ├── failed_initialization_errors_reporters.cpp │ ├── failed_initialization_errors_reporters.hpp │ ├── function_lookup_result.hpp │ ├── function_signature.cpp │ ├── function_signature.hpp │ ├── functions_context.cpp │ ├── functions_context.hpp │ ├── generic_type_creation_utils.cpp │ ├── generic_type_creation_utils.hpp │ ├── homogeneous_generic_type.cpp │ ├── homogeneous_generic_type.hpp │ ├── identifier_info.hpp │ ├── identifiers_context.cpp │ ├── identifiers_context.hpp │ ├── identifiers_index_provider.hpp │ ├── import_handler.hpp │ ├── overload_resolution.cpp │ ├── overload_resolution.hpp │ ├── qualified_contextes.cpp │ ├── qualified_contextes.hpp │ ├── qualified_contextes_refs.hpp │ ├── qualified_contexts_dumper.cpp │ ├── qualified_contexts_dumper.hpp │ ├── qualified_entries_finder.hpp │ ├── sema_builder.cpp │ ├── sema_builder.hpp │ ├── sema_builder_ast_visitor.cpp │ ├── sema_builder_ast_visitor.hpp │ ├── sema_context.hpp │ ├── sema_context_impl.cpp │ ├── sema_context_impl.hpp │ ├── sema_function.hpp │ ├── sema_node.cpp │ ├── sema_node.hpp │ ├── sema_node_visitor.hpp │ ├── sema_nodes.hpp │ ├── sema_tree_building_context.hpp │ ├── sema_type.cpp │ ├── sema_type.hpp │ ├── type_builder.cpp │ ├── type_builder.hpp │ ├── type_member_info.hpp │ ├── types_context.cpp │ ├── types_context.hpp │ ├── user_sema_function.hpp │ ├── variable_initialization_checker.cpp │ ├── variable_initialization_checker.hpp │ └── variable_initialization_issue.hpp ├── test ├── CMakeLists.cmsl ├── CMakeLists.txt ├── ast │ ├── CMakeLists.cmsl │ ├── CMakeLists.txt │ ├── DISABLED_CMakeLists.dcmsl │ ├── escaped_string_builder_test.cpp │ ├── mock │ │ └── ast_node_mock.hpp │ ├── parser_error_test.cpp │ └── parser_test.cpp ├── common │ ├── CMakeLists.cmsl │ ├── CMakeLists.dcmsl │ ├── CMakeLists.txt │ ├── tokens.cpp │ └── tokens.hpp ├── decl_ast │ ├── CMakeLists.dcmsl │ ├── CMakeLists.txt │ └── parser_test.cpp ├── errors_observer │ ├── CMakeLists.cmsl │ ├── CMakeLists.dcmsl │ ├── CMakeLists.txt │ └── errors_observer.cpp ├── errors_observer_mock │ ├── CMakeLists.cmsl │ ├── CMakeLists.txt │ ├── errors_observer_mock.cpp │ └── errors_observer_mock.hpp ├── exec │ ├── CMakeLists.cmsl │ ├── CMakeLists.txt │ ├── DISABLED_CMakeLists.dcmsl │ ├── add_subdirectory_test │ │ ├── add_subdirectory_smoke_test.cpp │ │ ├── foo │ │ │ └── CMakeLists.cmsl │ │ └── import │ │ │ ├── CMakeLists.cmsl │ │ │ └── foo.cmsl │ ├── auto_type_smoke_test.cpp │ ├── bool_type_smoke_test.cpp │ ├── break_smoke_test.cpp │ ├── builtin_function_caller_test.cpp │ ├── class_smoke_test.cpp │ ├── cmake_namespace_smoke_test.cpp │ ├── comments_smoke_test.cpp │ ├── decl_executable_smoke_test.cpp │ ├── decl_shared_library_smoke_test.cpp │ ├── decl_static_library_smoke_test.cpp │ ├── declarative │ │ ├── custom_static_library.dcmsl │ │ ├── custom_static_library_for_import.dcmsl │ │ ├── custom_static_library_with_list_appending.dcmsl │ │ ├── custom_static_library_with_string_appending.dcmsl │ │ ├── declarative_format_smoke_test.cpp │ │ ├── executable.dcmsl │ │ ├── foo │ │ │ └── CMakeLists.dcmsl │ │ ├── import_custom_static_library.dcmsl │ │ ├── static_library.dcmsl │ │ ├── static_library_with_cmake_variables.dcmsl │ │ ├── static_library_with_name_prefix.dcmsl │ │ ├── static_library_with_name_suffix.dcmsl │ │ ├── static_library_with_not_existing_cmake_variable.dcmsl │ │ └── test_executable.dcmsl │ ├── designated_initializers_smoke_test.cpp │ ├── double_type_smoke_test.cpp │ ├── enum_smoke_test.cpp │ ├── executable_smoke_test.cpp │ ├── expression_evaluation_visitor_test.cpp │ ├── extern_type_smoke_test.cpp │ ├── fatal_error_smoke_test.cpp │ ├── for_loop_smoke_test.cpp │ ├── forwarding_lists_type_smoke_test.cpp │ ├── function_smoke_test.cpp │ ├── if_else_smoke_test.cpp │ ├── import_test │ │ ├── baz.cmsl │ │ ├── foo.cmsl │ │ └── import_smoke_test.cpp │ ├── instance_value_variant_test.cpp │ ├── int_type_smoke_test.cpp │ ├── library_smoke_test.cpp │ ├── list_type_smoke_test.cpp │ ├── mock │ │ ├── function_caller_mock.hpp │ │ ├── identifiers_context_mock.hpp │ │ ├── instance_mock.hpp │ │ └── instances_holder_mock.hpp │ ├── namespaces_smoke_test.cpp │ ├── object_slicing_smoke_test.cpp │ ├── option_smoke_test.cpp │ ├── product_type_smoke_test.cpp │ ├── product_type_type_smoke_test.cpp │ ├── project_smoke_test.cpp │ ├── reference_smoke_tests.cpp │ ├── scopes_smoke_test.cpp │ ├── smoke_test_fixture.hpp │ ├── static_variables_smoke_test.cpp │ ├── string_type_smoke_tests.cpp │ ├── ternary_operator_smoke_test.cpp │ ├── variable_type_deduction.cpp │ ├── version_type_smoke_tests.cpp │ ├── void_type_smoke_test.cpp │ └── while_loop_smoke_test.cpp ├── integration_tests │ ├── build_cmake_with_cmakesl_support.py │ ├── build_cmakesl_using_cmakesl.py │ └── run_integration_tests.py ├── lexer │ ├── CMakeLists.cmsl │ ├── CMakeLists.dcmsl │ ├── CMakeLists.txt │ └── lexer_test.cpp ├── lexer_error │ ├── CMakeLists.cmsl │ ├── CMakeLists.dcmsl │ ├── CMakeLists.txt │ └── lexer_error_test.cpp ├── mock │ ├── cmake_facade_mock.hpp │ └── strings_container_mock.hpp ├── sema │ ├── CMakeLists.cmsl │ ├── CMakeLists.dcmsl │ ├── CMakeLists.txt │ ├── identifiers_context_test.cpp │ ├── mock │ │ ├── add_declarative_file_semantic_handler_mock.hpp │ │ ├── add_subdirectory_semantic_handler_mock.hpp │ │ ├── enum_values_context_mock.hpp │ │ ├── expression_node_mock.hpp │ │ ├── functions_context_mock.hpp │ │ ├── identifiers_context_mock.hpp │ │ ├── import_handler_mock.hpp │ │ ├── sema_context_mock.hpp │ │ ├── sema_function_mock.hpp │ │ └── types_context_mock.hpp │ ├── overload_resolution_test.cpp │ ├── sema_builder_ast_visitor_test.cpp │ ├── sema_dumper_smoke_test.cpp │ └── variable_initialization_check_test.cpp ├── source_location_manipulator │ ├── CMakeLists.cmsl │ ├── CMakeLists.dcmsl │ ├── CMakeLists.txt │ └── source_location_test.cpp └── tools │ ├── CMakeLists.cmsl │ ├── CMakeLists.txt │ └── smoke │ ├── CMakeLists.txt │ ├── complete │ ├── CMakeLists.txt │ └── complete_test.cpp │ └── index │ ├── CMakeLists.txt │ └── indexer_test.cpp └── tools ├── CMakeLists.cmsl ├── CMakeLists.txt ├── cmakesl ├── CMakeLists.cmsl ├── CMakeLists.txt └── main.cpp └── lib ├── CMakeLists.cmsl ├── CMakeLists.txt ├── cmsl_complete.cpp ├── cmsl_complete.hpp ├── cmsl_index.cpp ├── cmsl_index.hpp ├── cmsl_parse_source.cpp ├── cmsl_parse_source.hpp ├── cmsl_parsed_source.cpp ├── cmsl_parsed_source.hpp ├── completer.cpp ├── completer.hpp ├── completion_context_finder.cpp ├── completion_context_finder.hpp ├── completion_contextes.hpp ├── completion_contextes_visitor.cpp ├── completion_contextes_visitor.hpp ├── identifier_names_collector.cpp ├── identifier_names_collector.hpp ├── indexing_visitor.cpp ├── indexing_visitor.hpp ├── type_names_collector.cpp └── type_names_collector.hpp /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | # This configuration requires clang-format version 6.0 exactly. 3 | BasedOnStyle: Mozilla 4 | AlignOperands: false 5 | AllowShortFunctionsOnASingleLine: InlineOnly 6 | AlwaysBreakAfterDefinitionReturnType: None 7 | AlwaysBreakAfterReturnType: None 8 | BinPackArguments: true 9 | BinPackParameters: true 10 | BraceWrapping: 11 | AfterClass: true 12 | AfterEnum: true 13 | AfterFunction: true 14 | AfterStruct: true 15 | AfterUnion: true 16 | BreakBeforeBraces: Custom 17 | ColumnLimit: 79 18 | IndentPPDirectives: AfterHash 19 | SortUsingDeclarations: false 20 | SpaceAfterTemplateKeyword: true 21 | ... 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | b/* 3 | cmake-build-* 4 | .idea/* 5 | *.user 6 | *.pyc 7 | -------------------------------------------------------------------------------- /CMakeLists.txt.in: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.2) 2 | 3 | project(googletest-download NONE) 4 | 5 | include(ExternalProject) 6 | ExternalProject_Add(googletest 7 | GIT_REPOSITORY https://github.com/google/googletest.git 8 | GIT_TAG master 9 | SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" 10 | BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" 11 | CONFIGURE_COMMAND "" 12 | BUILD_COMMAND "" 13 | INSTALL_COMMAND "" 14 | TEST_COMMAND "" 15 | ) 16 | -------------------------------------------------------------------------------- /cmake/cmsl_cmake_utils.cmake: -------------------------------------------------------------------------------- 1 | function(cmsl_add_test) 2 | set(options) 3 | set(oneValueArgs NAME) 4 | set(multiValueArgs SOURCES INCLUDE_DIRS LIBRARIES) 5 | cmake_parse_arguments(CMSL_ADD_TEST "${options}" "${oneValueArgs}" 6 | "${multiValueArgs}" ${ARGN} ) 7 | 8 | set(test_name ${CMSL_ADD_TEST_NAME}_cmakesl_test) 9 | 10 | add_executable(${test_name} ${CMSL_ADD_TEST_SOURCES}) 11 | 12 | target_link_libraries(${test_name} 13 | PRIVATE 14 | gmock_main 15 | ${CMSL_ADD_TEST_LIBRARIES} 16 | ) 17 | 18 | target_include_directories(${test_name} 19 | PRIVATE 20 | ${CMSL_ADD_TEST_INCLUDE_DIRS} 21 | ) 22 | 23 | target_compile_options(${test_name} 24 | PRIVATE 25 | ${CMAKESL_ADDITIONAL_COMPILER_FLAGS} 26 | ) 27 | 28 | add_test(NAME ${test_name} COMMAND ${test_name}) 29 | endfunction() 30 | -------------------------------------------------------------------------------- /cmake/cmsl_directories.cmsl: -------------------------------------------------------------------------------- 1 | namespace cmsl { 2 | export auto root_dir = cmake::root_source_dir(); 3 | export auto source_dir = cmake::root_source_dir() + "/source"; 4 | export auto facade_dir = cmake::root_source_dir() + "/facade"; 5 | export auto scripts_dir = cmake::root_source_dir() + "/scripts"; 6 | export auto doc_dir = cmake::root_source_dir() + "/doc"; 7 | export auto tools_dir = cmake::root_source_dir() + "/tools"; 8 | export auto test_dir = cmake::root_source_dir() + "/test"; 9 | } 10 | -------------------------------------------------------------------------------- /cmake/test_utils.dcmsl: -------------------------------------------------------------------------------- 1 | component cmsl_test_executable : test_executable { 2 | name_suffix = "_cmakesl_test" 3 | 4 | dependencies.public = [ 5 | "gmock_main" 6 | ] 7 | 8 | compile_options.public 9 | = cmake_variables.CMAKESL_ADDITIONAL_COMPILER_FLAGS.as_list 10 | } 11 | -------------------------------------------------------------------------------- /doc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(Doxygen) 2 | if (DOXYGEN_FOUND) 3 | set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in) 4 | set(CONFIGURED_COXYGEN_CONFIG_FILE ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) 5 | set(DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/doc) 6 | set(DOXYGEN_HTML_OUT ${DOXYGEN_OUTPUT_DIR}/html) 7 | 8 | configure_file(${DOXYGEN_IN} ${CONFIGURED_COXYGEN_CONFIG_FILE} @ONLY) 9 | 10 | add_custom_target(cmakesl_doc ALL 11 | COMMAND 12 | ${DOXYGEN_EXECUTABLE} ${CONFIGURED_COXYGEN_CONFIG_FILE} 13 | WORKING_DIRECTORY 14 | ${CMAKE_CURRENT_BINARY_DIR} 15 | COMMENT 16 | "Generating API documentation with Doxygen" 17 | VERBATIM 18 | ) 19 | 20 | install( 21 | DIRECTORY 22 | ${DOXYGEN_HTML_OUT} 23 | DESTINATION 24 | doc/cmakesl 25 | ) 26 | 27 | else () 28 | message("Doxygen need to be installed to generate the doxygen documentation") 29 | endif () 30 | 31 | install( 32 | DIRECTORY 33 | builtin 34 | DESTINATION 35 | doc/cmakesl 36 | FILES_MATCHING PATTERN 37 | "*.cmsl" 38 | ) 39 | -------------------------------------------------------------------------------- /doc/Doxyfile.in: -------------------------------------------------------------------------------- 1 | DOXYFILE_ENCODING = UTF-8 2 | PROJECT_NAME = "CMakeSL builtin types documentation" 3 | EXTENSION_MAPPING = .cmsl=C++ 4 | CASE_SENSE_NAMES = YES 5 | FILE_PATTERNS = *.cmsl 6 | GENERATE_LATEX = NO 7 | WARN_AS_ERROR = YES 8 | 9 | OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/ 10 | INPUT = @CMAKE_CURRENT_SOURCE_DIR@/builtin/ 11 | -------------------------------------------------------------------------------- /doc/builtin/.gitignore: -------------------------------------------------------------------------------- 1 | html/ 2 | latex/ 3 | -------------------------------------------------------------------------------- /doc/builtin/decl.cmsl: -------------------------------------------------------------------------------- 1 | /** \brief The builtin decl namespace. 2 | * Declares types of objects created by declarative part of CMakeSL. 3 | * 4 | */ 5 | namespace decl { 6 | 7 | /** 8 | * \brief Represents a generic lists of values, divided by forwarding strategy. 9 | */ 10 | class forwarding_lists 11 | { 12 | list interface; 13 | list public; 14 | list private; 15 | }; 16 | 17 | /** 18 | * \brief Possible product types. 19 | */ 20 | enum product_type 21 | { 22 | executable, // product_type::executable 23 | static_library, // product_type::static_library 24 | shared_library // product_type::shared_library 25 | }; 26 | 27 | /** 28 | * \brief Represents a product built by the buildsystem (e.g. library, 29 | * executable). 30 | */ 31 | class product 32 | { 33 | product_type type; 34 | string name; 35 | string name_prefix; 36 | string name_suffix; 37 | forwarding_lists files; 38 | forwarding_lists include_dirs; 39 | forwarding_lists compile_definitions; 40 | forwarding_lists compile_options; 41 | forwarding_lists dependencies; 42 | }; 43 | 44 | class executable : product 45 | { 46 | }; 47 | 48 | class test_executable : product 49 | { 50 | }; 51 | 52 | class shared_library : product 53 | { 54 | }; 55 | 56 | class static_library : product 57 | { 58 | }; 59 | } 60 | -------------------------------------------------------------------------------- /doc/builtin/extern.cmsl: -------------------------------------------------------------------------------- 1 | /** \brief The builtin generic extern type. 2 | * 3 | * Object of an extern type represents a value passed in the command line CMake 4 | * invocation. \tparam ValueType can be one of: bool, int, double or string. 5 | */ 6 | template 7 | class extern 8 | 9 | { 10 | public: 11 | /** \brief Default constructor. 12 | * 13 | * \param name Name of the argument passed in the CMake command line. 14 | */ 15 | extern(string name); 16 | 17 | /** \brief Check whether an argument has been passed in the CMake command 18 | * line. 19 | * 20 | * \return true if argument has been passed, false otherwise. 21 | */ 22 | bool has_value(); 23 | 24 | /** \brief Check whether an argument has been passed in the CMake command 25 | * line. 26 | * 27 | * \return true if argument has been passed, false otherwise. 28 | */ 29 | ValueType value(); 30 | }; 31 | -------------------------------------------------------------------------------- /doc/builtin/option.cmsl: -------------------------------------------------------------------------------- 1 | namespace cmake { 2 | /** \brief The builtin option type. 3 | */ 4 | class option 5 | { 6 | public: 7 | /** \brief Constructor. 8 | * 9 | * Sets value to false. 10 | * 11 | * \param name The name of the option. 12 | * \param description The description to be initialized with. 13 | */ 14 | option(string name, string description); 15 | 16 | /** \brief Constructor. 17 | * 18 | * Sets value to \p value. 19 | * 20 | * \param name The name of the option. 21 | * \param description The description to be initialized with. 22 | * \param value The value to be initialized with. 23 | */ 24 | option(string name, string description, bool value); 25 | 26 | /** \brief Value getter. 27 | * 28 | * \return The option value. 29 | */ 30 | bool value(); 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /doc/builtin/project.cmsl: -------------------------------------------------------------------------------- 1 | namespace cmake { 2 | /** \brief The builtin project type. 3 | */ 4 | class project 5 | { 6 | public: 7 | /** \brief Initializes and registers a new project. 8 | * 9 | * @param name The name of the project. 10 | */ 11 | project(string name); 12 | 13 | /** \brief Initializes and registers an executable target in scope of this 14 | * project. 15 | * 16 | * @param name A name of the executable. 17 | * @param sources Source files of the executable. 18 | * @return A created executable object. 19 | */ 20 | executable add_executable(string name, list sources); 21 | 22 | /** \brief Initializes and registers an static library target in scope of 23 | * this project. 24 | * 25 | * @param name A name of the library. 26 | * @param sources Source files of the library. 27 | * @return A created library object. 28 | */ 29 | library add_library(string name, list sources); 30 | 31 | /** \brief Searches for a library, with a given name, in the project. 32 | * 33 | * @param name A name of the library. 34 | * @return The found library. 35 | */ 36 | library find_library(string name); 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /doc/builtin/void.cmsl: -------------------------------------------------------------------------------- 1 | /** \brief The builtin void type. 2 | * 3 | * Instance of this type can not be created. 4 | */ 5 | class void{}; 6 | -------------------------------------------------------------------------------- /examples/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | import "cmake/cmsl_directories.cmsl"; 2 | 3 | class example_adder 4 | { 5 | cmake::project p; 6 | cmake::library cmsl_tools; 7 | 8 | void add(string name, list sources) 9 | { 10 | auto include_dirs = { cmsl::tools_dir, cmsl::source_dir }; 11 | 12 | auto example = p.add_executable(name, sources); 13 | example.link_to(cmsl_tools); 14 | example.include_directories(include_dirs); 15 | cmake::install(example); 16 | } 17 | }; 18 | 19 | void main(cmake::library& cmsl_tools) 20 | { 21 | auto p = cmake::project("examples"); 22 | example_adder examples = { .p = p, .cmsl_tools = cmsl_tools }; 23 | 24 | examples.add("complete", { "complete.c" }); 25 | examples.add("index", { "index.c" }); 26 | } 27 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(examples) 2 | 3 | include_directories(${CMAKESL_SOURCES_DIR}) 4 | 5 | add_executable(complete complete.c) 6 | target_link_libraries(complete cmsl_tools) 7 | target_include_directories(complete PRIVATE ${CMAKESL_DIR}/tools) 8 | 9 | add_executable(index index.c) 10 | target_link_libraries(index cmsl_tools) 11 | target_include_directories(index PRIVATE ${CMAKESL_DIR}/tools) 12 | 13 | install(TARGETS complete index DESTINATION bin) 14 | -------------------------------------------------------------------------------- /examples/add_declarative_file/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | cmake::minimum_required(cmake::version(3, 14, 3)); 4 | 5 | auto p = cmake::project("add_declarative_file example"); 6 | 7 | auto lib = add_declarative_file("lib.dcmsl"); 8 | 9 | auto exe = p.add_executable("exe", { "main.cpp" }); 10 | exe.link_to(lib); 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /examples/add_declarative_file/README.md: -------------------------------------------------------------------------------- 1 | # Example usage of `add_declarative_file()` 2 | -------------------------------------------------------------------------------- /examples/add_declarative_file/lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | std::string get_message() 4 | { 5 | return "Hello from add_declarative_file() function example!\n"; 6 | } 7 | -------------------------------------------------------------------------------- /examples/add_declarative_file/lib.dcmsl: -------------------------------------------------------------------------------- 1 | static_library { 2 | name = "lib" 3 | 4 | files.public = [ 5 | "lib.cpp" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /examples/add_declarative_file/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | std::string get_message(); 4 | 5 | int main() 6 | { 7 | std::cout << get_message(); 8 | } 9 | -------------------------------------------------------------------------------- /examples/add_subdirectory_declarative/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | cmake::minimum_required(cmake::version(3, 14, 3)); 4 | 5 | auto p = cmake::project("add_subdirectory example"); 6 | 7 | auto lib = add_subdirectory("lib"); 8 | 9 | auto exe = p.add_executable("exe", { "main.cpp" }); 10 | exe.link_to(lib); 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /examples/add_subdirectory_declarative/README.md: -------------------------------------------------------------------------------- 1 | # Example usage of `add_subdirectory()` which contains a declarative `CMakeLists.dcmsl` -------------------------------------------------------------------------------- /examples/add_subdirectory_declarative/lib/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | static_library { 2 | name = "lib" 3 | 4 | files.public = [ 5 | "lib.cpp" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /examples/add_subdirectory_declarative/lib/lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | std::string get_message() 4 | { 5 | return "Hello from add_subdirectory() with declarative CMakeLists.dcmsl " 6 | "example!\n"; 7 | } 8 | -------------------------------------------------------------------------------- /examples/add_subdirectory_declarative/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | std::string get_message(); 4 | 5 | int main() 6 | { 7 | std::cout << get_message(); 8 | } 9 | -------------------------------------------------------------------------------- /examples/cmake_variables_accessor/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | cmake::minimum_required(cmake::version(3, 14, 3)); 4 | 5 | auto p = cmake::project("cmake_variables_accessor"); 6 | 7 | cmake::set_old_style_variable("MY_FANCY_PREFIX", "my_fancy_"); 8 | 9 | cmake::set_old_style_variable("EXE_SOURCES", "main.cpp;msg.cpp"); 10 | 11 | add_declarative_file("exe.dcmsl"); 12 | 13 | return 0; 14 | } -------------------------------------------------------------------------------- /examples/cmake_variables_accessor/README.md: -------------------------------------------------------------------------------- 1 | # Example usage of `cmake_variables.FOO.as_*` -------------------------------------------------------------------------------- /examples/cmake_variables_accessor/exe.dcmsl: -------------------------------------------------------------------------------- 1 | executable { 2 | name = "exe" 3 | name_prefix = cmake_variables.MY_FANCY_PREFIX.as_string 4 | files.public = cmake_variables.EXE_SOURCES.as_list 5 | } 6 | -------------------------------------------------------------------------------- /examples/cmake_variables_accessor/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | std::string get_msg(); 5 | 6 | int main() 7 | { 8 | std::cout << get_msg(); 9 | } 10 | -------------------------------------------------------------------------------- /examples/cmake_variables_accessor/msg.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | std::string get_msg() 4 | { 5 | return "Hello from cmake_variables accessor example!\n"; 6 | } -------------------------------------------------------------------------------- /examples/cmsl_example/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | cmake::minimum_required(cmake::version(3, 14, 3)); 4 | 5 | auto hello_world = cmake::project("Hello World"); 6 | 7 | auto lib = add_subdirectory("lib", hello_world); 8 | 9 | auto sources = { "main.cpp" }; 10 | auto exec = hello_world.add_executable("hw_exec", sources); 11 | exec.link_to(lib); 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /examples/cmsl_example/lib/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | auto main(cmake::project& hw_project) 2 | { 3 | auto sources = { "lib.cpp" }; 4 | return hw_project.add_library("lib", sources); 5 | } 6 | -------------------------------------------------------------------------------- /examples/cmsl_example/lib/lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | std::string get_message() 4 | { 5 | return "Hello CMakeSL World!"; 6 | } 7 | -------------------------------------------------------------------------------- /examples/cmsl_example/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern std::string get_message(); 5 | 6 | int main() 7 | { 8 | std::cout << get_message() << '\n'; 9 | } 10 | 11 | -------------------------------------------------------------------------------- /examples/custom_component/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | component my_fancy_exe : executable { 2 | name_prefix = "my_fancy_" 3 | } 4 | 5 | my_fancy_exe { 6 | name = "executable" 7 | 8 | files.public = [ 9 | "main.cpp" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /examples/custom_component/README.md: -------------------------------------------------------------------------------- 1 | # Example usage of custom components 2 | -------------------------------------------------------------------------------- /examples/custom_component/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | std::cout << "Hello from custom component example!\n"; 6 | } 7 | -------------------------------------------------------------------------------- /examples/declarative_root_cmakelists/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | executable { 2 | name = "declarative_root_example" 3 | 4 | files.public = [ 5 | "main.cpp" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /examples/declarative_root_cmakelists/README.md: -------------------------------------------------------------------------------- 1 | # Example usage of declarative format as the root `CMakeLists.dcmsl` -------------------------------------------------------------------------------- /examples/declarative_root_cmakelists/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | std::cout << "Hello from declarative root CMakeLists.dcmsl example!\n"; 6 | } 7 | -------------------------------------------------------------------------------- /examples/module_import/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | import "my_fancy_exe.dcmsl"; 2 | 3 | my_fancy_exe { 4 | name = "executable" 5 | 6 | files.public = [ 7 | "main.cpp" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /examples/module_import/README.md: -------------------------------------------------------------------------------- 1 | # Example usage of importing 2 | -------------------------------------------------------------------------------- /examples/module_import/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | std::cout << "Hello from custom component example!\n"; 6 | } 7 | -------------------------------------------------------------------------------- /examples/module_import/my_fancy_exe.dcmsl: -------------------------------------------------------------------------------- 1 | component my_fancy_exe : executable { 2 | name_prefix = "my_fancy_" 3 | } 4 | -------------------------------------------------------------------------------- /external/googletest/.clang-format: -------------------------------------------------------------------------------- 1 | # Run manually to reformat a file: 2 | # clang-format -i --style=file 3 | Language: Cpp 4 | BasedOnStyle: Google 5 | -------------------------------------------------------------------------------- /external/googletest/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore CI build directory 2 | build/ 3 | xcuserdata 4 | cmake-build-debug/ 5 | .idea/ 6 | bazel-bin 7 | bazel-genfiles 8 | bazel-googletest 9 | bazel-out 10 | bazel-testlogs 11 | # python 12 | *.pyc 13 | 14 | # Visual Studio files 15 | .vs 16 | *.sdf 17 | *.opensdf 18 | *.VC.opendb 19 | *.suo 20 | *.user 21 | _ReSharper.Caches/ 22 | Win32-Debug/ 23 | Win32-Release/ 24 | x64-Debug/ 25 | x64-Release/ 26 | 27 | # Ignore autoconf / automake files 28 | Makefile.in 29 | aclocal.m4 30 | configure 31 | build-aux/ 32 | autom4te.cache/ 33 | googletest/m4/libtool.m4 34 | googletest/m4/ltoptions.m4 35 | googletest/m4/ltsugar.m4 36 | googletest/m4/ltversion.m4 37 | googletest/m4/lt~obsolete.m4 38 | 39 | # Ignore generated directories. 40 | googlemock/fused-src/ 41 | googletest/fused-src/ 42 | 43 | # macOS files 44 | .DS_Store 45 | googletest/.DS_Store 46 | googletest/xcode/.DS_Store 47 | 48 | # Ignore cmake generated directories and files. 49 | CMakeFiles 50 | CTestTestfile.cmake 51 | Makefile 52 | cmake_install.cmake 53 | googlemock/CMakeFiles 54 | googlemock/CTestTestfile.cmake 55 | googlemock/Makefile 56 | googlemock/cmake_install.cmake 57 | googlemock/gtest 58 | -------------------------------------------------------------------------------- /external/googletest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.8) 2 | 3 | if (CMAKE_VERSION VERSION_LESS "3.1") 4 | add_definitions(-std=c++11) 5 | else() 6 | set(CMAKE_CXX_STANDARD 11) 7 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 8 | set(CMAKE_CXX_EXTENSIONS OFF) 9 | endif() 10 | 11 | if (POLICY CMP0048) 12 | cmake_policy(SET CMP0048 NEW) 13 | endif (POLICY CMP0048) 14 | 15 | project(googletest-distribution) 16 | set(GOOGLETEST_VERSION 1.9.0) 17 | 18 | enable_testing() 19 | 20 | include(CMakeDependentOption) 21 | include(GNUInstallDirs) 22 | 23 | #Note that googlemock target already builds googletest 24 | option(BUILD_GMOCK "Builds the googlemock subproject" ON) 25 | option(INSTALL_GTEST "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" ON) 26 | 27 | if(BUILD_GMOCK) 28 | add_subdirectory( googlemock ) 29 | else() 30 | add_subdirectory( googletest ) 31 | endif() 32 | -------------------------------------------------------------------------------- /external/googletest/Makefile.am: -------------------------------------------------------------------------------- 1 | ## Process this file with automake to produce Makefile.in 2 | ACLOCAL_AMFLAGS = -I m4 3 | 4 | AUTOMAKE_OPTIONS = foreign 5 | 6 | # Build . before src so that our all-local and clean-local hooks kicks in at 7 | # the right time. 8 | SUBDIRS = googletest googlemock 9 | 10 | EXTRA_DIST = \ 11 | BUILD.bazel \ 12 | CMakeLists.txt \ 13 | README.md \ 14 | WORKSPACE 15 | -------------------------------------------------------------------------------- /external/googletest/WORKSPACE: -------------------------------------------------------------------------------- 1 | workspace(name = "com_google_googletest") 2 | 3 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 4 | 5 | # Abseil 6 | http_archive( 7 | name = "com_google_absl", 8 | urls = ["https://github.com/abseil/abseil-cpp/archive/master.zip"], 9 | strip_prefix = "abseil-cpp-master", 10 | ) 11 | -------------------------------------------------------------------------------- /external/googletest/ci/build-platformio.sh: -------------------------------------------------------------------------------- 1 | # run PlatformIO builds 2 | platformio run 3 | -------------------------------------------------------------------------------- /external/googletest/ci/install-platformio.sh: -------------------------------------------------------------------------------- 1 | # install PlatformIO 2 | sudo pip install -U platformio 3 | 4 | # update PlatformIO 5 | platformio update 6 | -------------------------------------------------------------------------------- /external/googletest/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([Google C++ Mocking and Testing Frameworks], 2 | [1.9.0], 3 | [googlemock@googlegroups.com], 4 | [googletest]) 5 | 6 | # Provide various options to initialize the Autoconf and configure processes. 7 | AC_PREREQ([2.59]) 8 | AC_CONFIG_SRCDIR([./README.md]) 9 | AC_CONFIG_AUX_DIR([build-aux]) 10 | AC_CONFIG_FILES([Makefile]) 11 | AC_CONFIG_SUBDIRS([googletest googlemock]) 12 | 13 | AM_INIT_AUTOMAKE 14 | 15 | # Output the generated files. No further autoconf macros may be used. 16 | AC_OUTPUT 17 | -------------------------------------------------------------------------------- /external/googletest/googlemock/cmake/gmock.pc.in: -------------------------------------------------------------------------------- 1 | prefix=${pcfiledir}/../.. 2 | libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ 3 | includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ 4 | 5 | Name: gmock 6 | Description: GoogleMock (without main() function) 7 | Version: @PROJECT_VERSION@ 8 | URL: https://github.com/google/googletest 9 | Requires: gtest 10 | Libs: -L${libdir} -lgmock @CMAKE_THREAD_LIBS_INIT@ 11 | Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@ 12 | -------------------------------------------------------------------------------- /external/googletest/googlemock/cmake/gmock_main.pc.in: -------------------------------------------------------------------------------- 1 | prefix=${pcfiledir}/../.. 2 | libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ 3 | includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ 4 | 5 | Name: gmock_main 6 | Description: GoogleMock (with main() function) 7 | Version: @PROJECT_VERSION@ 8 | URL: https://github.com/google/googletest 9 | Requires: gmock 10 | Libs: -L${libdir} -lgmock_main @CMAKE_THREAD_LIBS_INIT@ 11 | Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@ 12 | -------------------------------------------------------------------------------- /external/googletest/googlemock/docs/Documentation.md: -------------------------------------------------------------------------------- 1 | This page lists all documentation markdown files for Google Mock **(the 2 | current git version)** 3 | -- **if you use a former version of Google Mock, please read the 4 | documentation for that specific version instead (e.g. by checking out 5 | the respective git branch/tag).** 6 | 7 | * [ForDummies](ForDummies.md) -- start here if you are new to Google Mock. 8 | * [CheatSheet](CheatSheet.md) -- a quick reference. 9 | * [CookBook](CookBook.md) -- recipes for doing various tasks using Google Mock. 10 | * [FrequentlyAskedQuestions](FrequentlyAskedQuestions.md) -- check here before asking a question on the mailing list. 11 | 12 | To contribute code to Google Mock, read: 13 | 14 | * [CONTRIBUTING](../../CONTRIBUTING.md) -- read this _before_ writing your first patch. 15 | * [Pump Manual](../../googletest/docs/PumpManual.md) -- how we generate some of Google Mock's source files. 16 | -------------------------------------------------------------------------------- /external/googletest/googlemock/include/gmock/internal/custom/README.md: -------------------------------------------------------------------------------- 1 | # Customization Points 2 | 3 | The custom directory is an injection point for custom user configurations. 4 | 5 | ## Header `gmock-port.h` 6 | 7 | The following macros can be defined: 8 | 9 | ### Flag related macros: 10 | 11 | * `GMOCK_DECLARE_bool_(name)` 12 | * `GMOCK_DECLARE_int32_(name)` 13 | * `GMOCK_DECLARE_string_(name)` 14 | * `GMOCK_DEFINE_bool_(name, default_val, doc)` 15 | * `GMOCK_DEFINE_int32_(name, default_val, doc)` 16 | * `GMOCK_DEFINE_string_(name, default_val, doc)` 17 | -------------------------------------------------------------------------------- /external/googletest/googlemock/include/gmock/internal/custom/gmock-generated-actions.h: -------------------------------------------------------------------------------- 1 | // This file was GENERATED by command: 2 | // pump.py gmock-generated-actions.h.pump 3 | // DO NOT EDIT BY HAND!!! 4 | 5 | // GOOGLETEST_CM0002 DO NOT DELETE 6 | 7 | #ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_ 8 | #define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_ 9 | 10 | #endif // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_ 11 | -------------------------------------------------------------------------------- /external/googletest/googlemock/include/gmock/internal/custom/gmock-generated-actions.h.pump: -------------------------------------------------------------------------------- 1 | $$ -*- mode: c++; -*- 2 | $$ This is a Pump source file. Please use Pump to convert 3 | $$ it to callback-actions.h. 4 | $$ 5 | $var max_callback_arity = 5 6 | $$}} This meta comment fixes auto-indentation in editors. 7 | 8 | // GOOGLETEST_CM0002 DO NOT DELETE 9 | #ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_ 10 | #define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_ 11 | 12 | #endif // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_ 13 | -------------------------------------------------------------------------------- /external/googletest/googlemock/msvc/2005/gmock_config.vsprops: -------------------------------------------------------------------------------- 1 | 2 | 7 | 11 | 15 | 16 | -------------------------------------------------------------------------------- /external/googletest/googlemock/msvc/2010/gmock_config.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | ../../../googletest 5 | 6 | 7 | <_ProjectFileVersion>10.0.30319.1 8 | 9 | 10 | 11 | $(GTestDir)/include;%(AdditionalIncludeDirectories) 12 | 13 | 14 | 15 | 16 | $(GTestDir) 17 | 18 | 19 | -------------------------------------------------------------------------------- /external/googletest/googlemock/msvc/2015/gmock_config.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ../../../googletest 5 | 6 | 7 | <_ProjectFileVersion>10.0.30319.1 8 | 9 | 10 | 11 | $(GTestDir)/include;%(AdditionalIncludeDirectories) 12 | 13 | 14 | 15 | 16 | $(GTestDir) 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /external/googletest/googlemock/scripts/generator/cpp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stryku/cmakesl/e53bffed62ae9ca68c0c2de0de8e2a94bfe4d326/external/googletest/googlemock/scripts/generator/cpp/__init__.py -------------------------------------------------------------------------------- /external/googletest/googlemock/scripts/generator/cpp/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2007 Neal Norwitz 4 | # Portions Copyright 2007 Google Inc. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | """Generic utilities for C++ parsing.""" 19 | 20 | __author__ = 'nnorwitz@google.com (Neal Norwitz)' 21 | 22 | 23 | import sys 24 | 25 | 26 | # Set to True to see the start/end token indices. 27 | DEBUG = True 28 | 29 | 30 | def ReadFile(filename, print_error=True): 31 | """Returns the contents of a file.""" 32 | try: 33 | fp = open(filename) 34 | try: 35 | return fp.read() 36 | finally: 37 | fp.close() 38 | except IOError: 39 | if print_error: 40 | print('Error reading %s: %s' % (filename, sys.exc_info()[1])) 41 | return None 42 | -------------------------------------------------------------------------------- /external/googletest/googlemock/scripts/generator/gmock_gen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2008 Google Inc. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Driver for starting up Google Mock class generator.""" 18 | 19 | __author__ = 'nnorwitz@google.com (Neal Norwitz)' 20 | 21 | import os 22 | import sys 23 | 24 | if __name__ == '__main__': 25 | # Add the directory of this script to the path so we can import gmock_class. 26 | sys.path.append(os.path.dirname(__file__)) 27 | 28 | from cpp import gmock_class 29 | # Fix the docstring in case they require the usage. 30 | gmock_class.__doc__ = gmock_class.__doc__.replace('gmock_class.py', __file__) 31 | gmock_class.main() 32 | -------------------------------------------------------------------------------- /external/googletest/googlemock/test/gmock-function-mocker_nc.cc: -------------------------------------------------------------------------------- 1 | #include "gmock/gmock.h" 2 | 3 | #include 4 | #include 5 | 6 | #if defined(TEST_MOCK_METHOD_INVALID_CONST_SPEC) 7 | 8 | struct Base { 9 | MOCK_METHOD(int, F, (), (onst)); 10 | }; 11 | 12 | #else 13 | 14 | // Sanity check - this should compile. 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /external/googletest/googletest/cmake/Config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | include(CMakeFindDependencyMacro) 3 | if (@GTEST_HAS_PTHREAD@) 4 | set(THREADS_PREFER_PTHREAD_FLAG @THREADS_PREFER_PTHREAD_FLAG@) 5 | find_dependency(Threads) 6 | endif() 7 | 8 | include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake") 9 | check_required_components("@project_name@") 10 | -------------------------------------------------------------------------------- /external/googletest/googletest/cmake/gtest.pc.in: -------------------------------------------------------------------------------- 1 | prefix=${pcfiledir}/../.. 2 | libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ 3 | includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ 4 | 5 | Name: gtest 6 | Description: GoogleTest (without main() function) 7 | Version: @PROJECT_VERSION@ 8 | URL: https://github.com/google/googletest 9 | Libs: -L${libdir} -lgtest @CMAKE_THREAD_LIBS_INIT@ 10 | Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@ 11 | -------------------------------------------------------------------------------- /external/googletest/googletest/cmake/gtest_main.pc.in: -------------------------------------------------------------------------------- 1 | prefix=${pcfiledir}/../.. 2 | libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ 3 | includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ 4 | 5 | Name: gtest_main 6 | Description: GoogleTest (with main() function) 7 | Version: @PROJECT_VERSION@ 8 | URL: https://github.com/google/googletest 9 | Requires: gtest 10 | Libs: -L${libdir} -lgtest_main @CMAKE_THREAD_LIBS_INIT@ 11 | Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@ 12 | -------------------------------------------------------------------------------- /external/googletest/googletest/docs/samples.md: -------------------------------------------------------------------------------- 1 | # Googletest Samples 2 | 3 | If you're like us, you'd like to look at [googletest 4 | samples.](https://github.com/google/googletest/tree/master/googletest/samples) 5 | The sample directory has a number of well-commented samples showing how to use a 6 | variety of googletest features. 7 | 8 | * Sample #1 shows the basic steps of using googletest to test C++ functions. 9 | * Sample #2 shows a more complex unit test for a class with multiple member 10 | functions. 11 | * Sample #3 uses a test fixture. 12 | * Sample #4 teaches you how to use googletest and `googletest.h` together to 13 | get the best of both libraries. 14 | * Sample #5 puts shared testing logic in a base test fixture, and reuses it in 15 | derived fixtures. 16 | * Sample #6 demonstrates type-parameterized tests. 17 | * Sample #7 teaches the basics of value-parameterized tests. 18 | * Sample #8 shows using `Combine()` in value-parameterized tests. 19 | * Sample #9 shows use of the listener API to modify Google Test's console 20 | output and the use of its reflection API to inspect test results. 21 | * Sample #10 shows use of the listener API to implement a primitive memory 22 | leak checker. 23 | -------------------------------------------------------------------------------- /external/googletest/googletest/msvc/2010/gtest-md.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /external/googletest/googletest/msvc/2010/gtest.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /external/googletest/googletest/msvc/2010/gtest_main-md.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /external/googletest/googletest/msvc/2010/gtest_main.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /external/googletest/googletest/msvc/2010/gtest_prod_test-md.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | Source Files 19 | 20 | 21 | 22 | 23 | Header Files 24 | 25 | 26 | -------------------------------------------------------------------------------- /external/googletest/googletest/msvc/2010/gtest_prod_test.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | Source Files 19 | 20 | 21 | 22 | 23 | Header Files 24 | 25 | 26 | -------------------------------------------------------------------------------- /external/googletest/googletest/msvc/2010/gtest_unittest-md.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /external/googletest/googletest/msvc/2010/gtest_unittest.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /external/googletest/googletest/xcode/Config/DebugProject.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // DebugProject.xcconfig 3 | // 4 | // These are Debug Configuration project settings for the gtest framework and 5 | // examples. It is set in the "Based On:" dropdown in the "Project" info 6 | // dialog. 7 | // This file is based on the Xcode Configuration files in: 8 | // https://github.com/google/google-toolbox-for-mac 9 | // 10 | 11 | #include "General.xcconfig" 12 | 13 | // No optimization 14 | GCC_OPTIMIZATION_LEVEL = 0 15 | 16 | // Deployment postprocessing is what triggers Xcode to strip, turn it off 17 | DEPLOYMENT_POSTPROCESSING = NO 18 | 19 | // Dead code stripping off 20 | DEAD_CODE_STRIPPING = NO 21 | 22 | // Debug symbols should be on obviously 23 | GCC_GENERATE_DEBUGGING_SYMBOLS = YES 24 | 25 | // Define the DEBUG macro in all debug builds 26 | OTHER_CFLAGS = $(OTHER_CFLAGS) -DDEBUG=1 27 | 28 | // These are turned off to avoid STL incompatibilities with client code 29 | // // Turns on special C++ STL checks to "encourage" good STL use 30 | // GCC_PREPROCESSOR_DEFINITIONS = $(GCC_PREPROCESSOR_DEFINITIONS) _GLIBCXX_DEBUG_PEDANTIC _GLIBCXX_DEBUG _GLIBCPP_CONCEPT_CHECKS 31 | -------------------------------------------------------------------------------- /external/googletest/googletest/xcode/Config/FrameworkTarget.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // FrameworkTarget.xcconfig 3 | // 4 | // These are Framework target settings for the gtest framework and examples. It 5 | // is set in the "Based On:" dropdown in the "Target" info dialog. 6 | // This file is based on the Xcode Configuration files in: 7 | // https://github.com/google/google-toolbox-for-mac 8 | // 9 | 10 | // Dynamic libs need to be position independent 11 | GCC_DYNAMIC_NO_PIC = NO 12 | 13 | // Dynamic libs should not have their external symbols stripped. 14 | STRIP_STYLE = non-global 15 | 16 | // Let the user install by specifying the $DSTROOT with xcodebuild 17 | SKIP_INSTALL = NO 18 | -------------------------------------------------------------------------------- /external/googletest/googletest/xcode/Config/ReleaseProject.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // ReleaseProject.xcconfig 3 | // 4 | // These are Release Configuration project settings for the gtest framework 5 | // and examples. It is set in the "Based On:" dropdown in the "Project" info 6 | // dialog. 7 | // This file is based on the Xcode Configuration files in: 8 | // https://github.com/google/google-toolbox-for-mac 9 | // 10 | 11 | #include "General.xcconfig" 12 | 13 | // subconfig/Release.xcconfig 14 | 15 | // Optimize for space and size (Apple recommendation) 16 | GCC_OPTIMIZATION_LEVEL = s 17 | 18 | // Deploment postprocessing is what triggers Xcode to strip 19 | DEPLOYMENT_POSTPROCESSING = YES 20 | 21 | // No symbols 22 | GCC_GENERATE_DEBUGGING_SYMBOLS = NO 23 | 24 | // Dead code strip does not affect ObjC code but can help for C 25 | DEAD_CODE_STRIPPING = YES 26 | 27 | // NDEBUG is used by things like assert.h, so define it for general compat. 28 | // ASSERT going away in release tends to create unused vars. 29 | OTHER_CFLAGS = $(OTHER_CFLAGS) -DNDEBUG=1 -Wno-unused-variable 30 | 31 | // When we strip we want to strip all symbols in release, but save externals. 32 | STRIP_STYLE = all 33 | -------------------------------------------------------------------------------- /external/googletest/googletest/xcode/Config/StaticLibraryTarget.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // StaticLibraryTarget.xcconfig 3 | // 4 | // These are static library target settings for libgtest.a. It 5 | // is set in the "Based On:" dropdown in the "Target" info dialog. 6 | // This file is based on the Xcode Configuration files in: 7 | // https://github.com/google/google-toolbox-for-mac 8 | // 9 | 10 | // Static libs can be included in bundles so make them position independent 11 | GCC_DYNAMIC_NO_PIC = NO 12 | 13 | // Static libs should not have their internal globals or external symbols 14 | // stripped. 15 | STRIP_STYLE = debugging 16 | 17 | // Let the user install by specifying the $DSTROOT with xcodebuild 18 | SKIP_INSTALL = NO 19 | -------------------------------------------------------------------------------- /external/googletest/googletest/xcode/Config/TestTarget.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // TestTarget.xcconfig 3 | // 4 | // These are Test target settings for the gtest framework and examples. It 5 | // is set in the "Based On:" dropdown in the "Target" info dialog. 6 | 7 | PRODUCT_NAME = $(TARGET_NAME) 8 | HEADER_SEARCH_PATHS = ../include 9 | -------------------------------------------------------------------------------- /external/googletest/googletest/xcode/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.google.${PRODUCT_NAME} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | GTEST_VERSIONINFO_LONG 21 | CFBundleShortVersionString 22 | GTEST_VERSIONINFO_SHORT 23 | CFBundleGetInfoString 24 | ${PRODUCT_NAME} GTEST_VERSIONINFO_LONG, ${GTEST_VERSIONINFO_ABOUT} 25 | NSHumanReadableCopyright 26 | ${GTEST_VERSIONINFO_ABOUT} 27 | CSResourcesFileMapped 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /external/googletest/googletest/xcode/Samples/FrameworkSample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.google.gtest.${PRODUCT_NAME:identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | CSResourcesFileMapped 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /external/googletest/platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; http://docs.platformio.org/page/projectconf.html 10 | 11 | 12 | [platformio] 13 | #src_dir = ./googlemock 14 | #src_dir = ./googletest 15 | src_dir = . 16 | 17 | [env:googletest_esp32] 18 | platform = espressif32 19 | board = esp32dev 20 | framework = arduino 21 | build_flags = -I./googletest/include -I./googletest 22 | src_filter = +<*> -<.git/> - - - - - - + + 23 | upload_speed = 921600 24 | 25 | [env:googlemock_esp32] 26 | platform = espressif32 27 | board = esp32dev 28 | framework = arduino 29 | build_flags = -I./googlemock/include -I./googletest/include -I./googletest -I./googlemock 30 | src_filter = +<*> -<.git/> - - - + + + 31 | upload_speed = 921600 32 | -------------------------------------------------------------------------------- /facade/visibility.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cmsl::facade { 4 | enum class visibility 5 | { 6 | interface, 7 | private_, 8 | public_ 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /scripts/build_cmake.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | COMPILER=$1 4 | 5 | # Clone CMake codebase. 6 | git clone https://github.com/stryku/cmake_for_cmakesl cmake 7 | cd cmake 8 | # CMakeSL bases on this particular branch. 9 | git checkout cmakesl 10 | 11 | # Clone CMakeSL in the `Source` directory. 12 | cd Source 13 | git clone https://github.com/stryku/cmakesl 14 | 15 | # Build CMake. C++17 compiler is required. 16 | cd ../.. 17 | mkdir build install 18 | cd build 19 | cmake ../cmake -DCMAKE_CXX_COMPILER=$COMPILER -DCMAKE_INSTALL_PREFIX=../install 20 | make install -j$(nproc) 21 | cd .. 22 | # Now, in install/bin you have the `cmake` binary that supports CMakeSL. 23 | 24 | # Build the cmsl_example 25 | cd install/bin 26 | cp -r ../../cmake/Source/cmakesl/examples/cmsl_example . 27 | mkdir build && cd build 28 | ./../cmake ../cmsl_example 29 | make -j$(nproc) 30 | ./hw_exec 31 | -------------------------------------------------------------------------------- /source/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | void main(cmake::project& p) 2 | { 3 | add_subdirectory("common", p); 4 | add_subdirectory("errors", p); 5 | add_subdirectory("lexer", p); 6 | add_subdirectory("parse", p); 7 | add_subdirectory("ast", p); 8 | add_subdirectory("decl_ast"); 9 | add_subdirectory("sema", p); 10 | add_subdirectory("decl_sema"); 11 | add_subdirectory("exec", p); 12 | } 13 | -------------------------------------------------------------------------------- /source/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(common) 2 | add_subdirectory(errors) 3 | add_subdirectory(lexer) 4 | add_subdirectory(parse) 5 | add_subdirectory(decl_ast) 6 | add_subdirectory(ast) 7 | add_subdirectory(decl_sema) 8 | add_subdirectory(sema) 9 | add_subdirectory(exec) 10 | 11 | -------------------------------------------------------------------------------- /source/ast/ast_node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "lexer/token.hpp" 4 | 5 | namespace cmsl { 6 | struct source_location; 7 | 8 | namespace ast { 9 | class ast_node_visitor; 10 | 11 | class ast_node 12 | { 13 | public: 14 | using token_t = lexer::token; 15 | 16 | virtual ~ast_node() {} 17 | 18 | virtual void visit(ast_node_visitor& visitor) const = 0; 19 | virtual source_location begin_location() const = 0; 20 | virtual source_location end_location() const = 0; 21 | virtual bool is_exported() const { return false; } 22 | 23 | source_range src_range() const 24 | { 25 | return source_range{ begin_location(), end_location() }; 26 | }; 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /source/ast/block_node.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/block_node.hpp" 2 | #include "ast/ast_node_visitor.hpp" 3 | #include "block_node.hpp" 4 | 5 | #include 6 | #include 7 | 8 | namespace cmsl::ast { 9 | block_node::block_node(token_t open_brace, nodes_t nodes, token_t close_brace) 10 | : m_open_brace{ open_brace } 11 | , m_nodes{ std::move(nodes) } 12 | , m_close_brace{ close_brace } 13 | { 14 | } 15 | 16 | const block_node::nodes_t& block_node::nodes() const 17 | { 18 | return m_nodes; 19 | } 20 | 21 | void block_node::visit(ast_node_visitor& visitor) const 22 | { 23 | visitor.visit(*this); 24 | } 25 | 26 | ast_node::token_t block_node::open_brace() const 27 | { 28 | return m_open_brace; 29 | } 30 | 31 | ast_node::token_t block_node::close_brace() const 32 | { 33 | return m_close_brace; 34 | } 35 | 36 | source_location block_node::begin_location() const 37 | { 38 | return m_open_brace.src_range().begin; 39 | } 40 | 41 | source_location block_node::end_location() const 42 | { 43 | return m_close_brace.src_range().end; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /source/ast/block_node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/ast_node.hpp" 4 | 5 | #include 6 | #include 7 | 8 | namespace cmsl::ast { 9 | class block_node : public ast_node 10 | { 11 | public: 12 | using nodes_t = std::vector>; 13 | 14 | block_node(token_t open_brace, nodes_t nodes, token_t close_brace); 15 | 16 | token_t open_brace() const; 17 | token_t close_brace() const; 18 | 19 | const nodes_t& nodes() const; 20 | 21 | void visit(ast_node_visitor& visitor) const override; 22 | source_location begin_location() const override; 23 | source_location end_location() const override; 24 | 25 | private: 26 | token_t m_open_brace; 27 | nodes_t m_nodes; 28 | token_t m_close_brace; 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /source/ast/break_node.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/break_node.hpp" 2 | 3 | #include "ast/ast_node_visitor.hpp" 4 | 5 | namespace cmsl::ast { 6 | break_node::break_node(ast_node::token_t break_token, 7 | ast_node::token_t semicolon) 8 | : m_break{ break_token } 9 | , m_semicolon{ semicolon } 10 | { 11 | } 12 | 13 | const ast_node::token_t& break_node::break_() const 14 | { 15 | return m_break; 16 | } 17 | 18 | const ast_node::token_t& break_node::semicolon() const 19 | { 20 | return m_semicolon; 21 | } 22 | 23 | void break_node::visit(ast_node_visitor& visitor) const 24 | { 25 | visitor.visit(*this); 26 | } 27 | 28 | source_location break_node::begin_location() const 29 | { 30 | return m_break.src_range().begin; 31 | } 32 | 33 | source_location break_node::end_location() const 34 | { 35 | return m_semicolon.src_range().end; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /source/ast/break_node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/ast_node.hpp" 4 | 5 | namespace cmsl::ast { 6 | class break_node : public ast_node 7 | { 8 | public: 9 | explicit break_node(token_t break_token, token_t semicolon); 10 | 11 | const token_t& break_() const; 12 | const token_t& semicolon() const; 13 | 14 | void visit(ast_node_visitor& visitor) const override; 15 | source_location begin_location() const override; 16 | source_location end_location() const override; 17 | 18 | private: 19 | token_t m_break; 20 | token_t m_semicolon; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /source/ast/class_node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/ast_node.hpp" 4 | #include "common/string.hpp" 5 | #include "lexer/token.hpp" 6 | 7 | #include 8 | #include 9 | 10 | namespace cmsl::ast { 11 | class class_node : public ast_node 12 | { 13 | public: 14 | using nodes_t = std::vector>; 15 | 16 | class_node(std::optional export_kw, token_t class_kw, token_t name, 17 | token_t open_brace, nodes_t nodes, token_t close_brace, 18 | token_t semicolon); 19 | 20 | const std::optional& export_() const; 21 | token_t class_kw() const; 22 | token_t name() const; 23 | token_t open_brace() const; 24 | token_t close_brace() const; 25 | token_t semicolon() const; 26 | const nodes_t& nodes() const; 27 | 28 | bool is_exported() const override; 29 | void visit(ast_node_visitor& visitor) const override; 30 | source_location begin_location() const override; 31 | source_location end_location() const override; 32 | 33 | private: 34 | std::optional m_export_kw; 35 | token_t m_class_kw; 36 | token_t m_name; 37 | token_t m_open_brace; 38 | nodes_t m_nodes; 39 | token_t m_close_brace; 40 | token_t m_semicolon; 41 | }; 42 | } 43 | -------------------------------------------------------------------------------- /source/ast/conditional_node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/ast_node.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::ast { 8 | class block_node; 9 | 10 | class conditional_node : public ast_node 11 | { 12 | public: 13 | explicit conditional_node(token_t open_paren, 14 | std::unique_ptr condition, 15 | token_t close_paren, 16 | std::unique_ptr body); 17 | ~conditional_node(); 18 | 19 | token_t open_paren() const; 20 | token_t close_paren() const; 21 | 22 | const ast_node& condition() const; 23 | const block_node& body() const; 24 | 25 | void visit(ast_node_visitor& visitor) const override; 26 | source_location begin_location() const override; 27 | source_location end_location() const override; 28 | 29 | private: 30 | token_t m_open_paren; 31 | std::unique_ptr m_condition; 32 | token_t m_close_paren; 33 | std::unique_ptr m_body; 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /source/ast/designated_initializers_node.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/designated_initializers_node.hpp" 2 | #include "ast/ast_node_visitor.hpp" 3 | 4 | namespace cmsl::ast { 5 | const ast_node::token_t& designated_initializers_node::open_brace() const 6 | { 7 | return m_open_brace; 8 | } 9 | 10 | const designated_initializers_node::initializers_t& 11 | designated_initializers_node::initializers() const 12 | { 13 | return m_initializers; 14 | } 15 | 16 | const ast_node::token_t& designated_initializers_node::close_brace() const 17 | { 18 | return m_close_brace; 19 | } 20 | 21 | void designated_initializers_node::visit(ast_node_visitor& visitor) const 22 | { 23 | visitor.visit(*this); 24 | } 25 | 26 | source_location designated_initializers_node::begin_location() const 27 | { 28 | return m_open_brace.src_range().begin; 29 | } 30 | 31 | source_location designated_initializers_node::end_location() const 32 | { 33 | return m_close_brace.src_range().end; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /source/ast/designated_initializers_node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/ast_node.hpp" 4 | #include 5 | 6 | namespace cmsl::ast { 7 | 8 | class designated_initializers_node : public ast_node 9 | { 10 | public: 11 | struct initializer 12 | { 13 | token_t dot; 14 | token_t name; 15 | token_t equal; 16 | std::unique_ptr initialization; 17 | std::optional comma; 18 | }; 19 | 20 | using initializers_t = std::vector; 21 | 22 | explicit designated_initializers_node(token_t open_brace, 23 | initializers_t initializers, 24 | token_t close_brace) 25 | : m_open_brace{ open_brace } 26 | , m_initializers{ std::move(initializers) } 27 | , m_close_brace{ close_brace } 28 | { 29 | } 30 | 31 | const token_t& open_brace() const; 32 | const initializers_t& initializers() const; 33 | const token_t& close_brace() const; 34 | 35 | void visit(ast_node_visitor& visitor) const override; 36 | source_location begin_location() const override; 37 | source_location end_location() const override; 38 | 39 | private: 40 | token_t m_open_brace; 41 | initializers_t m_initializers; 42 | token_t m_close_brace; 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /source/ast/enum_node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/ast_node.hpp" 4 | 5 | #include 6 | #include 7 | 8 | namespace cmsl::ast { 9 | class enum_node : public ast_node 10 | { 11 | public: 12 | explicit enum_node(std::optional export_kw, token_t enum_kw, 13 | token_t name, token_t open_brace, 14 | std::vector enumerators, token_t close_brace, 15 | token_t semicolon); 16 | 17 | const std::optional& export_() const; 18 | const token_t& enum_kw() const; 19 | const token_t& name() const; 20 | const token_t& open_brace() const; 21 | const std::vector& enumerators() const; 22 | const token_t& close_brace() const; 23 | const token_t& semicolon() const; 24 | 25 | bool is_exported() const override; 26 | void visit(ast_node_visitor& visitor) const override; 27 | source_location begin_location() const override; 28 | source_location end_location() const override; 29 | 30 | private: 31 | std::optional m_export_kw; 32 | token_t m_enum_kw; 33 | token_t m_name; 34 | token_t m_open_brace; 35 | std::vector m_enumerators; 36 | token_t m_close_brace; 37 | token_t m_semicolon; 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /source/ast/escaped_string_builder.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/string.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::ast { 8 | struct escaped_string_builder 9 | { 10 | static std::string escape(cmsl::string_view str) 11 | { 12 | std::string result; 13 | 14 | for (auto i = 0u; i < str.size(); ++i) { 15 | const auto c = str.at(i); 16 | if (c == '\\') { 17 | ++i; 18 | if (i >= str.size()) { 19 | break; 20 | } 21 | 22 | const auto char_meant_to_be_escaped = str.at(i); 23 | 24 | const auto result_char = [char_meant_to_be_escaped] { 25 | switch (char_meant_to_be_escaped) { 26 | case 'n': 27 | return '\n'; 28 | case 't': 29 | return '\t'; 30 | case '\\': 31 | return '\\'; 32 | default: 33 | return char_meant_to_be_escaped; 34 | } 35 | }(); 36 | 37 | result += result_char; 38 | 39 | continue; 40 | } 41 | 42 | result += c; 43 | } 44 | 45 | return result; 46 | } 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /source/ast/if_else_node.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/if_else_node.hpp" 2 | #include "ast/ast_node_visitor.hpp" 3 | 4 | #include "ast/block_node.hpp" 5 | #include "ast/conditional_node.hpp" 6 | #include "if_else_node.hpp" 7 | 8 | namespace cmsl::ast { 9 | if_else_node::if_else_node(ifs_t ifs, std::optional else_) 10 | : m_ifs{ std::move(ifs) } 11 | , m_else{ std::move(else_) } 12 | { 13 | } 14 | 15 | if_else_node::~if_else_node() 16 | { 17 | } 18 | 19 | const if_else_node::ifs_t& if_else_node::ifs() const 20 | { 21 | return m_ifs; 22 | } 23 | 24 | const block_node* if_else_node::else_body() const 25 | { 26 | return m_else ? m_else->body.get() : nullptr; 27 | } 28 | 29 | void if_else_node::visit(ast_node_visitor& visitor) const 30 | { 31 | visitor.visit(*this); 32 | } 33 | 34 | std::optional if_else_node::else_kw() const 35 | { 36 | if (m_else) { 37 | return m_else->else_kw; 38 | } 39 | 40 | return std::nullopt; 41 | } 42 | 43 | source_location if_else_node::begin_location() const 44 | { 45 | return m_ifs.front().if_kw.src_range().begin; 46 | } 47 | 48 | source_location if_else_node::end_location() const 49 | { 50 | return m_else ? m_else->body->end_location() 51 | : m_ifs.back().conditional->end_location(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /source/ast/if_else_node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/ast_node.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace cmsl::ast { 10 | class conditional_node; 11 | class block_node; 12 | 13 | class if_else_node : public ast_node 14 | { 15 | public: 16 | struct if_values 17 | { 18 | std::optional else_kw; 19 | token_t if_kw; 20 | std::unique_ptr conditional; 21 | }; 22 | 23 | struct last_else_value 24 | { 25 | token_t else_kw; 26 | std::unique_ptr body; 27 | }; 28 | 29 | using ifs_t = std::vector; 30 | 31 | explicit if_else_node(ifs_t m_ifs, std::optional else_); 32 | ~if_else_node(); 33 | 34 | const ifs_t& ifs() const; 35 | 36 | std::optional else_kw() const; 37 | const block_node* else_body() const; 38 | 39 | void visit(ast_node_visitor& visitor) const override; 40 | source_location begin_location() const override; 41 | source_location end_location() const override; 42 | 43 | private: 44 | ifs_t m_ifs; 45 | std::optional m_else; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /source/ast/import_node.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/import_node.hpp" 2 | 3 | #include "ast/ast_node_visitor.hpp" 4 | 5 | namespace cmsl::ast { 6 | 7 | import_node::import_node(const ast_node::token_t& import_token, 8 | const ast_node::token_t& file_path, 9 | const token_t& semicolon) 10 | : m_import{ import_token } 11 | , m_file_path{ file_path } 12 | , m_semicolon{ semicolon } 13 | { 14 | } 15 | 16 | const ast_node::token_t& import_node::import_() const 17 | { 18 | return m_import; 19 | } 20 | 21 | const ast_node::token_t& import_node::file_path() const 22 | { 23 | return m_file_path; 24 | } 25 | 26 | void import_node::visit(ast_node_visitor& visitor) const 27 | { 28 | visitor.visit(*this); 29 | } 30 | 31 | source_location import_node::begin_location() const 32 | { 33 | return m_import.src_range().begin; 34 | } 35 | 36 | source_location import_node::end_location() const 37 | { 38 | return m_semicolon.src_range().end; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /source/ast/import_node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/ast_node.hpp" 4 | 5 | namespace cmsl::ast { 6 | 7 | class import_node : public ast_node 8 | { 9 | public: 10 | explicit import_node(const token_t& import_token, const token_t& file_path, 11 | const token_t& semicolon); 12 | 13 | const token_t& import_() const; 14 | const token_t& file_path() const; 15 | 16 | void visit(ast_node_visitor& visitor) const override; 17 | source_location begin_location() const override; 18 | source_location end_location() const override; 19 | 20 | private: 21 | token_t m_import; 22 | token_t m_file_path; 23 | token_t m_semicolon; 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /source/ast/namespace_node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/ast_node.hpp" 4 | #include "ast/qualified_name.hpp" 5 | 6 | #include 7 | #include 8 | 9 | namespace cmsl::ast { 10 | 11 | class namespace_node : public ast_node 12 | { 13 | public: 14 | using nodes_t = std::vector>; 15 | using names_t = std::vector; 16 | 17 | explicit namespace_node(token_t namespace_kw, names_t names, 18 | token_t open_brace, nodes_t nodes, 19 | token_t close_brace); 20 | 21 | const token_t& namespace_() const; 22 | const names_t& names() const; 23 | const token_t& open_brace() const; 24 | const nodes_t& nodes() const; 25 | const token_t& close_brace() const; 26 | 27 | void visit(ast_node_visitor& visitor) const override; 28 | source_location begin_location() const override; 29 | source_location end_location() const override; 30 | 31 | private: 32 | token_t m_namespace; 33 | names_t m_names; 34 | token_t m_open_brace; 35 | nodes_t m_nodes; 36 | token_t m_close_brace; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /source/ast/parameter_declaration.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/type_representation.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::ast { 8 | struct param_declaration 9 | { 10 | type_representation ty; 11 | lexer::token name; 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /source/ast/parser_utils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/qualified_name.hpp" 4 | #include "lexer/token.hpp" 5 | #include "parse/parser_utils.hpp" 6 | 7 | #include 8 | 9 | namespace cmsl::ast { 10 | class parse_errors_observer; 11 | 12 | class parser_utils : public parse::parser_utils 13 | { 14 | protected: 15 | explicit parser_utils(parse_errors_observer& err_observer, token_it current, 16 | token_it end); 17 | 18 | bool possibly_qualified_name_starts() const; 19 | 20 | std::optional> 21 | parse_possibly_qualified_name(); 22 | }; 23 | } -------------------------------------------------------------------------------- /source/ast/qualified_name.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "lexer/token.hpp" 4 | 5 | #include 6 | #include 7 | 8 | namespace cmsl::ast { 9 | struct name_with_coloncolon 10 | { 11 | lexer::token name; 12 | std::optional 13 | coloncolon; // :: operator after the namespace name. 14 | 15 | bool operator==(const name_with_coloncolon& rhs) const 16 | { 17 | return std::tie(name, coloncolon) == std::tie(rhs.name, rhs.coloncolon); 18 | } 19 | }; 20 | 21 | class qualified_name 22 | { 23 | public: 24 | qualified_name(lexer::token name); 25 | qualified_name(std::vector names); 26 | 27 | const std::vector& names() const; 28 | 29 | std::string to_string() const; 30 | 31 | bool is_auto() const; 32 | bool is_fully_qualified() const; 33 | 34 | source_range src_range() const; 35 | source_view source() const; 36 | 37 | std::vector tokens() const; 38 | 39 | private: 40 | const lexer::token& first_name_token() const; 41 | 42 | private: 43 | std::vector m_names; 44 | }; 45 | 46 | // Todo: should be probably renamed 47 | using qualified_name_t = std::vector; 48 | } -------------------------------------------------------------------------------- /source/ast/return_node.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/return_node.hpp" 2 | #include "ast/ast_node_visitor.hpp" 3 | #include "return_node.hpp" 4 | 5 | namespace cmsl::ast { 6 | return_node::return_node(token_t return_kw, std::unique_ptr expr, 7 | token_t semicolon) 8 | : m_return_kw{ return_kw } 9 | , m_expression{ std::move(expr) } 10 | , m_semicolon{ semicolon } 11 | { 12 | } 13 | 14 | const ast_node& return_node::expression() const 15 | { 16 | return *m_expression; 17 | } 18 | 19 | void return_node::visit(ast_node_visitor& visitor) const 20 | { 21 | visitor.visit(*this); 22 | } 23 | 24 | const ast_node::token_t& return_node::return_kw() const 25 | { 26 | return m_return_kw; 27 | } 28 | 29 | const ast_node::token_t& return_node::semicolon() const 30 | { 31 | return m_semicolon; 32 | } 33 | 34 | source_location return_node::begin_location() const 35 | { 36 | return m_return_kw.src_range().begin; 37 | } 38 | 39 | source_location return_node::end_location() const 40 | { 41 | return m_semicolon.src_range().end; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /source/ast/return_node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/ast_node.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::ast { 8 | class return_node : public ast_node 9 | { 10 | public: 11 | explicit return_node(token_t return_kw, std::unique_ptr expr, 12 | token_t semicolon); 13 | 14 | const ast_node& expression() const; 15 | 16 | const token_t& return_kw() const; 17 | const token_t& semicolon() const; 18 | 19 | void visit(ast_node_visitor& visitor) const override; 20 | 21 | source_location begin_location() const override; 22 | source_location end_location() const override; 23 | 24 | private: 25 | token_t m_return_kw; 26 | std::unique_ptr m_expression; 27 | token_t m_semicolon; 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /source/ast/ternary_operator_node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/ast_node.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::ast { 8 | class ternary_operator_node : public ast_node 9 | { 10 | public: 11 | explicit ternary_operator_node(std::unique_ptr condition, 12 | token_t question_token, 13 | std::unique_ptr true_, 14 | token_t colon, 15 | std::unique_ptr false_); 16 | 17 | const ast_node& condition() const; 18 | const token_t& question() const; 19 | const ast_node& true_() const; 20 | const token_t& colon() const; 21 | const ast_node& false_() const; 22 | 23 | void visit(ast_node_visitor& visitor) const override; 24 | source_location begin_location() const override; 25 | source_location end_location() const override; 26 | 27 | private: 28 | std::unique_ptr m_condition; 29 | token_t m_question; 30 | std::unique_ptr m_true; 31 | token_t m_colon; 32 | std::unique_ptr m_false; 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /source/ast/translation_unit_node.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/translation_unit_node.hpp" 2 | #include "ast/ast_node_visitor.hpp" 3 | 4 | namespace cmsl::ast { 5 | translation_unit_node::translation_unit_node(nodes_t nodes) 6 | : m_nodes{ std::move(nodes) } 7 | { 8 | } 9 | 10 | const translation_unit_node::nodes_t& translation_unit_node::nodes() const 11 | { 12 | return m_nodes; 13 | } 14 | 15 | void translation_unit_node::visit(ast_node_visitor& visitor) const 16 | { 17 | visitor.visit(*this); 18 | } 19 | 20 | source_location translation_unit_node::begin_location() const 21 | { 22 | return (!m_nodes.empty()) ? m_nodes.front()->begin_location() 23 | : source_location{}; 24 | } 25 | 26 | source_location translation_unit_node::end_location() const 27 | { 28 | return (!m_nodes.empty()) ? m_nodes.front()->end_location() 29 | : source_location{}; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /source/ast/translation_unit_node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/ast_node.hpp" 4 | 5 | #include 6 | #include 7 | 8 | namespace cmsl::ast { 9 | class translation_unit_node : public ast_node 10 | { 11 | public: 12 | using nodes_t = std::vector>; 13 | 14 | explicit translation_unit_node(nodes_t nodes); 15 | 16 | const nodes_t& nodes() const; 17 | 18 | void visit(ast_node_visitor& visitor) const override; 19 | source_location begin_location() const override; 20 | source_location end_location() const override; 21 | 22 | private: 23 | nodes_t m_nodes; 24 | }; 25 | } -------------------------------------------------------------------------------- /source/ast/type_parser.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/parser_utils.hpp" 4 | 5 | namespace cmsl::ast { 6 | class type_representation; 7 | 8 | struct type_parsing_result; 9 | 10 | class type_parser : public parser_utils 11 | { 12 | public: 13 | explicit type_parser(parse_errors_observer& err_observer, token_it current, 14 | token_it end); 15 | 16 | type_parsing_result type(); 17 | 18 | private: 19 | std::optional eat_generic_type_token(); 20 | 21 | std::optional parse_type(); 22 | 23 | std::optional generic_type(); 24 | 25 | std::optional simple_type(); 26 | 27 | bool generic_type_starts() const; 28 | 29 | bool current_is_generic_type() const; 30 | 31 | bool is_builtin_simple_type(token_type_t token_type) const; 32 | 33 | std::optional eat_simple_type_name(); 34 | 35 | private: 36 | parse_errors_observer& m_err_observer; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /source/ast/type_parsing_result.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/type_representation.hpp" 4 | #include 5 | 6 | namespace cmsl::ast { 7 | struct type_parsing_result 8 | { 9 | std::optional ty; 10 | lexer::token_container_t::const_iterator stopped_at; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /source/ast/while_node.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/while_node.hpp" 2 | #include "ast/ast_node_visitor.hpp" 3 | #include "ast/conditional_node.hpp" 4 | #include "while_node.hpp" 5 | 6 | namespace cmsl::ast { 7 | 8 | while_node::while_node(token_t while_kw, 9 | std::unique_ptr node) 10 | : m_while_kw{ while_kw } 11 | , m_node{ std::move(node) } 12 | { 13 | } 14 | 15 | while_node::~while_node() 16 | { 17 | } 18 | 19 | const conditional_node& while_node::node() const 20 | { 21 | return *m_node; 22 | } 23 | 24 | void while_node::visit(ast_node_visitor& visitor) const 25 | { 26 | visitor.visit(*this); 27 | } 28 | 29 | ast_node::token_t while_node::while_kw() const 30 | { 31 | return m_while_kw; 32 | } 33 | 34 | source_location while_node::begin_location() const 35 | { 36 | return m_while_kw.src_range().begin; 37 | } 38 | 39 | source_location while_node::end_location() const 40 | { 41 | return m_node->end_location(); 42 | } 43 | } -------------------------------------------------------------------------------- /source/ast/while_node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/ast_node.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::ast { 8 | class conditional_node; 9 | 10 | class while_node : public ast_node 11 | { 12 | public: 13 | explicit while_node(token_t while_kw, 14 | std::unique_ptr node); 15 | ~while_node(); 16 | 17 | token_t while_kw() const; 18 | 19 | const conditional_node& node() const; 20 | 21 | void visit(ast_node_visitor& visitor) const override; 22 | source_location begin_location() const override; 23 | source_location end_location() const override; 24 | 25 | private: 26 | token_t m_while_kw; 27 | std::unique_ptr m_node; 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /source/common/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | import "cmake/cmsl_directories.cmsl"; 2 | 3 | void main(cmake::project& p) 4 | { 5 | auto sources = { 6 | // clang-format off 7 | "algorithm.hpp", 8 | "assert.hpp", 9 | "dumper_utils.cpp", 10 | "dumper_utils.hpp", 11 | "enum_class_utils.hpp", 12 | "int_alias.hpp", 13 | "overloaded.hpp", 14 | "source_location.hpp", 15 | "source_view.cpp", 16 | "source_view.hpp", 17 | "string.hpp", 18 | "strings_container.hpp", 19 | "strings_container_impl.cpp", 20 | "strings_container_impl.hpp" 21 | // clang-format on 22 | }; 23 | auto lib = p.add_library("common", sources); 24 | lib.include_directories({ cmsl::source_dir }); 25 | } 26 | -------------------------------------------------------------------------------- /source/common/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | static_library { 2 | name = "common" 3 | 4 | include_dirs.public = [ 5 | cmake_variables.CMAKESL_SOURCES_DIR.as_string 6 | ] 7 | 8 | compile_options.public = cmake_variables.CMAKESL_ADDITIONAL_COMPILER_FLAGS.as_list 9 | 10 | files.public = [ 11 | "algorithm.hpp", 12 | "assert.hpp", 13 | "dumper_utils.cpp", 14 | "dumper_utils.hpp", 15 | "enum_class_utils.hpp", 16 | "int_alias.hpp", 17 | "overloaded.hpp", 18 | "source_location.hpp", 19 | "source_view.cpp", 20 | "source_view.hpp", 21 | "string.hpp", 22 | "strings_container.hpp", 23 | "strings_container_impl.cpp", 24 | "strings_container_impl.hpp" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /source/common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMMON_SOURCES 2 | algorithm.hpp 3 | assert.hpp 4 | dumper_utils.cpp 5 | dumper_utils.hpp 6 | enum_class_utils.hpp 7 | int_alias.hpp 8 | overloaded.hpp 9 | source_location.hpp 10 | source_view.cpp 11 | source_view.hpp 12 | string.hpp 13 | strings_container.hpp 14 | strings_container_impl.cpp 15 | strings_container_impl.hpp 16 | ) 17 | 18 | add_library(common "${COMMON_SOURCES}") 19 | 20 | target_include_directories(common 21 | PRIVATE 22 | ${CMAKESL_SOURCES_DIR} 23 | ) 24 | 25 | target_compile_options(common 26 | PRIVATE 27 | ${CMAKESL_ADDITIONAL_COMPILER_FLAGS} 28 | ) 29 | -------------------------------------------------------------------------------- /source/common/assert.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define CMSL_ASSERT(EXPR) assert((EXPR)) 6 | #define CMSL_ASSERT_MSG(EXPR, MSG) assert((EXPR) && (MSG)) 7 | #define CMSL_UNREACHABLE(MSG) assert(false && (MSG)) 8 | -------------------------------------------------------------------------------- /source/common/enum_class_utils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace cmsl { 7 | namespace details { 8 | struct enum_class_hash 9 | { 10 | template 11 | std::size_t operator()(T t) const 12 | { 13 | return static_cast(t); 14 | } 15 | }; 16 | } 17 | 18 | template 19 | using enum_unordered_map = std::unordered_map; 20 | 21 | template 22 | using enum_unordered_set = std::unordered_set; 23 | } 24 | -------------------------------------------------------------------------------- /source/common/int_alias.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace cmsl { 6 | using int_t = std::int64_t; 7 | } 8 | -------------------------------------------------------------------------------- /source/common/overloaded.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cmsl { 4 | template 5 | struct overloaded : Ts... 6 | { 7 | using Ts::operator()...; 8 | }; 9 | template 10 | overloaded(Ts...)->overloaded; 11 | } 12 | -------------------------------------------------------------------------------- /source/common/source_location.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/string.hpp" 4 | 5 | namespace cmsl { 6 | struct source_location 7 | { 8 | unsigned line{ 1u }; 9 | unsigned column{ 1u }; 10 | unsigned absolute{ 0u }; 11 | 12 | bool operator<(const source_location& rhs) const 13 | { 14 | return absolute < rhs.absolute; 15 | } 16 | 17 | bool operator==(const source_location& rhs) const 18 | { 19 | return absolute == rhs.absolute; 20 | } 21 | 22 | bool operator<=(const source_location& rhs) const 23 | { 24 | return *this < rhs || *this == rhs; 25 | } 26 | }; 27 | 28 | struct source_range 29 | { 30 | source_location begin; 31 | source_location end; 32 | 33 | constexpr auto size() const { return end.absolute - begin.absolute; } 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /source/common/source_view.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/string.hpp" 4 | 5 | namespace cmsl { 6 | class source_view 7 | { 8 | public: 9 | struct line_info 10 | { 11 | cmsl::string_view line; 12 | cmsl::string_view::size_type start_pos; 13 | }; 14 | 15 | explicit source_view(cmsl::string_view source); 16 | explicit source_view(cmsl::string_view source_path, 17 | cmsl::string_view source); 18 | 19 | source_view(const source_view&) = default; 20 | source_view& operator=(const source_view&) = default; 21 | source_view(source_view&&) = default; 22 | source_view& operator=(source_view&&) = default; 23 | 24 | cmsl::string_view path() const; 25 | cmsl::string_view source() const; 26 | 27 | cmsl::string_view::const_iterator cbegin() const; 28 | cmsl::string_view::const_iterator cend() const; 29 | cmsl::string_view::const_pointer cdata() const; 30 | 31 | // Line numbers start from 1, not 0. 32 | line_info line(unsigned line_no) const; 33 | 34 | private: 35 | cmsl::string_view m_path; 36 | cmsl::string_view m_source; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /source/common/string.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace cmsl { 7 | using string_view = std::string_view; 8 | 9 | template 10 | using string_view_map = std::unordered_map; 11 | } 12 | -------------------------------------------------------------------------------- /source/common/strings_container.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/string.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl { 8 | class strings_container 9 | { 10 | public: 11 | virtual ~strings_container() = default; 12 | 13 | virtual cmsl::string_view store(std::string str) = 0; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /source/common/strings_container_impl.cpp: -------------------------------------------------------------------------------- 1 | #include "common/strings_container_impl.hpp" 2 | 3 | namespace cmsl { 4 | cmsl::string_view strings_container_impl::store(std::string str) 5 | { 6 | auto str_ptr = std::make_unique(std::move(str)); 7 | cmsl::string_view view = *str_ptr; 8 | m_strings.emplace_back(std::move(str_ptr)); 9 | return view; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /source/common/strings_container_impl.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/strings_container.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace cmsl { 10 | class strings_container_impl : public strings_container 11 | { 12 | public: 13 | cmsl::string_view store(std::string str) override; 14 | 15 | private: 16 | std::vector> m_strings; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /source/decl_ast/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | static_library { 2 | name = "decl_ast" 3 | 4 | include_dirs.public = [ 5 | cmake_variables.CMAKESL_SOURCES_DIR.as_string 6 | ] 7 | 8 | dependencies.public = [ 9 | "parse" 10 | ] 11 | 12 | compile_options.public = cmake_variables.CMAKESL_ADDITIONAL_COMPILER_FLAGS.as_list 13 | 14 | files.public = [ 15 | "ast_node.hpp", 16 | "ast_nodes.hpp", 17 | "parse_errors_reporter.cpp", 18 | "parse_errors_reporter.hpp", 19 | "parser.cpp", 20 | "parser.hpp" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /source/decl_ast/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(DECL_AST_SOURCES 2 | ast_node.hpp 3 | ast_nodes.hpp 4 | parse_errors_reporter.cpp 5 | parse_errors_reporter.hpp 6 | parser.cpp 7 | parser.hpp 8 | ) 9 | 10 | add_library(decl_ast "${DECL_AST_SOURCES}") 11 | 12 | target_include_directories(decl_ast 13 | PRIVATE 14 | ${CMAKESL_SOURCES_DIR} 15 | ) 16 | 17 | target_link_libraries(decl_ast 18 | PUBLIC 19 | parse 20 | ) 21 | 22 | target_compile_options(decl_ast 23 | PRIVATE 24 | ${CMAKESL_ADDITIONAL_COMPILER_FLAGS} 25 | ) 26 | -------------------------------------------------------------------------------- /source/decl_ast/ast_node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "lexer/token.hpp" 4 | 5 | namespace cmsl { 6 | struct source_location; 7 | 8 | namespace decl_ast { 9 | class ast_node_visitor; 10 | 11 | class ast_node 12 | { 13 | public: 14 | using token_t = lexer::token; 15 | 16 | virtual ~ast_node() = default; 17 | 18 | virtual void visit(ast_node_visitor& visitor) const = 0; 19 | virtual source_location begin_location() const = 0; 20 | virtual source_location end_location() const = 0; 21 | 22 | source_range src_range() const 23 | { 24 | return source_range{ begin_location(), end_location() }; 25 | }; 26 | }; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /source/decl_ast/ast_node_visitor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cmsl::decl_ast { 4 | class bool_value_node; 5 | class cmake_variable_access_node; 6 | class component_declaration_node; 7 | class component_node; 8 | class double_value_node; 9 | class import_node; 10 | class int_value_node; 11 | class list_node; 12 | class property_access_node; 13 | class property_append_node; 14 | class property_node; 15 | class string_value_node; 16 | class translation_unit_node; 17 | 18 | class ast_node_visitor 19 | { 20 | public: 21 | virtual ~ast_node_visitor() = default; 22 | 23 | virtual void visit(const bool_value_node& node) = 0; 24 | virtual void visit(const cmake_variable_access_node& node) = 0; 25 | virtual void visit(const component_declaration_node& node) = 0; 26 | virtual void visit(const component_node& node) = 0; 27 | virtual void visit(const double_value_node& node) = 0; 28 | virtual void visit(const import_node& node) = 0; 29 | virtual void visit(const int_value_node& node) = 0; 30 | virtual void visit(const list_node& node) = 0; 31 | virtual void visit(const property_access_node& node) = 0; 32 | virtual void visit(const property_append_node& node) = 0; 33 | virtual void visit(const property_node& node) = 0; 34 | virtual void visit(const string_value_node& node) = 0; 35 | virtual void visit(const translation_unit_node& node) = 0; 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /source/decl_sema/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | static_library { 2 | name = "decl_sema" 3 | 4 | include_dirs.public = [ 5 | cmake_variables.CMAKESL_SOURCES_DIR.as_string, 6 | cmake_variables.CMAKESL_GENERATED_PARENT_DIR.as_string 7 | ] 8 | 9 | dependencies.public = [ 10 | "decl_ast", 11 | "sema" 12 | ] 13 | 14 | compile_options.public = cmake_variables.CMAKESL_ADDITIONAL_COMPILER_FLAGS.as_list 15 | 16 | files.public = [ 17 | "builtin_decl_namespace_context.cpp", 18 | "builtin_decl_namespace_context.hpp", 19 | "component_creation_sema_function.hpp", 20 | "declarative_import_handler.hpp", 21 | "sema_builder_ast_visitor.cpp", 22 | "sema_builder_ast_visitor.hpp", 23 | "sema_node_visitor.hpp", 24 | "sema_nodes.hpp" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /source/decl_sema/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(DECL_SEMA_SOURCES 2 | builtin_decl_namespace_context.cpp 3 | builtin_decl_namespace_context.hpp 4 | component_creation_sema_function.hpp 5 | declarative_import_handler.hpp 6 | sema_builder_ast_visitor.cpp 7 | sema_builder_ast_visitor.hpp 8 | sema_node_visitor.hpp 9 | sema_nodes.hpp 10 | ) 11 | 12 | add_library(decl_sema "${DECL_SEMA_SOURCES}") 13 | 14 | target_include_directories(decl_sema 15 | PRIVATE 16 | ${CMAKESL_SOURCES_DIR} 17 | ${CMAKESL_GENERATED_PARENT_DIR} 18 | ) 19 | 20 | target_link_libraries(decl_sema 21 | PUBLIC 22 | decl_ast 23 | sema 24 | ) 25 | 26 | target_compile_options(decl_sema 27 | PRIVATE 28 | ${CMAKESL_ADDITIONAL_COMPILER_FLAGS} 29 | ) 30 | -------------------------------------------------------------------------------- /source/decl_sema/decl_namespace_types_accessor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cmsl { 4 | namespace sema { 5 | class sema_type; 6 | } 7 | 8 | namespace decl_sema { 9 | struct decl_namespace_types_accessor 10 | { 11 | const sema::sema_type& forwarding_lists; 12 | const sema::sema_type& forwarding_lists_ref; 13 | const sema::sema_type& product; 14 | const sema::sema_type& product_ref; 15 | const sema::sema_type& executable; 16 | const sema::sema_type& executable_ref; 17 | const sema::sema_type& test_executable; 18 | const sema::sema_type& test_executable_ref; 19 | const sema::sema_type& static_library; 20 | const sema::sema_type& static_library_ref; 21 | const sema::sema_type& shared_library; 22 | const sema::sema_type& shared_library_ref; 23 | }; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /source/decl_sema/declarative_import_handler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sema/qualified_contextes.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::decl_sema { 8 | class component_declaration_node; 9 | 10 | class declarative_import_handler 11 | { 12 | public: 13 | virtual ~declarative_import_handler() = default; 14 | 15 | struct result 16 | { 17 | sema::qualified_contextes qualified_contexts; 18 | cmsl::string_view_map 19 | component_declarations; 20 | }; 21 | 22 | virtual std::optional handle_declarative_import( 23 | cmsl::string_view path) = 0; 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /source/errors/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | import "cmake/cmsl_directories.cmsl"; 2 | 3 | void main(cmake::project& p) 4 | { 5 | auto lib = p.add_library( 6 | "errors", { "error.hpp", "errors_observer.hpp", "errors_observer.cpp" }); 7 | 8 | cmake::message(cmsl::facade_dir); 9 | lib.include_directories({ cmsl::source_dir, cmsl::facade_dir }); 10 | } 11 | -------------------------------------------------------------------------------- /source/errors/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | static_library { 2 | name = "errors" 3 | 4 | include_dirs.public = [ 5 | cmake_variables.CMAKESL_SOURCES_DIR.as_string, 6 | cmake_variables.CMAKESL_FACADE_DIR.as_string 7 | ] 8 | 9 | compile_options.public = cmake_variables.CMAKESL_ADDITIONAL_COMPILER_FLAGS.as_list 10 | 11 | files.public = [ 12 | "error.hpp", 13 | "errors_observer.hpp", 14 | "errors_observer.cpp" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /source/errors/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(ERRORS_SOURCES 2 | error.hpp 3 | errors_observer.hpp 4 | errors_observer.cpp 5 | ) 6 | 7 | add_library(errors "${ERRORS_SOURCES}") 8 | 9 | target_include_directories(errors 10 | PRIVATE 11 | ${CMAKESL_SOURCES_DIR} 12 | ) 13 | 14 | target_compile_options(errors 15 | PRIVATE 16 | ${CMAKESL_ADDITIONAL_COMPILER_FLAGS} 17 | ) 18 | -------------------------------------------------------------------------------- /source/errors/error.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/source_location.hpp" 4 | #include 5 | 6 | namespace cmsl::errors { 7 | enum class error_type 8 | { 9 | error, 10 | warning, 11 | note 12 | }; 13 | 14 | struct error 15 | { 16 | cmsl::string_view source_path; 17 | cmsl::string_view line_snippet; 18 | cmsl::string_view::size_type line_start_pos; 19 | std::string message; 20 | error_type type; 21 | source_range range; 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /source/errors/errors_observer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace cmsl { 6 | namespace facade { 7 | class cmake_facade; 8 | } 9 | 10 | namespace errors { 11 | struct error; 12 | 13 | class errors_observer 14 | { 15 | public: 16 | explicit errors_observer(std::ostream& out); 17 | explicit errors_observer(facade::cmake_facade* facade = nullptr); 18 | 19 | void notify_error(const error& error); 20 | 21 | private: 22 | std::string format_error(const error& err) const; 23 | 24 | private: 25 | facade::cmake_facade* m_facade{ nullptr }; 26 | std::ostream* m_out{ nullptr }; 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /source/exec/builtin_identifiers_observer.cpp: -------------------------------------------------------------------------------- 1 | #include "exec/builtin_identifiers_observer.hpp" 2 | #include "cmake_facade.hpp" 3 | 4 | namespace cmsl::exec { 5 | builtin_identifiers_observer::builtin_identifiers_observer( 6 | facade::cmake_facade& f) 7 | : m_facade{ f } 8 | { 9 | } 10 | 11 | void builtin_identifiers_observer::notify( 12 | const std::string& variable_name, const std::string& value) const 13 | { 14 | m_facade.set_property(variable_name, value); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /source/exec/builtin_identifiers_observer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace cmsl { 6 | 7 | namespace facade { 8 | class cmake_facade; 9 | } 10 | 11 | namespace exec { 12 | class builtin_identifiers_observer 13 | { 14 | public: 15 | explicit builtin_identifiers_observer(facade::cmake_facade& f); 16 | 17 | void notify(const std::string& variable_name, 18 | const std::string& value) const; 19 | 20 | private: 21 | facade::cmake_facade& m_facade; 22 | }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /source/exec/cross_translation_unit_static_variables_accessor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cmsl::exec { 4 | 5 | namespace inst { 6 | class instance; 7 | } 8 | 9 | class cross_translation_unit_static_variables_accessor 10 | { 11 | public: 12 | virtual ~cross_translation_unit_static_variables_accessor() = default; 13 | virtual inst::instance* access_variable(unsigned index) = 0; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /source/exec/expression_evaluation_context.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace cmsl { 6 | namespace facade { 7 | class cmake_facade; 8 | } 9 | 10 | namespace sema { 11 | class sema_type; 12 | } 13 | 14 | namespace exec { 15 | class function_caller; 16 | class identifiers_context; 17 | 18 | namespace inst { 19 | class instances_holder_interface; 20 | } 21 | 22 | struct expression_evaluation_context 23 | { 24 | function_caller& caller; 25 | inst::instances_holder_interface& instances; 26 | identifiers_context& ids_context; 27 | facade::cmake_facade& cmake_facade; 28 | 29 | using expected_types_t = 30 | std::stack>; 31 | expected_types_t expected_types; 32 | }; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /source/exec/extern_argument_parser.cpp: -------------------------------------------------------------------------------- 1 | #include "exec/extern_argument_parser.hpp" 2 | 3 | namespace cmsl::exec { 4 | 5 | std::optional extern_argument_parser::try_bool( 6 | const std::string& value) const 7 | { 8 | if (value == "true") { 9 | return true; 10 | } 11 | if (value == "false") { 12 | return false; 13 | } 14 | 15 | return std::nullopt; 16 | } 17 | 18 | std::optional extern_argument_parser::try_int( 19 | const std::string& value) const 20 | { 21 | try { 22 | const auto val = std::stoll(value); 23 | return static_cast(val); 24 | } catch (const std::exception& e) { 25 | return std::nullopt; 26 | } 27 | } 28 | 29 | std::optional extern_argument_parser::try_double( 30 | const std::string& value) const 31 | { 32 | try { 33 | return std::stod(value); 34 | } catch (const std::exception& e) { 35 | return std::nullopt; 36 | } 37 | } 38 | 39 | std::optional extern_argument_parser::try_string( 40 | const std::string& value) const 41 | { 42 | return value; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /source/exec/extern_argument_parser.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/int_alias.hpp" 4 | 5 | #include 6 | #include 7 | 8 | namespace cmsl::exec { 9 | class extern_argument_parser 10 | { 11 | public: 12 | std::optional try_bool(const std::string& value) const; 13 | std::optional try_int(const std::string& value) const; 14 | std::optional try_double(const std::string& value) const; 15 | std::optional try_string(const std::string& value) const; 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /source/exec/function_caller.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace cmsl { 7 | namespace ast { 8 | class function; 9 | } 10 | 11 | namespace sema { 12 | class sema_function; 13 | } 14 | 15 | namespace exec { 16 | namespace inst { 17 | class instance; 18 | class instances_holder_interface; 19 | } 20 | 21 | class function_caller 22 | { 23 | public: 24 | virtual ~function_caller() = default; 25 | 26 | virtual std::unique_ptr call( 27 | const sema::sema_function& fun, const std::vector& params, 28 | inst::instances_holder_interface& instances) = 0; 29 | virtual std::unique_ptr call_member( 30 | inst::instance& class_instance, const sema::sema_function& fun, 31 | const std::vector& params, 32 | inst::instances_holder_interface& instances) = 0; 33 | }; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /source/exec/identifiers_context.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/string.hpp" 4 | 5 | namespace cmsl::exec { 6 | namespace inst { 7 | class instance; 8 | } 9 | 10 | class identifiers_context 11 | { 12 | public: 13 | virtual ~identifiers_context() = default; 14 | virtual inst::instance* lookup_identifier(unsigned index) = 0; 15 | virtual inst::instance* get_class_instance() = 0; 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /source/exec/instance/enum_constant_value.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cmsl::exec::inst { 4 | struct enum_constant_value 5 | { 6 | unsigned value{}; 7 | }; 8 | } -------------------------------------------------------------------------------- /source/exec/instance/extern_value.cpp: -------------------------------------------------------------------------------- 1 | #include "exec/instance/extern_value.hpp" 2 | #include "exec/instance/instance.hpp" 3 | #include "extern_value.hpp" 4 | 5 | namespace cmsl::exec::inst { 6 | extern_value::extern_value(std::unique_ptr value) 7 | : m_value{ std::move(value) } 8 | { 9 | } 10 | 11 | extern_value::extern_value(const extern_value& other) 12 | { 13 | m_value = other.m_value ? other.m_value->copy() : nullptr; 14 | } 15 | 16 | extern_value& extern_value::operator=(const extern_value& other) 17 | { 18 | m_value = other.m_value ? other.m_value->copy() : nullptr; 19 | return *this; 20 | } 21 | 22 | extern_value::~extern_value() 23 | { 24 | } 25 | 26 | bool extern_value::has_value() const 27 | { 28 | return m_value != nullptr; 29 | } 30 | 31 | const instance& extern_value::value_cref() const 32 | { 33 | 34 | return *m_value; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /source/exec/instance/extern_value.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace cmsl::exec::inst { 6 | class instance; 7 | 8 | class extern_value 9 | { 10 | public: 11 | explicit extern_value(std::unique_ptr value); 12 | 13 | extern_value(const extern_value& other); 14 | extern_value& operator=(const extern_value& other); 15 | 16 | ~extern_value(); 17 | 18 | bool has_value() const; 19 | 20 | const instance& value_cref() const; 21 | 22 | private: 23 | std::unique_ptr m_value; 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /source/exec/instance/instance_reference.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "exec/instance/instance.hpp" 4 | 5 | namespace cmsl::exec { 6 | class execution_context; 7 | 8 | namespace inst { 9 | class instance_reference : public instance 10 | { 11 | public: 12 | instance_reference(unsigned index, execution_context& ctx); 13 | 14 | explicit instance_reference( 15 | instance& referenced_instance, 16 | const sema::sema_type* referenced_base_type = nullptr); 17 | 18 | instance_value_variant value() const override; 19 | instance_value_accessor value_accessor() override; 20 | const instance_value_variant& value_cref() const override; 21 | 22 | void assign(instance_value_variant val) override; 23 | void assign(std::unique_ptr val) override; 24 | void assign_member(unsigned index, std::unique_ptr val) override; 25 | 26 | std::unique_ptr copy() const override; 27 | 28 | instance* find_member(unsigned index) override; 29 | const instance* find_cmember(unsigned index) const override; 30 | sema::single_scope_function_lookup_result_t find_function( 31 | lexer::token name) const override; 32 | 33 | const sema::sema_type& type() const override; 34 | 35 | private: 36 | instance& m_instance; 37 | const sema::sema_type* m_referenced_base_type; 38 | }; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /source/exec/instance/instance_value_accessor.cpp: -------------------------------------------------------------------------------- 1 | #include "exec/instance/instance_value_accessor.hpp" 2 | #include "exec/instance/instance_value_variant.hpp" 3 | 4 | namespace cmsl::exec::inst { 5 | 6 | instance_value_accessor::instance_value_accessor( 7 | const sema::sema_type& type, instance_value_variant& value_ref, 8 | instance_value_observer_t observer) 9 | : m_type{ type } 10 | , m_value_ref{ value_ref } 11 | , m_observer{ std::move(observer) } 12 | { 13 | } 14 | 15 | instance_value_accessor::~instance_value_accessor() 16 | { 17 | if (m_possibly_dirty) { 18 | call_observer(); 19 | } 20 | } 21 | 22 | void instance_value_accessor::set_value(instance_value_variant new_value) 23 | { 24 | m_value_ref = std::move(new_value); 25 | } 26 | 27 | instance_value_variant& instance_value_accessor::access() 28 | { 29 | m_possibly_dirty = true; 30 | return m_value_ref; 31 | } 32 | 33 | void instance_value_accessor::call_observer() const 34 | { 35 | if (m_observer) { 36 | m_observer(m_type, m_value_ref); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /source/exec/instance/instance_value_accessor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "exec/instance/instance_value_observer.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::exec::inst { 8 | class instance_value_variant; 9 | 10 | class instance_value_accessor 11 | { 12 | public: 13 | explicit instance_value_accessor(const sema::sema_type& type, 14 | instance_value_variant& value_ref, 15 | instance_value_observer_t observer = {}); 16 | ~instance_value_accessor(); 17 | 18 | template 19 | void set(T&& new_value) 20 | { 21 | set_value(std::forward(new_value)); 22 | call_observer(); 23 | } 24 | 25 | instance_value_variant& access(); 26 | 27 | private: 28 | void set_value(instance_value_variant new_value); 29 | 30 | void call_observer() const; 31 | 32 | private: 33 | const sema::sema_type& m_type; 34 | instance_value_variant& m_value_ref; 35 | instance_value_observer_t m_observer; 36 | bool m_possibly_dirty{ false }; 37 | }; 38 | } -------------------------------------------------------------------------------- /source/exec/instance/instance_value_alternative.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cmsl::exec::inst { 4 | enum class instance_value_alternative 5 | { 6 | bool_, 7 | int_, 8 | double_, 9 | enum_, 10 | string, 11 | version, 12 | extern_, 13 | list, 14 | project, 15 | library, 16 | executable, 17 | option 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /source/exec/instance/instance_value_observer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace cmsl { 6 | namespace sema { 7 | class sema_type; 8 | } 9 | 10 | namespace exec::inst { 11 | class instance_value_variant; 12 | using instance_value_observer_t = std::function; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /source/exec/instance/list_value_utils.cpp: -------------------------------------------------------------------------------- 1 | #include "exec/instance/list_value_utils.hpp" 2 | #include "exec/instance/instance.hpp" 3 | #include "exec/instance/list_value.hpp" 4 | 5 | namespace cmsl::exec::inst { 6 | 7 | list_value_utils::list_value_utils(const list_value& list) 8 | : m_list{ list } 9 | { 10 | } 11 | std::vector list_value_utils::strings( 12 | const std::string& prefix) const 13 | { 14 | std::vector collected; 15 | collected.reserve(m_list.size()); 16 | 17 | for (auto i = 0u; i < m_list.size(); ++i) { 18 | const auto& instance = m_list.at(i); 19 | const auto& source = instance.value_cref().get_string_cref(); 20 | const auto full_source_path = prefix + source; 21 | collected.emplace_back(full_source_path); 22 | } 23 | 24 | return collected; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /source/exec/instance/list_value_utils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/string.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace cmsl::exec::inst { 10 | 11 | class list_value; 12 | 13 | class list_value_utils 14 | { 15 | public: 16 | explicit list_value_utils(const list_value& list); 17 | 18 | std::vector strings(const std::string& prefix = "") const; 19 | 20 | private: 21 | const list_value& m_list; 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /source/exec/instance/option_value.cpp: -------------------------------------------------------------------------------- 1 | #include "exec/instance/option_value.hpp" 2 | 3 | namespace cmsl::exec::inst { 4 | option_value::option_value(const std::string& description, bool value) 5 | : m_description{ description } 6 | , m_value{ value } 7 | { 8 | } 9 | 10 | const std::string& option_value::description() const 11 | { 12 | return m_description; 13 | } 14 | 15 | bool option_value::value() const 16 | { 17 | return m_value; 18 | } 19 | } -------------------------------------------------------------------------------- /source/exec/instance/option_value.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace cmsl::exec::inst { 6 | class option_value 7 | { 8 | public: 9 | explicit option_value(const std::string& description, bool value = false); 10 | 11 | const std::string& description() const; 12 | 13 | bool value() const; 14 | 15 | private: 16 | std::string m_description; 17 | bool m_value; 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /source/exec/instance/project_value.cpp: -------------------------------------------------------------------------------- 1 | #include "exec/instance/project_value.hpp" 2 | #include "exec/instance/instance.hpp" 3 | #include "exec/instance/list_value_utils.hpp" 4 | 5 | #include "cmake_facade.hpp" 6 | 7 | namespace cmsl::exec::inst { 8 | project_value::project_value(const std::string& name) 9 | : m_name{ name } 10 | { 11 | } 12 | 13 | std::string project_value::name() const 14 | { 15 | return m_name; 16 | } 17 | 18 | void project_value::add_executable(facade::cmake_facade& cmake_facade, 19 | const std::string& name, 20 | const list_value& sources) 21 | { 22 | std::vector extracted_sources = 23 | list_value_utils{ sources }.strings(); 24 | cmake_facade.add_executable(name, extracted_sources); 25 | } 26 | 27 | void project_value::add_library(facade::cmake_facade& cmake_facade, 28 | const std::string& name, 29 | const list_value& sources) 30 | { 31 | std::vector extracted_sources = 32 | list_value_utils{ sources }.strings(); 33 | cmake_facade.add_library(name, extracted_sources); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /source/exec/instance/project_value.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/string.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl { 8 | namespace facade { 9 | class cmake_facade; 10 | } 11 | 12 | namespace exec::inst { 13 | class list_value; 14 | 15 | class project_value 16 | { 17 | public: 18 | explicit project_value(const std::string& name); 19 | 20 | std::string name() const; 21 | 22 | void add_executable(facade::cmake_facade& cmake_facade, 23 | const std::string& name, const list_value& sources); 24 | void add_library(facade::cmake_facade& cmake_facade, const std::string& name, 25 | const list_value& sources); 26 | 27 | private: 28 | std::string m_name; 29 | }; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /source/exec/instance/version_value.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/int_alias.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::exec::inst { 8 | class version_value 9 | { 10 | public: 11 | explicit version_value(int_t major, int_t minor = 0u, int_t patch = 0u, 12 | int_t tweak = 0u); 13 | 14 | // Avoid major and minor macros from sysmacros.h 15 | int_t major_() const; 16 | int_t minor_() const; 17 | int_t patch() const; 18 | int_t tweak() const; 19 | 20 | std::string to_string() const; 21 | 22 | bool operator==(const version_value& rhs) const; 23 | bool operator!=(const version_value& rhs) const; 24 | bool operator<(const version_value& rhs) const; 25 | bool operator<=(const version_value& rhs) const; 26 | bool operator>(const version_value& rhs) const; 27 | bool operator>=(const version_value& rhs) const; 28 | 29 | private: 30 | int_t m_major{ 0u }; 31 | int_t m_minor{ 0u }; 32 | int_t m_patch{ 0u }; 33 | int_t m_tweak{ 0u }; 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /source/exec/module_sema_tree_provider.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/string.hpp" 4 | 5 | namespace cmsl { 6 | namespace sema { 7 | class sema_node; 8 | } 9 | 10 | namespace exec { 11 | class module_sema_tree_provider 12 | { 13 | public: 14 | virtual const sema::sema_node& get_sema_tree( 15 | cmsl::string_view import_path) const = 0; 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /source/exec/module_static_variables_initializer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/string.hpp" 4 | 5 | namespace cmsl::exec { 6 | class module_static_variables_initializer 7 | { 8 | public: 9 | virtual ~module_static_variables_initializer() = default; 10 | 11 | virtual void initialize(cmsl::string_view import_path) = 0; 12 | }; 13 | } -------------------------------------------------------------------------------- /source/exec/scope_context.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/string.hpp" 4 | #include "exec/instance/instance.hpp" 5 | 6 | #include 7 | 8 | namespace cmsl::exec { 9 | class scope_context 10 | { 11 | private: 12 | using instance_t = inst::instance; 13 | 14 | public: 15 | // Used when creating initial function scope or scope in already created 16 | // scope 17 | explicit scope_context(scope_context* parent); 18 | 19 | // Used when entering a method which is member of class_instance 20 | explicit scope_context(instance_t* class_instance); 21 | 22 | void add_variable(unsigned index, std::unique_ptr inst); 23 | instance_t* get_variable(unsigned index); 24 | const instance_t* get_variable(unsigned index) const; 25 | 26 | bool variable_exists(unsigned index) const; 27 | 28 | private: 29 | std::unordered_map> m_variables; 30 | scope_context* m_parent; 31 | instance_t* m_class_instance; 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /source/lexer/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | import "cmake/cmsl_directories.cmsl"; 2 | 3 | void main(cmake::project& p) 4 | { 5 | auto sources = { 6 | // clang-format off 7 | "lexer.cpp", 8 | "lexer.hpp", 9 | "source_location_manipulator.cpp", 10 | "source_location_manipulator.hpp", 11 | "token.cpp", 12 | "token.hpp", 13 | "token_type.cpp", 14 | "token_type.hpp" 15 | // clang-format on 16 | }; 17 | 18 | auto lib = p.add_library("lexer", sources); 19 | lib.include_directories({ cmsl::source_dir }); 20 | 21 | auto common = p.find_library("common"); 22 | lib.link_to(common, cmake::visibility::public); 23 | } 24 | -------------------------------------------------------------------------------- /source/lexer/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | static_library { 2 | name = "lexer" 3 | 4 | include_dirs.public = [ 5 | cmake_variables.CMAKESL_SOURCES_DIR.as_string 6 | ] 7 | 8 | dependencies.public = [ 9 | "common" 10 | ] 11 | 12 | compile_options.public = cmake_variables.CMAKESL_ADDITIONAL_COMPILER_FLAGS.as_list 13 | 14 | files.public = [ 15 | "lexer.cpp", 16 | "lexer.hpp", 17 | "source_location_manipulator.cpp", 18 | "source_location_manipulator.hpp", 19 | "token.cpp", 20 | "token.hpp", 21 | "token_type.cpp", 22 | "token_type.hpp" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /source/lexer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LEXER_SOURCES 2 | lexer.cpp 3 | lexer.hpp 4 | source_location_manipulator.cpp 5 | source_location_manipulator.hpp 6 | token.cpp 7 | token.hpp 8 | token_type.cpp 9 | token_type.hpp 10 | ) 11 | 12 | add_library(lexer "${LEXER_SOURCES}") 13 | target_include_directories(lexer 14 | PRIVATE 15 | ${CMAKESL_SOURCES_DIR} 16 | ) 17 | 18 | target_link_libraries(lexer 19 | PUBLIC 20 | common 21 | ) 22 | 23 | target_compile_options(lexer 24 | PRIVATE 25 | ${CMAKESL_ADDITIONAL_COMPILER_FLAGS} 26 | ) 27 | 28 | -------------------------------------------------------------------------------- /source/lexer/source_location_manipulator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/source_location.hpp" 4 | #include "common/string.hpp" 5 | 6 | namespace cmsl::lexer { 7 | class source_location_manipulator 8 | { 9 | public: 10 | explicit source_location_manipulator(cmsl::string_view source); 11 | 12 | source_location location() const; 13 | 14 | cmsl::string_view::value_type current_char() const; 15 | cmsl::string_view::value_type next_char() const; 16 | 17 | bool is_at_end() const; 18 | bool has_next() const; 19 | 20 | void consume_char(); 21 | 22 | private: 23 | cmsl::string_view::const_iterator current_it() const; 24 | 25 | private: 26 | const cmsl::string_view m_source; 27 | source_location m_source_loc; 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /source/parse/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | import "cmake/cmsl_directories.cmsl"; 2 | 3 | void main(cmake::project& p) 4 | { 5 | auto sources = { "parse_errors_observer.hpp", "parser_utils.cpp", 6 | "parser_utils.hpp" }; 7 | 8 | auto lib = p.add_library("parse", sources); 9 | lib.include_directories({ cmsl::source_dir }); 10 | 11 | auto lexer = p.find_library("lexer"); 12 | lib.link_to(lexer, cmake::visibility::public); 13 | } 14 | -------------------------------------------------------------------------------- /source/parse/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | static_library { 2 | name = "parse" 3 | 4 | include_dirs.public = [ 5 | cmake_variables.CMAKESL_SOURCES_DIR.as_string 6 | ] 7 | 8 | dependencies.public = [ 9 | "lexer" 10 | ] 11 | 12 | compile_options.public = cmake_variables.CMAKESL_ADDITIONAL_COMPILER_FLAGS.as_list 13 | 14 | files.public = [ 15 | "parse_errors_observer.hpp", 16 | "parser_utils.cpp", 17 | "parser_utils.hpp" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /source/parse/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(PARSE_SOURCES 2 | parse_errors_observer.hpp 3 | parser_utils.cpp 4 | parser_utils.hpp 5 | ) 6 | 7 | add_library(parse "${PARSE_SOURCES}") 8 | 9 | target_include_directories(parse 10 | PRIVATE 11 | ${CMAKESL_SOURCES_DIR} 12 | ) 13 | 14 | target_link_libraries(parse 15 | PUBLIC 16 | lexer 17 | ) 18 | 19 | target_compile_options(parse 20 | PRIVATE 21 | ${CMAKESL_ADDITIONAL_COMPILER_FLAGS} 22 | ) 23 | 24 | -------------------------------------------------------------------------------- /source/parse/parse_errors_observer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "lexer/token.hpp" 4 | 5 | namespace cmsl::parse { 6 | class parse_errors_observer 7 | { 8 | public: 9 | virtual ~parse_errors_observer() = default; 10 | 11 | virtual void raise_unexpected_end_of_file(lexer::token token) = 0; 12 | virtual void raise_expected_token(lexer::token token, 13 | lexer::token_type type) = 0; 14 | virtual void raise_unexpected_token(lexer::token token) = 0; 15 | virtual void raise_expected_keyword(lexer::token token, 16 | lexer::token_type keyword) = 0; 17 | virtual void raise_expected_expression(lexer::token token) = 0; 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /source/sema/add_declarative_file_semantic_handler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/string.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::sema { 8 | class sema_function; 9 | 10 | class add_declarative_file_semantic_handler 11 | { 12 | public: 13 | virtual ~add_declarative_file_semantic_handler() = default; 14 | 15 | struct no_script_found 16 | { 17 | }; 18 | struct contains_declarative_cmakesl_script 19 | { 20 | const sema_function* target_creation_function; 21 | }; 22 | struct compilation_failed 23 | { 24 | }; 25 | 26 | using add_declarative_file_result_t = 27 | std::variant; 29 | 30 | virtual add_declarative_file_result_t handle_add_declarative_file( 31 | cmsl::string_view name) = 0; 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /source/sema/add_subdirectory_semantic_handler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/string.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace cmsl::sema { 10 | class expression_node; 11 | class sema_function; 12 | 13 | class add_subdirectory_semantic_handler 14 | { 15 | public: 16 | virtual ~add_subdirectory_semantic_handler() = default; 17 | 18 | struct no_script_found 19 | { 20 | }; 21 | struct contains_old_cmake_script 22 | { 23 | }; 24 | struct contains_cmakesl_script 25 | { 26 | const sema_function* main_function; 27 | }; 28 | struct contains_declarative_cmakesl_script 29 | { 30 | const sema_function* component_creation_function; 31 | }; 32 | struct compilation_failed 33 | { 34 | }; 35 | 36 | using add_subdirectory_result_t = 37 | std::variant; 40 | 41 | virtual add_subdirectory_result_t handle_add_subdirectory( 42 | cmsl::string_view name, 43 | const std::vector>& params) = 0; 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /source/sema/block_node_manipulator.cpp: -------------------------------------------------------------------------------- 1 | #include "sema/block_node_manipulator.hpp" 2 | #include "sema/sema_nodes.hpp" 3 | 4 | namespace cmsl::sema { 5 | 6 | block_node_manipulator::block_node_manipulator(block_node& block) 7 | : m_block_node{ block } 8 | { 9 | } 10 | void block_node_manipulator::append_expression( 11 | std::unique_ptr node) 12 | { 13 | m_block_node.m_nodes.emplace_back(std::move(node)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /source/sema/block_node_manipulator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace cmsl::sema { 6 | 7 | class expression_node; 8 | class block_node; 9 | 10 | class block_node_manipulator 11 | { 12 | public: 13 | explicit block_node_manipulator(block_node& block); 14 | 15 | void append_expression(std::unique_ptr node); 16 | 17 | private: 18 | block_node& m_block_node; 19 | }; 20 | } -------------------------------------------------------------------------------- /source/sema/builtin_sema_function.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sema/sema_function.hpp" 4 | 5 | namespace cmsl::sema { 6 | enum class builtin_function_kind; 7 | class sema_context; 8 | 9 | class builtin_sema_function : public sema_function 10 | { 11 | public: 12 | explicit builtin_sema_function(const sema_context& ctx, 13 | const sema_type& return_type, 14 | function_signature s, 15 | builtin_function_kind kind) 16 | : m_ctx{ ctx } 17 | , m_return_type{ return_type } 18 | , m_signature{ std::move(s) } 19 | , m_kind{ kind } 20 | { 21 | } 22 | 23 | const function_signature& signature() const override { return m_signature; } 24 | 25 | const sema_type& return_type() const override { return m_return_type; } 26 | const sema_type* try_return_type() const override { return &m_return_type; } 27 | 28 | builtin_function_kind kind() const { return m_kind; } 29 | 30 | const sema_context& context() const override { return m_ctx; } 31 | 32 | private: 33 | const sema_context& m_ctx; 34 | const sema_type& m_return_type; 35 | function_signature m_signature; 36 | builtin_function_kind m_kind; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /source/sema/builtin_types_accessor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cmsl::sema { 4 | struct cmake_namespace_types_accessor; 5 | class sema_type; 6 | 7 | struct builtin_types_accessor 8 | { 9 | const sema_type& void_; 10 | const sema_type& bool_; 11 | const sema_type& bool_ref; 12 | const sema_type& int_; 13 | const sema_type& int_ref; 14 | const sema_type& double_; 15 | const sema_type& double_ref; 16 | const sema_type& string; 17 | const sema_type& string_ref; 18 | 19 | const cmake_namespace_types_accessor* cmake{ nullptr }; 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /source/sema/cmake_namespace_types_accessor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cmsl::sema { 4 | class sema_type; 5 | 6 | struct cmake_namespace_types_accessor 7 | { 8 | const sema_type& cxx_compiler_id; 9 | const sema_type& cxx_compiler_id_ref; 10 | const sema_type& cxx_compiler_info; 11 | const sema_type& cxx_compiler_info_ref; 12 | const sema_type& cxx_standard_value; 13 | const sema_type& cxx_standard_value_ref; 14 | const sema_type& visibility; 15 | const sema_type& visibility_ref; 16 | const sema_type& version; 17 | const sema_type& version_ref; 18 | const sema_type& library; 19 | const sema_type& library_ref; 20 | const sema_type& executable; 21 | const sema_type& executable_ref; 22 | const sema_type& project; 23 | const sema_type& project_ref; 24 | const sema_type& option; 25 | const sema_type& option_ref; 26 | const sema_type& system_info; 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /source/sema/enum_creator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sema/sema_type.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl { 8 | 9 | namespace lexer { 10 | class token; 11 | } 12 | 13 | namespace sema { 14 | class factories_provider; 15 | class types_context; 16 | class sema_context; 17 | struct builtin_types_accessor; 18 | 19 | class enum_creator 20 | { 21 | public: 22 | explicit enum_creator(factories_provider& factories, 23 | types_context& types_ctx, sema_context& parent_ctx, 24 | const builtin_types_accessor& builtin_types); 25 | 26 | const sema_type& create(const lexer::token& name, 27 | const std::vector& enumerators, 28 | sema_type::flags_t additional_flags = {}); 29 | 30 | private: 31 | factories_provider& m_factories; 32 | types_context& m_types_ctx; 33 | sema_context& m_parent_ctx; 34 | const builtin_types_accessor& m_builtin_types; 35 | }; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /source/sema/enum_type.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sema/sema_type.hpp" 4 | 5 | namespace cmsl::sema { 6 | class enum_type : public sema_type 7 | { 8 | public: 9 | explicit enum_type(const sema_context& ctx, ast::type_representation name, 10 | std::vector enumerators, 11 | flags_t additional_flags = {}) 12 | : sema_type{ ctx, std::move(name), {}, flags::enum_ | additional_flags } 13 | , m_enumerators{ std::move(enumerators) } 14 | { 15 | } 16 | 17 | const std::vector& enumerators() const 18 | { 19 | return m_enumerators; 20 | } 21 | 22 | const lexer::token& enumerator(unsigned value) const 23 | { 24 | return m_enumerators[value]; 25 | } 26 | 27 | private: 28 | std::vector m_enumerators; 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /source/sema/factories_provider.cpp: -------------------------------------------------------------------------------- 1 | #include "sema/factories_provider.hpp" 2 | 3 | #include "sema/factories.hpp" 4 | #include "sema/sema_context.hpp" 5 | #include "sema/sema_function.hpp" 6 | #include "sema/sema_type.hpp" 7 | 8 | namespace cmsl::sema { 9 | factories_provider::~factories_provider() 10 | { 11 | } 12 | 13 | sema_context_factory factories_provider::context_factory() 14 | { 15 | return sema_context_factory{ m_contextes }; 16 | } 17 | 18 | sema_function_factory factories_provider::function_factory() 19 | { 20 | return sema_function_factory{ m_functions }; 21 | } 22 | 23 | sema_type_factory factories_provider::type_factory(types_context& ctx) 24 | { 25 | return sema_type_factory{ ctx, m_types }; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /source/sema/factories_provider.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace cmsl::sema { 7 | class sema_context; 8 | class sema_function; 9 | class sema_type; 10 | class sema_context_factory; 11 | class sema_function_factory; 12 | class sema_type_factory; 13 | class types_context; 14 | 15 | class factories_provider 16 | { 17 | public: 18 | ~factories_provider(); 19 | 20 | sema_context_factory context_factory(); 21 | sema_function_factory function_factory(); 22 | sema_type_factory type_factory(types_context& ctx); 23 | 24 | private: 25 | std::vector> m_contextes; 26 | std::vector> m_functions; 27 | std::vector> m_types; 28 | }; 29 | } -------------------------------------------------------------------------------- /source/sema/function_lookup_result.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace cmsl::sema { 6 | class sema_function; 7 | 8 | using single_scope_function_lookup_result_t = 9 | std::vector; 10 | 11 | // Is the vector needed? When function is searched for, and it's found in some 12 | // scope, the only results that are returned are the functions from this scope. 13 | using function_lookup_result_t = 14 | std::vector; 15 | } 16 | -------------------------------------------------------------------------------- /source/sema/function_signature.cpp: -------------------------------------------------------------------------------- 1 | #include "sema/function_signature.hpp" 2 | #include "sema/sema_type.hpp" 3 | 4 | #include 5 | namespace cmsl::sema { 6 | bool parameter_declaration::operator==(const parameter_declaration& rhs) const 7 | { 8 | return std::tie(ty, name) == std::tie(rhs.ty, rhs.name); 9 | } 10 | 11 | bool function_signature::operator==(const function_signature& rhs) const 12 | { 13 | return std::tie(name, params) == std::tie(rhs.name, rhs.params); 14 | } 15 | } -------------------------------------------------------------------------------- /source/sema/function_signature.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "lexer/token.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::sema { 8 | class sema_type; 9 | 10 | struct parameter_declaration 11 | { 12 | const sema_type& ty; 13 | lexer::token name; 14 | unsigned index; 15 | 16 | bool operator==(const parameter_declaration& rhs) const; 17 | }; 18 | 19 | struct function_signature 20 | { 21 | lexer::token name; 22 | std::vector params{}; 23 | 24 | bool operator==(const function_signature& rhs) const; 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /source/sema/generic_type_creation_utils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cmsl { 4 | namespace ast { 5 | class type_representation; 6 | } 7 | 8 | namespace errors { 9 | class errors_observer; 10 | } 11 | 12 | namespace sema { 13 | class builtin_token_provider; 14 | class factories_provider; 15 | class sema_context; 16 | class sema_generic_type_factory; 17 | class sema_type; 18 | class types_context; 19 | struct builtin_types_accessor; 20 | 21 | class generic_type_creation_utils 22 | { 23 | public: 24 | explicit generic_type_creation_utils( 25 | sema_context& generic_types_context, factories_provider& factories, 26 | errors::errors_observer& errors_observer, 27 | const builtin_token_provider& builtin_token_provider, 28 | const builtin_types_accessor& builtin_types, types_context& types_ctx); 29 | 30 | const sema_type& list_of_strings(); 31 | 32 | private: 33 | const sema_type& get_or_create_generic_type( 34 | const ast::type_representation& type_representation); 35 | 36 | private: 37 | sema_context& m_generic_types_context; 38 | factories_provider& m_factories; 39 | errors::errors_observer& m_errors_observer; 40 | const builtin_token_provider& m_builtin_token_provider; 41 | const builtin_types_accessor& m_builtin_types; 42 | types_context& m_types_ctx; 43 | }; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /source/sema/homogeneous_generic_type.cpp: -------------------------------------------------------------------------------- 1 | #include "sema/homogeneous_generic_type.hpp" 2 | #include "homogeneous_generic_type.hpp" 3 | 4 | namespace cmsl::sema { 5 | homogeneous_generic_type::homogeneous_generic_type( 6 | const sema_context& ctx, ast::type_representation name, 7 | const sema_type& value_type) 8 | : sema_type{ ctx, std::move(name), {}, flags::builtin } 9 | , m_value_type{ value_type } 10 | { 11 | } 12 | 13 | const sema_type& homogeneous_generic_type::value_type() const 14 | { 15 | return m_value_type; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /source/sema/homogeneous_generic_type.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sema/sema_type.hpp" 4 | 5 | namespace cmsl::sema { 6 | class homogeneous_generic_type : public sema_type 7 | { 8 | public: 9 | explicit homogeneous_generic_type(const sema_context& ctx, 10 | ast::type_representation name, 11 | const sema_type& value_type); 12 | 13 | const sema_type& value_type() const; 14 | 15 | private: 16 | const sema_type& m_value_type; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /source/sema/identifier_info.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace cmsl::sema { 6 | class sema_type; 7 | struct identifier_info 8 | { 9 | std::reference_wrapper type; 10 | unsigned index; 11 | }; 12 | 13 | struct builtin_identifier_info 14 | { 15 | identifier_info id_info; 16 | std::string cmake_variable_name; 17 | }; 18 | } -------------------------------------------------------------------------------- /source/sema/identifiers_index_provider.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cmsl::sema { 4 | class identifiers_index_provider 5 | { 6 | public: 7 | using id_t = unsigned; 8 | 9 | static id_t get_next() 10 | { 11 | static id_t current{ 0u }; 12 | return current++; 13 | } 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /source/sema/import_handler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/string.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::sema { 8 | struct qualified_contextes; 9 | 10 | class import_handler 11 | { 12 | public: 13 | virtual ~import_handler() = default; 14 | 15 | // It could be std::optional, but gmock complains about its copy ctor. 16 | virtual std::unique_ptr handle_import( 17 | cmsl::string_view path) = 0; 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /source/sema/qualified_contextes.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace cmsl { 6 | namespace errors { 7 | class errors_observer; 8 | } 9 | 10 | namespace sema { 11 | class enum_values_context; 12 | class functions_context; 13 | class identifiers_context; 14 | class types_context; 15 | 16 | struct qualified_contextes 17 | { 18 | qualified_contextes(qualified_contextes&&) = default; 19 | qualified_contextes& operator=(qualified_contextes&&) = default; 20 | 21 | ~qualified_contextes(); 22 | 23 | std::unique_ptr enums; 24 | std::unique_ptr functions; 25 | std::unique_ptr ids; 26 | std::unique_ptr types; 27 | 28 | qualified_contextes clone() const; 29 | qualified_contextes collect_exported_stuff() const; 30 | bool merge_imported_stuff(const qualified_contextes& imported, 31 | errors::errors_observer& errs); 32 | }; 33 | } 34 | } -------------------------------------------------------------------------------- /source/sema/sema_function.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "lexer/token.hpp" 4 | #include "sema/function_signature.hpp" 5 | 6 | namespace cmsl::sema { 7 | class sema_context; 8 | 9 | class sema_function 10 | { 11 | public: 12 | virtual ~sema_function() = default; 13 | virtual const function_signature& signature() const = 0; 14 | virtual const sema_type& return_type() const = 0; 15 | virtual const sema_type* try_return_type() const = 0; 16 | virtual const sema_context& context() const = 0; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /source/sema/sema_node.cpp: -------------------------------------------------------------------------------- 1 | #include "sema/sema_node.hpp" 2 | 3 | #include "ast/ast_node.hpp" 4 | #include "sema_node.hpp" 5 | 6 | namespace cmsl::sema { 7 | sema::sema_node::sema_node(const ast::ast_node& ast_node) 8 | : m_ast_node{ ast_node } 9 | { 10 | } 11 | 12 | source_location sema_node::begin_location() const 13 | { 14 | return m_ast_node.begin_location(); 15 | } 16 | 17 | source_location sema_node::end_location() const 18 | { 19 | return m_ast_node.end_location(); 20 | } 21 | 22 | const ast::ast_node& sema_node::ast_node() const 23 | { 24 | return m_ast_node; 25 | } 26 | 27 | void sema_node::set_parent(const sema_node& node, passkey) 28 | { 29 | m_parent = &node; 30 | } 31 | 32 | const sema_node* sema_node::parent() const 33 | { 34 | return m_parent; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /source/sema/sema_node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cmsl { 4 | struct source_location; 5 | 6 | namespace ast { 7 | class ast_node; 8 | } 9 | 10 | namespace sema { 11 | class sema_node_visitor; 12 | 13 | class sema_node 14 | { 15 | protected: 16 | struct passkey 17 | { 18 | }; 19 | 20 | public: 21 | explicit sema_node(const ast::ast_node& ast_node); 22 | 23 | virtual ~sema_node() = default; 24 | 25 | virtual void visit(sema_node_visitor& visitor) const = 0; 26 | virtual source_location begin_location() const; 27 | virtual source_location end_location() const; 28 | const ast::ast_node& ast_node() const; 29 | const sema_node* parent() const; 30 | void set_parent(const sema_node& node, passkey); 31 | 32 | private: 33 | const ast::ast_node& m_ast_node; 34 | const sema_node* m_parent{ nullptr }; 35 | }; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /source/sema/sema_tree_building_context.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "errors/errors_observer.hpp" 4 | #include "sema/factories_provider.hpp" 5 | #include "sema/functions_context.hpp" 6 | #include "sema/types_context.hpp" 7 | 8 | namespace cmsl::sema { 9 | struct sema_tree_building_context 10 | { 11 | errors::errors_observer errors_observer; 12 | sema::functions_context_impl functions_ctx; 13 | sema::types_context_impl types_ctx; 14 | sema::factories_provider factories; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /source/sema/type_member_info.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "lexer/token.hpp" 4 | 5 | namespace cmsl::sema { 6 | class sema_type; 7 | struct member_info 8 | { 9 | lexer::token name; 10 | const sema_type& ty; 11 | unsigned index; 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /source/sema/variable_initialization_checker.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "lexer/token.hpp" 4 | #include "sema/variable_initialization_issue.hpp" 5 | 6 | #include 7 | 8 | namespace cmsl::sema { 9 | class sema_type; 10 | class expression_node; 11 | class designated_initializers_node; 12 | 13 | class variable_initialization_checker 14 | { 15 | public: 16 | using issue_t = variable_initialization_issue_t; 17 | 18 | // Returns a vector of issues. If the vector is empty, variable can be 19 | // initialized with the given expression. 20 | std::vector check( 21 | const sema_type& variable_type, 22 | const expression_node& initialization_expression) const; 23 | 24 | private: 25 | std::optional check_initialization_of_reference_type( 26 | const sema_type& variable_type, 27 | const expression_node& initialization_expression) const; 28 | std::optional check_initialization( 29 | const sema_type& variable_type, 30 | const expression_node& initialization_expression) const; 31 | 32 | std::vector check_designated_initializers( 33 | const sema_type& variable_type, 34 | const designated_initializers_node& designated_initializers) const; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /test/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | void main(cmake::project p) 2 | { 3 | add_subdirectory("ast", p); 4 | add_subdirectory("common", p); 5 | add_subdirectory("errors_observer", p); 6 | add_subdirectory("errors_observer_mock", p); 7 | add_subdirectory("exec", p); 8 | add_subdirectory("lexer", p); 9 | add_subdirectory("lexer_error", p); 10 | add_subdirectory("sema", p); 11 | add_subdirectory("source_location_manipulator", p); 12 | 13 | auto system = cmake::get_system_info().id; 14 | if (system != cmake::system_id::windows) { 15 | cmake::add_custom_target("RUN_ALL_TEST", { cmake::ctest_command() }); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CMAKESL_TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}) 2 | 3 | include_directories(${CMAKESL_FACADE_DIR}) 4 | 5 | add_subdirectory(ast) 6 | add_subdirectory(decl_ast) 7 | add_subdirectory(common) 8 | add_subdirectory(errors_observer) 9 | add_subdirectory(errors_observer_mock) 10 | add_subdirectory(exec) 11 | add_subdirectory(lexer) 12 | add_subdirectory(lexer_error) 13 | add_subdirectory(sema) 14 | add_subdirectory(source_location_manipulator) 15 | 16 | if(CMAKESL_WITH_TOOLS) 17 | add_subdirectory(tools) 18 | endif() 19 | 20 | if(NOT WIN32) 21 | add_custom_target(RUN_ALL_TEST COMMAND ${CMAKE_CTEST_COMMAND}) 22 | endif() 23 | -------------------------------------------------------------------------------- /test/ast/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | import "cmake/cmsl_directories.cmsl"; 2 | import "cmake/test_utils.cmsl"; 3 | 4 | void main(cmake::project p) 5 | { 6 | auto include_dirs = { cmsl::source_dir, cmsl::facade_dir, cmsl::root_dir }; 7 | 8 | cmsl::test::add_test( 9 | p, 10 | { .name = "ast", 11 | .sources = { "parser_test.cpp", "escaped_string_builder_test.cpp" }, 12 | .include_dirs = include_dirs, 13 | .libraries = { "ast", "lexer", "errors", "tests_common" } }); 14 | 15 | cmsl::test::add_test(p, 16 | { .name = "ast_error", 17 | .sources = { "parser_error_test.cpp" }, 18 | .include_dirs = include_dirs, 19 | .libraries = { "ast", "lexer", "errors_observer_mock", 20 | "tests_common" } }); 21 | } 22 | -------------------------------------------------------------------------------- /test/ast/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKESL_DIR}/cmake/cmsl_cmake_utils.cmake) 2 | 3 | cmsl_add_test( 4 | NAME 5 | ast 6 | SOURCES 7 | parser_test.cpp 8 | escaped_string_builder_test.cpp 9 | INCLUDE_DIRS 10 | ${CMAKESL_SOURCES_DIR} 11 | ${CMAKESL_FACADE_SOURCES_DIR} 12 | ${CMAKESL_DIR} 13 | LIBRARIES 14 | ast 15 | lexer 16 | errors 17 | tests_common 18 | ) 19 | 20 | cmsl_add_test( 21 | NAME 22 | ast_error 23 | SOURCES 24 | parser_error_test.cpp 25 | INCLUDE_DIRS 26 | ${CMAKESL_SOURCES_DIR} 27 | ${CMAKESL_DIR} 28 | LIBRARIES 29 | ast 30 | lexer 31 | errors_observer_mock 32 | tests_common 33 | ) 34 | -------------------------------------------------------------------------------- /test/ast/DISABLED_CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | import "cmake/test_utils.dcmsl"; 2 | 3 | cmsl_test_executable { 4 | name = "ast" 5 | files.public = [ 6 | "parser_test.cpp", 7 | "escaped_string_builder_test.cpp" 8 | ] 9 | 10 | dependencies.public += [ 11 | "ast", 12 | "lexer", 13 | "errors", 14 | "tests_common" 15 | ] 16 | 17 | include_dirs.public = [ 18 | cmake_variables.CMAKESL_SOURCES_DIR.as_string, 19 | cmake_variables.CMAKESL_FACADE_SOURCES_DIR.as_string, 20 | cmake_variables.CMAKESL_DIR.as_string 21 | ] 22 | } 23 | 24 | void main(cmake::project p) 25 | { 26 | auto include_dirs = { cmsl::source_dir, cmsl::facade_dir, cmsl::root_dir }; 27 | 28 | cmsl::test::add_test( 29 | p, 30 | { .name = "ast", 31 | .sources = { "parser_test.cpp", "escaped_string_builder_test.cpp" }, 32 | .include_dirs = include_dirs, 33 | .libraries = { "ast", "lexer", "errors", "tests_common" } }); 34 | 35 | cmsl::test::add_test(p, 36 | { .name = "ast_error", 37 | .sources = { "parser_error_test.cpp" }, 38 | .include_dirs = include_dirs, 39 | .libraries = { "ast", "lexer", "errors_observer_mock", 40 | "tests_common" } }); 41 | } 42 | -------------------------------------------------------------------------------- /test/ast/escaped_string_builder_test.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/escaped_string_builder.hpp" 2 | 3 | #include 4 | 5 | namespace cmsl::ast::test { 6 | using ::testing::Eq; 7 | 8 | TEST(EscapedStringBuilderTest, EscapesCorrectly) 9 | { 10 | cmsl::string_view to_escape = "\\\\foo\\tbar\\nbaz"; 11 | const auto result = escaped_string_builder::escape(to_escape); 12 | EXPECT_THAT(result, Eq("\\foo\tbar\nbaz")); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/ast/mock/ast_node_mock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/ast_node.hpp" 4 | #include "ast/ast_node_visitor.hpp" 5 | 6 | #include 7 | 8 | namespace cmsl::ast::test { 9 | class ast_node_mock : public ast_node 10 | { 11 | public: 12 | MOCK_CONST_METHOD1(visit, void(ast_node_visitor& visitor)); 13 | MOCK_CONST_METHOD0(begin_location, source_location()); 14 | MOCK_CONST_METHOD0(end_location, source_location()); 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /test/common/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | import "cmake/cmsl_directories.cmsl"; 2 | import "cmake/test_utils.cmsl"; 3 | 4 | void main(cmake::project p) 5 | { 6 | cmsl::test::add_library( 7 | p, 8 | { .name = "tests_common", 9 | .sources = { "tokens.cpp", "tokens.hpp" }, 10 | .include_dirs = { cmsl::root_dir, cmsl::source_dir } }); 11 | } 12 | -------------------------------------------------------------------------------- /test/common/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | static_library { 2 | name = "tests_common" 3 | 4 | files.public = [ 5 | "tokens.cpp", 6 | "tokens.hpp" 7 | ] 8 | 9 | include_dirs.public = [ 10 | cmake_variables.CMAKESL_SOURCES_DIR.as_string, 11 | cmake_variables.CMAKESL_DIR.as_string 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /test/common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CMAKESL_TEST_COMMON_SOURCES 2 | tokens.cpp 3 | tokens.hpp 4 | ) 5 | 6 | add_library(tests_common "${CMAKESL_TEST_COMMON_SOURCES}") 7 | target_include_directories(tests_common 8 | PRIVATE 9 | ${CMAKESL_SOURCES_DIR} 10 | ${CMAKESL_DIR} 11 | ) 12 | -------------------------------------------------------------------------------- /test/decl_ast/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | import "cmake/test_utils.dcmsl"; 2 | 3 | cmsl_test_executable { 4 | name = "decl_ast" 5 | 6 | files.public = [ 7 | "parser_test.cpp" 8 | ] 9 | 10 | include_dirs.public = [ 11 | cmake_variables.CMAKESL_SOURCES_DIR.as_string, 12 | cmake_variables.CMAKESL_FACADE_DIR.as_string, 13 | cmake_variables.CMAKESL_DIR.as_string 14 | ] 15 | 16 | dependencies.public += [ 17 | "decl_ast", 18 | "lexer", 19 | "errors_observer_mock", 20 | "tests_common" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /test/decl_ast/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKESL_DIR}/cmake/cmsl_cmake_utils.cmake) 2 | 3 | cmsl_add_test( 4 | NAME 5 | decl_ast 6 | SOURCES 7 | parser_test.cpp 8 | INCLUDE_DIRS 9 | ${CMAKESL_SOURCES_DIR} 10 | ${CMAKESL_FACADE_SOURCES_DIR} 11 | ${CMAKESL_DIR} 12 | LIBRARIES 13 | decl_ast 14 | lexer 15 | errors_observer_mock 16 | tests_common 17 | ) 18 | -------------------------------------------------------------------------------- /test/errors_observer/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | import "cmake/cmsl_directories.cmsl"; 2 | import "cmake/test_utils.cmsl"; 3 | 4 | void main(cmake::project p) 5 | { 6 | cmsl::test::add_test( 7 | p, 8 | { .name = "errors_observer", 9 | .sources = { "errors_observer.cpp" }, 10 | .include_dirs = { cmsl::source_dir, cmsl::facade_dir, cmsl::root_dir }, 11 | .libraries = { "errors" } }); 12 | } 13 | -------------------------------------------------------------------------------- /test/errors_observer/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | import "cmake/test_utils.dcmsl"; 2 | 3 | cmsl_test_executable { 4 | name = "errors_observer" 5 | 6 | files.public = [ 7 | "errors_observer.cpp" 8 | ] 9 | 10 | include_dirs.public = [ 11 | cmake_variables.CMAKESL_SOURCES_DIR.as_string, 12 | cmake_variables.CMAKESL_FACADE_DIR.as_string, 13 | cmake_variables.CMAKESL_DIR.as_string 14 | ] 15 | 16 | dependencies.public += [ 17 | "errors" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /test/errors_observer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKESL_DIR}/cmake/cmsl_cmake_utils.cmake) 2 | 3 | cmsl_add_test( 4 | NAME 5 | errors_observer 6 | SOURCES 7 | errors_observer.cpp 8 | INCLUDE_DIRS 9 | ${CMAKESL_SOURCES_DIR} 10 | ${CMAKESL_FACADE_SOURCES_DIR} 11 | ${CMAKESL_DIR} 12 | LIBRARIES 13 | errors 14 | ) 15 | -------------------------------------------------------------------------------- /test/errors_observer/errors_observer.cpp: -------------------------------------------------------------------------------- 1 | #include "errors/errors_observer.hpp" 2 | #include "errors/error.hpp" 3 | #include "test/mock/cmake_facade_mock.hpp" 4 | 5 | #include 6 | #include 7 | 8 | namespace cmsl::errors::test { 9 | using ::testing::Ne; 10 | using ::testing::_; 11 | 12 | TEST(ErrorsObserverTest, WithoutStreamAndFacade_NotifyError_DoesntFail) 13 | { 14 | errors_observer observer; 15 | error err{}; 16 | EXPECT_NO_FATAL_FAILURE(observer.notify_error(err)); 17 | } 18 | 19 | TEST(ErrorsObserverTest, WithStream_NotifyError_ForwardsErrorToStream) 20 | { 21 | std::ostringstream oss; 22 | errors_observer observer{ oss }; 23 | error err{}; 24 | err.message = "foo"; 25 | 26 | observer.notify_error(err); 27 | 28 | const auto found = oss.str().find("error: foo"); 29 | EXPECT_THAT(found, Ne(std::string::npos)); 30 | } 31 | 32 | TEST(ErrorsObserverTest, WithFacade_NotifyError_ForwardsErrorToFacade) 33 | { 34 | exec::test::cmake_facade_mock facade_mock; 35 | errors_observer observer{ &facade_mock }; 36 | error err{}; 37 | EXPECT_CALL(facade_mock, error(_)); 38 | 39 | observer.notify_error(err); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /test/errors_observer_mock/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | import "cmake/cmsl_directories.cmsl"; 2 | import "cmake/test_utils.cmsl"; 3 | 4 | void main(cmake::project p) 5 | { 6 | cmsl::test::add_library( 7 | p, 8 | { .name = "errors_observer_mock", 9 | .sources = { "errors_observer_mock.cpp" }, 10 | .include_dirs = { cmsl::source_dir, cmsl::test_dir } }); 11 | } 12 | -------------------------------------------------------------------------------- /test/errors_observer_mock/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(ERRORS_OBSERVER_MOCK_SOURCES 2 | errors_observer_mock.cpp 3 | ) 4 | 5 | add_library(errors_observer_mock "${ERRORS_OBSERVER_MOCK_SOURCES}") 6 | target_include_directories(errors_observer_mock 7 | PRIVATE 8 | ${CMAKESL_SOURCES_DIR} 9 | ${CMAKESL_TESTS_DIR} 10 | "${gtest_SOURCE_DIR}/include" 11 | "${gmock_SOURCE_DIR}/include" 12 | ) 13 | 14 | target_compile_options(errors_observer_mock 15 | PRIVATE 16 | ${CMAKESL_ADDITIONAL_COMPILER_FLAGS} 17 | ) 18 | -------------------------------------------------------------------------------- /test/errors_observer_mock/errors_observer_mock.cpp: -------------------------------------------------------------------------------- 1 | #include "errors_observer_mock/errors_observer_mock.hpp" 2 | #include "errors/errors_observer.hpp" 3 | 4 | namespace { 5 | cmsl::errors::test::errors_observer_mock* errors_observer_mock_ptr; 6 | } 7 | 8 | namespace cmsl::errors { 9 | namespace test { 10 | errors_observer_mock::errors_observer_mock() 11 | { 12 | assert(!errors_observer_mock_ptr); 13 | errors_observer_mock_ptr = this; 14 | } 15 | 16 | errors_observer_mock::~errors_observer_mock() 17 | { 18 | errors_observer_mock_ptr = nullptr; 19 | } 20 | } 21 | 22 | errors_observer::errors_observer(facade::cmake_facade*) 23 | { 24 | } 25 | 26 | void errors_observer::notify_error(const cmsl::errors::error& error) 27 | { 28 | errors_observer_mock_ptr->notify_error(error); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/errors_observer_mock/errors_observer_mock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "errors/error.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::errors::test { 8 | struct errors_observer_mock 9 | { 10 | errors_observer_mock(); 11 | ~errors_observer_mock(); 12 | 13 | MOCK_METHOD1(notify_error, void(const error&)); 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /test/exec/add_subdirectory_test/foo/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | int main(double value) 2 | { 3 | return int(value * 10.0); 4 | } 5 | -------------------------------------------------------------------------------- /test/exec/add_subdirectory_test/import/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | import "add_subdirectory_test/import/foo.cmsl"; 2 | 3 | void main(double value) 4 | { 5 | foo::bar /= 10.0; 6 | } 7 | -------------------------------------------------------------------------------- /test/exec/add_subdirectory_test/import/foo.cmsl: -------------------------------------------------------------------------------- 1 | namespace foo { 2 | export auto bar = 4.2; 3 | } 4 | -------------------------------------------------------------------------------- /test/exec/declarative/custom_static_library.dcmsl: -------------------------------------------------------------------------------- 1 | component custom_static_library : static_library { 2 | dependencies.public = [ 3 | "custom_dependency" 4 | ] 5 | } 6 | 7 | custom_static_library { 8 | name = "library_name" 9 | } 10 | -------------------------------------------------------------------------------- /test/exec/declarative/custom_static_library_for_import.dcmsl: -------------------------------------------------------------------------------- 1 | component custom_static_library : static_library { 2 | dependencies.public = [ 3 | "custom_dependency" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /test/exec/declarative/custom_static_library_with_list_appending.dcmsl: -------------------------------------------------------------------------------- 1 | component custom_static_library : static_library { 2 | dependencies.public = [ 3 | "custom_dependency" 4 | ] 5 | } 6 | 7 | custom_static_library { 8 | name = "library_name" 9 | 10 | dependencies.public += [ 11 | "another_custom_dependency" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /test/exec/declarative/custom_static_library_with_string_appending.dcmsl: -------------------------------------------------------------------------------- 1 | component custom_static_library : static_library { 2 | dependencies.public = [ 3 | "custom_dependency" 4 | ] 5 | } 6 | 7 | custom_static_library { 8 | name = "library_name" 9 | dependencies.public += "another_custom_dependency" 10 | } 11 | -------------------------------------------------------------------------------- /test/exec/declarative/executable.dcmsl: -------------------------------------------------------------------------------- 1 | executable { 2 | name = "executable_name" 3 | files.public = [ 4 | "exec.cpp" 5 | ] 6 | 7 | include_dirs.public = [ 8 | "include" 9 | ] 10 | 11 | compile_options.public = [ 12 | "-DANSWER=42" 13 | ] 14 | 15 | compile_definitions.public = [ 16 | "SOME_DEF=42" 17 | ] 18 | 19 | dependencies.public = [ 20 | "dependency", 21 | "another_dependency" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /test/exec/declarative/foo/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | static_library { 2 | name = "foo" 3 | files.public = [ 4 | "foo.cpp" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /test/exec/declarative/import_custom_static_library.dcmsl: -------------------------------------------------------------------------------- 1 | import "declarative/custom_static_library_for_import.dcmsl"; 2 | 3 | custom_static_library { 4 | name = "library_name" 5 | } 6 | -------------------------------------------------------------------------------- /test/exec/declarative/static_library.dcmsl: -------------------------------------------------------------------------------- 1 | static_library { 2 | name = "library_name" 3 | files.public = [ 4 | "library.cpp" 5 | ] 6 | 7 | include_dirs.public = [ 8 | "include" 9 | ] 10 | 11 | compile_options.public = [ 12 | "-DANSWER=42" 13 | ] 14 | 15 | compile_definitions.public = [ 16 | "SOME_DEF=42" 17 | ] 18 | 19 | dependencies.public = [ 20 | "dependency", 21 | "another_dependency" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /test/exec/declarative/static_library_with_cmake_variables.dcmsl: -------------------------------------------------------------------------------- 1 | static_library { 2 | name = cmake_variables.LIBRARY_NAME.as_string 3 | files.public = cmake_variables.LIBRARY_PUBLIC_FILES.as_list 4 | } 5 | -------------------------------------------------------------------------------- /test/exec/declarative/static_library_with_name_prefix.dcmsl: -------------------------------------------------------------------------------- 1 | static_library { 2 | name = "library_name" 3 | name_prefix = "prefix_" 4 | 5 | files.public = [ "library.cpp" ] 6 | } 7 | -------------------------------------------------------------------------------- /test/exec/declarative/static_library_with_name_suffix.dcmsl: -------------------------------------------------------------------------------- 1 | static_library { 2 | name = "library_name" 3 | name_suffix = "_suffix" 4 | 5 | files.public = [ "library.cpp" ] 6 | } 7 | -------------------------------------------------------------------------------- /test/exec/declarative/static_library_with_not_existing_cmake_variable.dcmsl: -------------------------------------------------------------------------------- 1 | static_library { 2 | name = "foo" 3 | files.public = cmake_variables.NOT_EXISTING_VARIABLE.as_list 4 | } 5 | -------------------------------------------------------------------------------- /test/exec/declarative/test_executable.dcmsl: -------------------------------------------------------------------------------- 1 | test_executable { 2 | name = "test_executable_name" 3 | files.public = [ 4 | "test_exec.cpp" 5 | ] 6 | 7 | include_dirs.public = [ 8 | "include" 9 | ] 10 | 11 | compile_options.public = [ 12 | "-DANSWER=42" 13 | ] 14 | 15 | dependencies.public = [ 16 | "dependency", 17 | "another_dependency" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /test/exec/forwarding_lists_type_smoke_test.cpp: -------------------------------------------------------------------------------- 1 | #include "test/exec/smoke_test_fixture.hpp" 2 | 3 | #include 4 | 5 | namespace cmsl::exec::test { 6 | using ::testing::Eq; 7 | 8 | using ForwardingListsTypeSmokeTest = ExecutionSmokeTest; 9 | 10 | TEST_F(ForwardingListsTypeSmokeTest, DefaultConstruction) 11 | { 12 | const auto source = "int main()" 13 | "{" 14 | " decl::forwarding_lists lists;" 15 | "" 16 | " auto all_empty = lists.private.empty()" 17 | " && lists.public.empty()" 18 | " && lists.interface.empty();" 19 | "" 20 | " return int(all_empty);" 21 | "}"; 22 | const auto result = m_executor->execute(source); 23 | EXPECT_THAT(result, Eq(1)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/exec/function_smoke_test.cpp: -------------------------------------------------------------------------------- 1 | #include "test/exec/smoke_test_fixture.hpp" 2 | 3 | #include 4 | 5 | namespace cmsl::exec::test { 6 | using ::testing::Eq; 7 | 8 | using FunctionSmokeTest = ExecutionSmokeTest; 9 | 10 | TEST_F(FunctionSmokeTest, Recursion) 11 | { 12 | // The n_1 and n_2 are to ensure that local variables have their own scope. 13 | const auto source = "int fib(int n)" 14 | "{" 15 | " if(n == 0)" 16 | " {" 17 | " return 0;" 18 | " }" 19 | " if(n == 1)" 20 | " {" 21 | " return 1;" 22 | " }" 23 | "" 24 | " auto n_1 = fib(n - 1);" 25 | " auto n_2 = fib(n - 2);" 26 | "" 27 | " return n_1 + n_2;" 28 | "}" 29 | "" 30 | "int main()" 31 | "{" 32 | " return fib(9) + 8;" 33 | "}"; 34 | const auto result = m_executor->execute(source); 35 | EXPECT_THAT(result, Eq(42)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /test/exec/import_test/baz.cmsl: -------------------------------------------------------------------------------- 1 | import "import_test/foo.cmsl"; 2 | 3 | namespace baz { 4 | int change_and_get() 5 | { 6 | auto old = foo::bar; 7 | foo::bar = 24; 8 | return old; 9 | } 10 | 11 | export auto qux = change_and_get(); 12 | } 13 | -------------------------------------------------------------------------------- /test/exec/import_test/foo.cmsl: -------------------------------------------------------------------------------- 1 | namespace foo { 2 | export auto bar = 42; 3 | 4 | export auto baz() 5 | { 6 | return 42; 7 | } 8 | 9 | export class qux 10 | { 11 | int get() { return 42; } 12 | }; 13 | 14 | export enum top { kek }; 15 | } 16 | -------------------------------------------------------------------------------- /test/exec/mock/function_caller_mock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "exec/function_caller.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::exec::test { 8 | class function_caller2_mock : public function_caller 9 | { 10 | private: 11 | using inst_t = inst::instance; 12 | 13 | public: 14 | MOCK_METHOD3(call, 15 | std::unique_ptr(const sema::sema_function&, 16 | const std::vector&, 17 | inst::instances_holder_interface&)); 18 | 19 | MOCK_METHOD4(call_member, 20 | std::unique_ptr(inst_t&, const sema::sema_function&, 21 | const std::vector&, 22 | inst::instances_holder_interface&)); 23 | 24 | MOCK_METHOD2(call_add_subdirectory_with_cmakesl_script, 25 | std::unique_ptr(const std::string&, 26 | const std::vector&)); 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /test/exec/mock/identifiers_context_mock.hpp: -------------------------------------------------------------------------------- 1 | #include "exec/identifiers_context.hpp" 2 | 3 | #include 4 | 5 | namespace cmsl::exec::test { 6 | class identifiers_context_mock : public identifiers_context 7 | { 8 | public: 9 | MOCK_METHOD1(lookup_identifier, inst::instance*(unsigned index)); 10 | MOCK_METHOD0(get_class_instance, inst::instance*()); 11 | }; 12 | } -------------------------------------------------------------------------------- /test/exec/mock/instance_mock.hpp: -------------------------------------------------------------------------------- 1 | #include "exec/instance/instance.hpp" 2 | #include "sema/sema_type.hpp" 3 | 4 | #include 5 | 6 | namespace cmsl::exec::inst::test { 7 | class instance_mock : public instance 8 | { 9 | private: 10 | public: 11 | MOCK_CONST_METHOD0(copy, std::unique_ptr()); 12 | 13 | MOCK_CONST_METHOD0(value, instance_value_variant()); 14 | MOCK_METHOD0(value_accessor, instance_value_accessor()); 15 | MOCK_CONST_METHOD0(value_cref, const instance_value_variant&()); 16 | MOCK_METHOD1(assign, void(instance_value_variant)); 17 | MOCK_METHOD1(assign, void(std::unique_ptr)); 18 | MOCK_METHOD2(assign_member, void(unsigned, std::unique_ptr)); 19 | MOCK_METHOD1(find_member, instance*(unsigned)); 20 | MOCK_CONST_METHOD1(find_cmember, const instance*(unsigned)); 21 | MOCK_CONST_METHOD1( 22 | find_function, sema::single_scope_function_lookup_result_t(lexer::token)); 23 | MOCK_CONST_METHOD0(type, const sema::sema_type&()); 24 | }; 25 | } -------------------------------------------------------------------------------- /test/exec/mock/instances_holder_mock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "exec/instance/instance.hpp" 4 | #include "exec/instance/instance_value_variant.hpp" 5 | #include "exec/instance/instances_holder_interface.hpp" 6 | 7 | #include 8 | 9 | namespace cmsl::exec::inst { 10 | class instance; 11 | 12 | namespace test { 13 | struct instances_holder_mock : public instances_holder_interface 14 | { 15 | MOCK_METHOD1(store, void(std::unique_ptr)); 16 | MOCK_METHOD1(gather_ownership, std::unique_ptr(inst::instance*)); 17 | MOCK_CONST_METHOD1(owns, bool(inst::instance*)); 18 | 19 | MOCK_METHOD1(create, instance*(instance_value_variant)); 20 | 21 | MOCK_METHOD1(create_reference, instance*(instance&)); 22 | MOCK_METHOD2(create_reference_to_base, 23 | instance*(instance&, const sema::sema_type&)); 24 | MOCK_METHOD1(create, instance*(const sema::sema_type&)); 25 | MOCK_METHOD2(create, 26 | instance*(const sema::sema_type&, instance_value_variant)); 27 | 28 | MOCK_METHOD0(create_void, instance*()); 29 | }; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test/exec/option_smoke_test.cpp: -------------------------------------------------------------------------------- 1 | #include "test/exec/smoke_test_fixture.hpp" 2 | 3 | #include 4 | 5 | namespace cmsl::exec::test { 6 | using ::testing::Eq; 7 | 8 | using OptionSmokeTest = ExecutionSmokeTest; 9 | 10 | TEST_F(OptionSmokeTest, ConstructorWithDescription) 11 | { 12 | const auto source = "int main()" 13 | "{" 14 | " auto foo = cmake::option(\"bar\", \"baz\");" 15 | " return int(foo.value() == false);" 16 | "}"; 17 | const auto result = m_executor->execute(source); 18 | EXPECT_THAT(result, Eq(1)); 19 | } 20 | 21 | TEST_F(OptionSmokeTest, ConstructorWithDescriptionAndValue) 22 | { 23 | const auto source = 24 | "int main()" 25 | "{" 26 | " auto foo = cmake::option(\"bar\", \"baz\", false);" 27 | " auto qux = cmake::option(\"top\", \"kek\", true);" 28 | " return int(foo.value() == false && qux.value() == true);" 29 | "}"; 30 | const auto result = m_executor->execute(source); 31 | EXPECT_THAT(result, Eq(1)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/exec/product_type_type_smoke_test.cpp: -------------------------------------------------------------------------------- 1 | #include "test/exec/smoke_test_fixture.hpp" 2 | 3 | #include 4 | 5 | namespace cmsl::exec::test { 6 | using ::testing::Eq; 7 | 8 | using ProductTypeTypeSmokeTest = ExecutionSmokeTest; 9 | 10 | TEST_F(ProductTypeTypeSmokeTest, DefaultConstructor) 11 | { 12 | const auto source = "int main()" 13 | "{" 14 | " decl::product_type pt;" 15 | " auto result = pt == decl::product_type::executable;" 16 | " return int(result);" 17 | "}"; 18 | const auto result = m_executor->execute(source); 19 | EXPECT_THAT(result, Eq(1)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/exec/smoke_test_fixture.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "errors/errors_observer.hpp" 4 | #include "exec/global_executor.hpp" 5 | #include "test/errors_observer_mock/errors_observer_mock.hpp" 6 | #include "test/mock/cmake_facade_mock.hpp" 7 | 8 | #include 9 | 10 | namespace cmsl::exec::test { 11 | class ExecutionSmokeTest : public ::testing::Test 12 | { 13 | protected: 14 | ::testing::NiceMock m_facade; 15 | 16 | void SetUp() override 17 | { 18 | m_errors_observer_mock = 19 | std::make_unique(); 20 | 21 | m_executor = std::make_unique( 22 | CMAKESL_EXEC_SMOKE_TEST_ROOT_DIR, m_facade, *m_errs); 23 | } 24 | 25 | void TearDown() override 26 | { 27 | m_executor.reset(); 28 | m_errors_observer_mock.reset(); 29 | } 30 | 31 | std::unique_ptr m_errors_observer_mock; 32 | std::unique_ptr m_errs; 33 | std::unique_ptr m_executor; 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /test/exec/ternary_operator_smoke_test.cpp: -------------------------------------------------------------------------------- 1 | #include "test/exec/smoke_test_fixture.hpp" 2 | 3 | #include 4 | 5 | namespace cmsl::exec::test { 6 | using ::testing::Eq; 7 | 8 | using TernaryOperatorSmokeTest = ExecutionSmokeTest; 9 | 10 | TEST_F(TernaryOperatorSmokeTest, TrueCondition) 11 | { 12 | const auto source = "int main()" 13 | "{" 14 | " return true ? 42 : 0;" 15 | "}"; 16 | const auto result = m_executor->execute(source); 17 | EXPECT_THAT(result, Eq(42)); 18 | } 19 | 20 | TEST_F(TernaryOperatorSmokeTest, FalseCondition) 21 | { 22 | const auto source = "int main()" 23 | "{" 24 | " return false ? 0 : 42;" 25 | "}"; 26 | const auto result = m_executor->execute(source); 27 | EXPECT_THAT(result, Eq(42)); 28 | } 29 | 30 | TEST_F(TernaryOperatorSmokeTest, ReturnsReferences) 31 | { 32 | const auto source = "int main()" 33 | "{" 34 | " int foo;" 35 | " int bar;" 36 | " int& baz = true ? foo : bar;" 37 | " baz = 42;" 38 | " return foo;" 39 | "}"; 40 | const auto result = m_executor->execute(source); 41 | EXPECT_THAT(result, Eq(42)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /test/exec/variable_type_deduction.cpp: -------------------------------------------------------------------------------- 1 | #include "test/exec/smoke_test_fixture.hpp" 2 | 3 | #include 4 | 5 | namespace cmsl::exec::test { 6 | using ::testing::Eq; 7 | 8 | using VariableTypeDeductionTest = ExecutionSmokeTest; 9 | 10 | TEST_F(VariableTypeDeductionTest, InitByCopy) 11 | { 12 | const auto source = "int main()" 13 | "{" 14 | " auto foo = 42;" 15 | " return foo;" 16 | "}"; 17 | const auto result = m_executor->execute(source); 18 | EXPECT_THAT(result, Eq(42)); 19 | } 20 | 21 | TEST_F(VariableTypeDeductionTest, InitReference) 22 | { 23 | const auto source = "int main()" 24 | "{" 25 | " auto foo = 24;" 26 | " auto& bar = foo;" 27 | " bar = 42;" 28 | " return int(foo == 42 && bar == 42);" 29 | "}"; 30 | const auto result = m_executor->execute(source); 31 | EXPECT_THAT(result, Eq(1)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/exec/void_type_smoke_test.cpp: -------------------------------------------------------------------------------- 1 | #include "test/exec/smoke_test_fixture.hpp" 2 | 3 | #include 4 | 5 | namespace cmsl::exec::test { 6 | using ::testing::Eq; 7 | using VoidTypeSmokeTest = ExecutionSmokeTest; 8 | 9 | TEST_F(VoidTypeSmokeTest, EmptyVoidFunction) 10 | { 11 | const auto source = "void foo()" 12 | "{}" 13 | "" 14 | "int main()" 15 | "{" 16 | " foo();" 17 | " return 42;" 18 | "}"; 19 | const auto result = m_executor->execute(source); 20 | EXPECT_THAT(result, Eq(42)); 21 | } 22 | 23 | TEST_F(VoidTypeSmokeTest, FunctionReturningVoid) 24 | { 25 | const auto source = "void foo(int& i)" 26 | "{" 27 | " i = 42;" 28 | "}" 29 | "" 30 | "int main()" 31 | "{" 32 | " int i;" 33 | " foo( i );" 34 | " return i;" 35 | "}"; 36 | const auto result = m_executor->execute(source); 37 | EXPECT_THAT(result, Eq(42)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test/exec/while_loop_smoke_test.cpp: -------------------------------------------------------------------------------- 1 | #include "test/exec/smoke_test_fixture.hpp" 2 | 3 | #include 4 | 5 | namespace cmsl::exec::test { 6 | using ::testing::Eq; 7 | using WhileLoopSmokeTest = ExecutionSmokeTest; 8 | 9 | TEST_F(WhileLoopSmokeTest, SimpleWhileLoop) 10 | { 11 | const auto source = "int main()" 12 | "{" 13 | " auto counter = 0;" 14 | " while(counter < 42)" 15 | " {" 16 | " counter += 1;" 17 | " }" 18 | " return counter;" 19 | "}"; 20 | const auto result = m_executor->execute(source); 21 | EXPECT_THAT(result, Eq(42)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/integration_tests/run_integration_tests.py: -------------------------------------------------------------------------------- 1 | from build_cmake_with_cmakesl_support import * 2 | from build_cmakesl_using_cmakesl import * 3 | 4 | build_cmake_with_cmakesl_support() 5 | build_cmakesl_using_cmakesl() 6 | -------------------------------------------------------------------------------- /test/lexer/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | import "cmake/cmsl_directories.cmsl"; 2 | import "cmake/test_utils.cmsl"; 3 | 4 | void main(cmake::project p) 5 | { 6 | cmsl::test::add_test( 7 | p, 8 | { .name = "lexer", 9 | .sources = { "lexer_test.cpp" }, 10 | .include_dirs = { cmsl::source_dir, cmsl::facade_dir }, 11 | .libraries = { "lexer", "errors" } }); 12 | } 13 | -------------------------------------------------------------------------------- /test/lexer/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | import "cmake/test_utils.dcmsl"; 2 | 3 | cmsl_test_executable { 4 | name = "lexer" 5 | 6 | files.public = [ 7 | "lexer_test.cpp" 8 | ] 9 | 10 | include_dirs.public = [ 11 | cmake_variables.CMAKESL_SOURCES_DIR.as_string, 12 | cmake_variables.CMAKESL_FACADE_DIR.as_string 13 | ] 14 | 15 | dependencies.public += [ 16 | "lexer", 17 | "errors" 18 | ] 19 | 20 | } 21 | -------------------------------------------------------------------------------- /test/lexer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKESL_DIR}/cmake/cmsl_cmake_utils.cmake) 2 | 3 | cmsl_add_test( 4 | NAME 5 | lexer 6 | SOURCES 7 | lexer_test.cpp 8 | INCLUDE_DIRS 9 | ${CMAKESL_SOURCES_DIR} 10 | ${CMAKESL_FACADE_SOURCES_DIR} 11 | LIBRARIES 12 | lexer 13 | errors 14 | ) 15 | 16 | -------------------------------------------------------------------------------- /test/lexer_error/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | import "cmake/cmsl_directories.cmsl"; 2 | import "cmake/test_utils.cmsl"; 3 | 4 | void main(cmake::project p) 5 | { 6 | cmsl::test::add_test( 7 | p, 8 | { .name = "lexer_error", 9 | .sources = { "lexer_error_test.cpp" }, 10 | .include_dirs = { cmsl::source_dir, cmsl::facade_dir, cmsl::test_dir }, 11 | .libraries = { "lexer", "errors_observer_mock" } }); 12 | } 13 | -------------------------------------------------------------------------------- /test/lexer_error/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | import "cmake/test_utils.dcmsl"; 2 | 3 | cmsl_test_executable { 4 | name = "lexer_error" 5 | 6 | files.public = [ 7 | "lexer_error_test.cpp" 8 | ] 9 | 10 | include_dirs.public = [ 11 | cmake_variables.CMAKESL_SOURCES_DIR.as_string, 12 | cmake_variables.CMAKESL_FACADE_DIR.as_string, 13 | cmake_variables.CMAKESL_TESTS_DIR.as_string 14 | ] 15 | 16 | dependencies.public += [ 17 | "lexer", 18 | "errors_observer_mock" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /test/lexer_error/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKESL_DIR}/cmake/cmsl_cmake_utils.cmake) 2 | 3 | cmsl_add_test( 4 | NAME 5 | lexer_error 6 | SOURCES 7 | lexer_error_test.cpp 8 | INCLUDE_DIRS 9 | ${CMAKESL_SOURCES_DIR} 10 | ${CMAKESL_TESTS_DIR} 11 | ${CMAKESL_FACADE_SOURCES_DIR} 12 | LIBRARIES 13 | lexer 14 | errors_observer_mock 15 | ) 16 | -------------------------------------------------------------------------------- /test/mock/strings_container_mock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/strings_container.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::test { 8 | class strings_container_mock : public strings_container 9 | { 10 | public: 11 | MOCK_METHOD1(store, cmsl::string_view(std::string)); 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /test/sema/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | import "cmake/cmsl_directories.cmsl"; 2 | import "cmake/test_utils.cmsl"; 3 | 4 | void main(cmake::project p) 5 | { 6 | auto sources = { "mock/add_subdirectory_semantic_handler_mock.hpp", 7 | "mock/enum_values_context_mock.hpp", 8 | "mock/expression_node_mock.hpp", 9 | "mock/identifiers_context_mock.hpp", 10 | "mock/import_handler_mock.hpp", 11 | "mock/sema_context_mock.hpp", 12 | "mock/sema_function_mock.hpp", 13 | "identifiers_context_test.cpp", 14 | "overload_resolution_test.cpp", 15 | "sema_builder_ast_visitor_test.cpp", 16 | "sema_dumper_smoke_test.cpp", 17 | "vatiable_initialization_check_test.cpp" }; 18 | 19 | auto include_dirs = { cmsl::source_dir, cmsl::facade_dir, cmsl::test_dir, 20 | cmsl::root_dir }; 21 | auto libs = { "lexer", "ast", "sema", "errors_observer_mock", 22 | "tests_common" }; 23 | 24 | cmsl::test::add_test(p, 25 | { .name = "sema", 26 | .sources = sources, 27 | .include_dirs = include_dirs, 28 | .libraries = libs }); 29 | } 30 | -------------------------------------------------------------------------------- /test/sema/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | import "cmake/test_utils.dcmsl"; 2 | 3 | cmsl_test_executable { 4 | name = "sema" 5 | 6 | include_dirs.public = [ 7 | cmake_variables.CMAKESL_SOURCES_DIR.as_string, 8 | cmake_variables.CMAKESL_FACADE_DIR.as_string, 9 | cmake_variables.CMAKESL_TESTS_DIR.as_string, 10 | cmake_variables.CMAKESL_DIR.as_string 11 | ] 12 | 13 | dependencies.public += [ 14 | "lexer", 15 | "ast", 16 | "sema", 17 | "errors_observer_mock", 18 | "tests_common" 19 | ] 20 | 21 | files.public = [ 22 | "identifiers_context_test.cpp", 23 | "mock/add_declarative_file_semantic_handler_mock.hpp", 24 | "mock/add_subdirectory_semantic_handler_mock.hpp", 25 | "mock/enum_values_context_mock.hpp", 26 | "mock/expression_node_mock.hpp", 27 | "mock/identifiers_context_mock.hpp", 28 | "mock/import_handler_mock.hpp", 29 | "mock/sema_context_mock.hpp", 30 | "mock/sema_function_mock.hpp", 31 | "overload_resolution_test.cpp", 32 | "sema_builder_ast_visitor_test.cpp", 33 | "sema_dumper_smoke_test.cpp", 34 | "variable_initialization_check_test.cpp" 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /test/sema/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKESL_DIR}/cmake/cmsl_cmake_utils.cmake) 2 | 3 | cmsl_add_test( 4 | NAME 5 | sema 6 | SOURCES 7 | identifiers_context_test.cpp 8 | mock/add_declarative_file_semantic_handler_mock.hpp 9 | mock/add_subdirectory_semantic_handler_mock.hpp 10 | mock/enum_values_context_mock.hpp 11 | mock/expression_node_mock.hpp 12 | mock/identifiers_context_mock.hpp 13 | mock/import_handler_mock.hpp 14 | mock/sema_context_mock.hpp 15 | mock/sema_function_mock.hpp 16 | overload_resolution_test.cpp 17 | sema_builder_ast_visitor_test.cpp 18 | sema_dumper_smoke_test.cpp 19 | variable_initialization_check_test.cpp 20 | INCLUDE_DIRS 21 | ${CMAKESL_SOURCES_DIR} 22 | ${CMAKESL_FACADE_SOURCES_DIR} 23 | ${CMAKESL_TESTS_DIR} 24 | ${CMAKESL_DIR} 25 | LIBRARIES 26 | lexer 27 | ast 28 | sema 29 | errors_observer_mock 30 | tests_common 31 | ) 32 | -------------------------------------------------------------------------------- /test/sema/mock/add_declarative_file_semantic_handler_mock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sema/add_declarative_file_semantic_handler.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::sema::test { 8 | class add_declarative_file_semantic_handler_mock 9 | : public add_declarative_file_semantic_handler 10 | { 11 | public: 12 | MOCK_METHOD1(handle_add_declarative_file, 13 | add_declarative_file_result_t(cmsl::string_view)); 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /test/sema/mock/add_subdirectory_semantic_handler_mock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sema/add_subdirectory_semantic_handler.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::sema::test { 8 | class add_subdirectory_semantic_handler_mock : public add_subdirectory_semantic_handler 9 | { 10 | public: 11 | MOCK_METHOD2(handle_add_subdirectory, 12 | add_subdirectory_result_t( 13 | cmsl::string_view, 14 | const std::vector>&)); 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /test/sema/mock/enum_values_context_mock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sema/enum_values_context.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::sema::test { 8 | class enum_values_context_mock : public enum_values_context 9 | { 10 | public: 11 | MOCK_METHOD3(register_identifier, void(lexer::token, enum_value_info, bool)); 12 | MOCK_CONST_METHOD1(info_of, 13 | std::optional(const qualified_names_t&)); 14 | MOCK_METHOD2(enter_global_ctx, void(token_t, bool)); 15 | MOCK_METHOD0(leave_ctx, void()); 16 | MOCK_CONST_METHOD0(clone, std::unique_ptr()); 17 | MOCK_CONST_METHOD0(collect_exported_stuff, 18 | std::unique_ptr()); 19 | MOCK_METHOD2(merge_imported_stuff, 20 | bool(const enum_values_context& imported, 21 | errors::errors_observer& errs)); 22 | 23 | MOCK_CONST_METHOD1(dump, void(qualified_contexts_dumper&)); 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /test/sema/mock/expression_node_mock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sema/sema_nodes.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::sema::test { 8 | class expression_node_mock : public expression_node 9 | { 10 | public: 11 | explicit expression_node_mock(const ast::ast_node& ast_node) 12 | : expression_node{ ast_node } 13 | { 14 | } 15 | 16 | MOCK_CONST_METHOD0(type, const sema_type&()); 17 | MOCK_CONST_METHOD0(produces_temporary_value, bool()); 18 | MOCK_CONST_METHOD1(visit, void(sema_node_visitor&)); 19 | MOCK_CONST_METHOD0(begin_location, source_location()); 20 | MOCK_CONST_METHOD0(end_location, source_location()); 21 | MOCK_CONST_METHOD0(ast_node, const ast::ast_node&()); 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /test/sema/mock/functions_context_mock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sema/functions_context.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::sema::test { 8 | class functions_context_mock : public functions_context 9 | { 10 | public: 11 | MOCK_METHOD3(register_function, 12 | void(const lexer::token&, const sema_function&, bool)); 13 | 14 | MOCK_CONST_METHOD1( 15 | find, 16 | function_lookup_result_t(const std::vector&)); 17 | 18 | MOCK_CONST_METHOD1( 19 | find_in_current_scope, 20 | const sema_function*(const function_signature& signature)); 21 | 22 | MOCK_METHOD2(enter_global_ctx, void(const lexer::token&, bool)); 23 | MOCK_METHOD0(leave_ctx, void()); 24 | MOCK_CONST_METHOD0(clone, std::unique_ptr()); 25 | MOCK_CONST_METHOD0(collect_exported_stuff, 26 | std::unique_ptr()); 27 | MOCK_METHOD2(merge_imported_stuff, 28 | bool(const functions_context& imported, 29 | errors::errors_observer& errs)); 30 | 31 | MOCK_CONST_METHOD1(dump, void(qualified_contexts_dumper&)); 32 | }; 33 | } -------------------------------------------------------------------------------- /test/sema/mock/identifiers_context_mock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sema/identifiers_context.hpp" 4 | #include "sema/qualified_contexts_dumper.hpp" 5 | 6 | #include 7 | 8 | namespace cmsl::sema::test { 9 | class identifiers_context_mock : public identifiers_context 10 | { 11 | public: 12 | MOCK_METHOD3(register_identifier, void(lexer::token, identifier_info, bool)); 13 | MOCK_CONST_METHOD1( 14 | info_of, std::optional(const qualified_names_t& names)); 15 | MOCK_METHOD2(enter_global_ctx, void(token_t, bool)); 16 | MOCK_METHOD0(enter_local_ctx, void()); 17 | MOCK_METHOD0(leave_ctx, void()); 18 | MOCK_CONST_METHOD0(is_in_global_ctx, bool()); 19 | 20 | MOCK_CONST_METHOD0(clone, std::unique_ptr()); 21 | MOCK_CONST_METHOD0(collect_exported_stuff, 22 | std::unique_ptr()); 23 | MOCK_METHOD2(merge_imported_stuff, 24 | bool(const identifiers_context& imported, 25 | errors::errors_observer& errs)); 26 | 27 | MOCK_CONST_METHOD1(dump, void(qualified_contexts_dumper&)); 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /test/sema/mock/import_handler_mock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sema/import_handler.hpp" 4 | #include "sema/qualified_contextes.hpp" 5 | 6 | #include 7 | 8 | namespace cmsl::sema::test { 9 | class import_handler_mock : public import_handler 10 | { 11 | public: 12 | MOCK_METHOD1(handle_import, 13 | std::unique_ptr(cmsl::string_view)); 14 | }; 15 | } -------------------------------------------------------------------------------- /test/sema/mock/sema_function_mock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sema/sema_function.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::sema::test { 8 | class sema_function_mock : public sema_function 9 | { 10 | public: 11 | MOCK_CONST_METHOD0(body, const block_node&()); 12 | MOCK_CONST_METHOD0(signature, const function_signature&()); 13 | MOCK_CONST_METHOD0(return_type, const sema_type&()); 14 | MOCK_CONST_METHOD0(try_return_type, const sema_type*()); 15 | MOCK_CONST_METHOD0(context, const sema_context&()); 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /test/sema/mock/types_context_mock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sema/types_context.hpp" 4 | 5 | #include 6 | 7 | namespace cmsl::sema::test { 8 | class types_context_mock : public types_context 9 | { 10 | public: 11 | MOCK_METHOD3(register_type, 12 | void(const lexer::token&, const sema_type&, bool)); 13 | 14 | MOCK_CONST_METHOD1(find, 15 | std::optional( 16 | const std::vector&)); 17 | 18 | MOCK_CONST_METHOD1(find_generic, 19 | const sema_type*(const ast::type_representation&)); 20 | 21 | MOCK_CONST_METHOD1(find_in_current_scope, 22 | const sema_type*(const lexer::token& name)); 23 | 24 | MOCK_METHOD2(enter_global_ctx, void(const lexer::token&, bool)); 25 | MOCK_METHOD0(leave_ctx, void()); 26 | MOCK_CONST_METHOD0(clone, std::unique_ptr()); 27 | MOCK_CONST_METHOD0(collect_exported_stuff, std::unique_ptr()); 28 | MOCK_METHOD2(merge_imported_stuff, 29 | bool(const types_context& imported, 30 | errors::errors_observer& errs)); 31 | 32 | MOCK_CONST_METHOD1(dump, void(qualified_contexts_dumper&)); 33 | }; 34 | } -------------------------------------------------------------------------------- /test/sema/sema_dumper_smoke_test.cpp: -------------------------------------------------------------------------------- 1 | #include "sema/dumper.hpp" 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace cmsl::sema::test { 8 | 9 | TEST(SemaDumper, ImplementsAllPureVirtualMethods) 10 | { 11 | std::ostringstream oss; 12 | dumper d{ oss }; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/source_location_manipulator/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | import "cmake/cmsl_directories.cmsl"; 2 | import "cmake/test_utils.cmsl"; 3 | 4 | void main(cmake::project p) 5 | { 6 | cmsl::test::add_test( 7 | p, 8 | { .name = "source_location_manipulator", 9 | .sources = { "source_location_test.cpp" }, 10 | .include_dirs = { cmsl::source_dir, cmsl::facade_dir }, 11 | .libraries = { "lexer" } }); 12 | } 13 | -------------------------------------------------------------------------------- /test/source_location_manipulator/CMakeLists.dcmsl: -------------------------------------------------------------------------------- 1 | import "cmake/test_utils.dcmsl"; 2 | 3 | cmsl_test_executable { 4 | name = "source_location_manipulator" 5 | 6 | include_dirs.public = [ 7 | cmake_variables.CMAKESL_SOURCES_DIR.as_string, 8 | cmake_variables.CMAKESL_FACADE_DIR.as_string 9 | ] 10 | 11 | dependencies.public += [ 12 | "lexer" 13 | ] 14 | 15 | files.public = [ 16 | "source_location_test.cpp" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /test/source_location_manipulator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKESL_DIR}/cmake/cmsl_cmake_utils.cmake) 2 | 3 | cmsl_add_test( 4 | NAME 5 | source_location_manipulator 6 | SOURCES 7 | source_location_test.cpp 8 | INCLUDE_DIRS 9 | ${CMAKESL_SOURCES_DIR} 10 | ${CMAKESL_FACADE_SOURCES_DIR} 11 | LIBRARIES 12 | lexer 13 | ) 14 | -------------------------------------------------------------------------------- /test/tools/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | void main(cmake::project& p) 2 | { 3 | add_subdirectory("smoke", p); 4 | } 5 | -------------------------------------------------------------------------------- /test/tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(smoke) 2 | 3 | -------------------------------------------------------------------------------- /test/tools/smoke/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(complete) 2 | add_subdirectory(index) 3 | -------------------------------------------------------------------------------- /test/tools/smoke/complete/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKESL_DIR}/cmake/cmsl_cmake_utils.cmake) 2 | 3 | cmsl_add_test( 4 | NAME 5 | complete_smoke 6 | SOURCES 7 | complete_test.cpp 8 | INCLUDE_DIRS 9 | ${CMAKESL_SOURCES_DIR} 10 | ${CMAKESL_FACADE_SOURCES_DIR} 11 | ${CMAKESL_TESTS_DIR} 12 | ${CMAKESL_DIR} 13 | LIBRARIES 14 | lexer 15 | ast 16 | sema 17 | errors_observer_mock 18 | cmsl_tools 19 | tests_common 20 | ) 21 | -------------------------------------------------------------------------------- /test/tools/smoke/index/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKESL_DIR}/cmake/cmsl_cmake_utils.cmake) 2 | 3 | cmsl_add_test( 4 | NAME 5 | indexer_smoke 6 | SOURCES 7 | indexer_test.cpp 8 | INCLUDE_DIRS 9 | ${CMAKESL_SOURCES_DIR} 10 | ${CMAKESL_FACADE_SOURCES_DIR} 11 | ${CMAKESL_TESTS_DIR} 12 | ${CMAKESL_DIR} 13 | LIBRARIES 14 | lexer 15 | ast 16 | sema 17 | errors_observer_mock 18 | cmsl_tools 19 | tests_common 20 | ) 21 | -------------------------------------------------------------------------------- /tools/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | void main(cmake::project& p) 2 | { 3 | add_subdirectory("lib", p); 4 | add_subdirectory("cmakesl", p); 5 | } 6 | -------------------------------------------------------------------------------- /tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(lib) 2 | add_subdirectory(cmakesl) 3 | -------------------------------------------------------------------------------- /tools/cmakesl/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | import "cmake/cmsl_directories.cmsl"; 2 | 3 | void main(cmake::project& p) 4 | { 5 | auto sources = { "main.cpp" }; 6 | auto exe = p.add_executable("cmakesl", sources); 7 | exe.include_directories({ cmsl::source_dir, cmsl::facade_dir }); 8 | 9 | exe.link_to(p.find_library("exec")); 10 | exe.link_to(p.find_library("sema")); 11 | exe.link_to(p.find_library("errors")); 12 | 13 | cmake::install(exe); 14 | } 15 | -------------------------------------------------------------------------------- /tools/cmakesl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CMSL_EXECUTABLE_SOURCES 2 | main.cpp 3 | ) 4 | 5 | add_executable(cmakesl ${CMSL_EXECUTABLE_SOURCES}) 6 | 7 | target_include_directories(cmakesl 8 | PRIVATE 9 | ${CMAKESL_SOURCES_DIR} 10 | ${CMAKESL_FACADE_DIR} 11 | ) 12 | 13 | target_link_libraries(cmakesl 14 | PRIVATE 15 | exec 16 | sema 17 | errors 18 | ) 19 | 20 | target_compile_options(cmakesl 21 | PRIVATE 22 | ${CMAKESL_ADDITIONAL_COMPILER_FLAGS} 23 | ) 24 | 25 | install(TARGETS cmakesl DESTINATION bin) 26 | -------------------------------------------------------------------------------- /tools/lib/CMakeLists.cmsl: -------------------------------------------------------------------------------- 1 | import "cmake/cmsl_directories.cmsl"; 2 | 3 | void main(cmake::project& p) 4 | { 5 | auto sources = { "cmsl_complete.cpp", 6 | "cmsl_complete.hpp", 7 | "cmsl_index.cpp", 8 | "cmsl_index.hpp", 9 | "cmsl_parse_source.cpp", 10 | "cmsl_parse_source.hpp", 11 | "cmsl_parsed_source.cpp", 12 | "cmsl_parsed_source.hpp", 13 | "completer.cpp", 14 | "completer.hpp", 15 | "completion_context_finder.cpp", 16 | "completion_context_finder.hpp", 17 | "completion_contextes_visitor.cpp", 18 | "completion_contextes_visitor.hpp", 19 | "identifier_names_collector.cpp", 20 | "identifier_names_collector.hpp", 21 | "indexing_visitor.cpp", 22 | "indexing_visitor.hpp", 23 | "type_names_collector.cpp", 24 | "type_names_collector.hpp" }; 25 | auto exe = p.add_library("cmsl_tools", sources); 26 | exe.include_directories({ cmsl::source_dir, cmsl::facade_dir }); 27 | 28 | exe.link_to(p.find_library("sema")); 29 | exe.link_to(p.find_library("errors")); 30 | } 31 | -------------------------------------------------------------------------------- /tools/lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CMSL_TOOLS_SOURCES 2 | cmsl_complete.cpp 3 | cmsl_complete.hpp 4 | cmsl_index.cpp 5 | cmsl_index.hpp 6 | cmsl_parse_source.cpp 7 | cmsl_parse_source.hpp 8 | cmsl_parsed_source.cpp 9 | cmsl_parsed_source.hpp 10 | completer.cpp 11 | completer.hpp 12 | completion_context_finder.cpp 13 | completion_context_finder.hpp 14 | completion_contextes_visitor.cpp 15 | completion_contextes_visitor.hpp 16 | identifier_names_collector.cpp 17 | identifier_names_collector.hpp 18 | indexing_visitor.cpp 19 | indexing_visitor.hpp 20 | type_names_collector.cpp 21 | type_names_collector.hpp 22 | ) 23 | 24 | add_library(cmsl_tools ${CMSL_TOOLS_SOURCES}) 25 | 26 | target_include_directories(cmsl_tools 27 | PRIVATE 28 | ${CMAKESL_SOURCES_DIR} 29 | ${CMAKESL_FACADE_DIR} 30 | ) 31 | 32 | target_link_libraries(cmsl_tools 33 | PRIVATE 34 | sema 35 | errors 36 | ) 37 | 38 | target_compile_options(cmsl_tools 39 | PRIVATE 40 | ${CMAKESL_ADDITIONAL_COMPILER_FLAGS} 41 | ) 42 | -------------------------------------------------------------------------------- /tools/lib/cmsl_complete.cpp: -------------------------------------------------------------------------------- 1 | #include "cmsl_complete.hpp" 2 | #include "cmsl_parsed_source.hpp" 3 | #include "completer.hpp" 4 | 5 | cmsl_complete_results* cmsl_complete_at( 6 | const cmsl_parsed_source* parsed_source, unsigned absolute_position) 7 | { 8 | return cmsl::tools::completer{ *parsed_source, absolute_position } 9 | .complete(); 10 | } 11 | 12 | void cmsl_destroy_complete_results(cmsl_complete_results* complete_results) 13 | { 14 | for (auto i = 0u; i < complete_results->num_results; ++i) { 15 | delete[] complete_results->results[i]; 16 | } 17 | 18 | delete[] complete_results->results; 19 | delete complete_results; 20 | } 21 | -------------------------------------------------------------------------------- /tools/lib/cmsl_complete.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "cmsl_parse_source.hpp" 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | struct cmsl_complete_results 9 | { 10 | char** results; 11 | unsigned num_results; 12 | }; 13 | 14 | struct cmsl_complete_results* cmsl_complete_at( 15 | const struct cmsl_parsed_source* parsed_source, unsigned absolute_position); 16 | void cmsl_destroy_complete_results( 17 | struct cmsl_complete_results* complete_results); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | -------------------------------------------------------------------------------- /tools/lib/cmsl_index.cpp: -------------------------------------------------------------------------------- 1 | #include "cmsl_index.hpp" 2 | 3 | #include "cmsl_parsed_source.hpp" 4 | #include "indexing_visitor.hpp" 5 | 6 | #include 7 | #include 8 | 9 | struct cmsl_index_entries* cmsl_index( 10 | const struct cmsl_parsed_source* parsed_source) 11 | { 12 | if (!parsed_source || !parsed_source->ast_tree || 13 | !parsed_source->sema_tree) { 14 | return nullptr; 15 | } 16 | 17 | cmsl::tools::indexer indexer; 18 | parsed_source->sema_tree->visit(indexer); 19 | const auto& result = indexer.result(); 20 | 21 | auto index_entries = new cmsl_index_entries; 22 | 23 | index_entries->num_entries = result.size(); 24 | 25 | index_entries->entries = new cmsl_index_entry[result.size()]; 26 | 27 | for (auto i = 0u; i < result.size(); ++i) { 28 | index_entries->entries[i] = result[i]; 29 | } 30 | 31 | return index_entries; 32 | } 33 | 34 | void cmsl_destroy_index_entries(struct cmsl_index_entries* index_entries) 35 | { 36 | for (auto i = 0u; i < index_entries->num_entries; ++i) { 37 | delete[] index_entries->entries[i].source_path; 38 | } 39 | 40 | delete[] index_entries->entries; 41 | delete index_entries; 42 | } 43 | -------------------------------------------------------------------------------- /tools/lib/cmsl_index.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CMSL_INDEX_HPP 2 | #define CMSL_INDEX_HPP 3 | 4 | #include "cmsl_parse_source.hpp" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | enum cmsl_index_entry_type 10 | { 11 | type, 12 | identifier, 13 | parameter_declaration_identifier, 14 | class_member_identifier, 15 | operator_function, 16 | function_call_name, 17 | namespace_, 18 | enum_value, 19 | file, 20 | add_subdirectory 21 | }; 22 | 23 | struct cmsl_index_entry 24 | { 25 | unsigned begin_pos; 26 | unsigned end_pos; 27 | enum cmsl_index_entry_type type; 28 | char* source_path; 29 | unsigned position; 30 | }; 31 | 32 | struct cmsl_index_entries 33 | { 34 | struct cmsl_index_entry* entries; 35 | unsigned num_entries; 36 | }; 37 | 38 | struct cmsl_index_entries* cmsl_index( 39 | const struct cmsl_parsed_source* parsed_source); 40 | void cmsl_destroy_index_entries(struct cmsl_index_entries* index_entries); 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | 46 | #endif // CMSL_INDEX_HPP 47 | -------------------------------------------------------------------------------- /tools/lib/cmsl_parse_source.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CMSL_PARSE_SOURCE_HPP 2 | #define CMSL_PARSE_SOURCE_HPP 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | struct cmsl_parsed_source; 9 | 10 | struct cmsl_parsed_source* cmsl_parse_source( 11 | const char* source, const char* builtin_types_documentation_path); 12 | void cmsl_destroy_parsed_source(struct cmsl_parsed_source* parsed_source); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif // CMSL_PARSE_SOURCE_HPP 19 | -------------------------------------------------------------------------------- /tools/lib/cmsl_parsed_source.cpp: -------------------------------------------------------------------------------- 1 | #include "cmsl_parsed_source.hpp" 2 | 3 | #include "ast/ast_node.hpp" 4 | #include "common/strings_container.hpp" 5 | #include "sema/add_declarative_file_semantic_handler.hpp" 6 | #include "sema/add_subdirectory_semantic_handler.hpp" 7 | #include "sema/builtin_token_provider.hpp" 8 | #include "sema/import_handler.hpp" 9 | #include "sema/sema_context.hpp" 10 | 11 | cmsl_parsed_source::~cmsl_parsed_source() 12 | { 13 | } 14 | -------------------------------------------------------------------------------- /tools/lib/cmsl_parsed_source.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sema/builtin_types_accessor.hpp" 4 | #include "sema/import_handler.hpp" 5 | #include "sema/sema_node.hpp" 6 | #include "sema/sema_tree_building_context.hpp" 7 | 8 | #include 9 | #include 10 | 11 | namespace cmsl { 12 | class strings_container; 13 | 14 | namespace sema { 15 | class add_declarative_file_semantic_handler; 16 | class add_subdirectory_semantic_handler; 17 | class builtin_token_provider; 18 | } 19 | } 20 | 21 | struct cmsl_parsed_source 22 | { 23 | ~cmsl_parsed_source(); 24 | 25 | std::string source; 26 | std::unique_ptr builtin_token_provider; 27 | cmsl::sema::sema_tree_building_context context; 28 | std::unique_ptr 29 | add_subdirectory_handler; 30 | std::unique_ptr 31 | add_declarative_file_handler; 32 | std::unique_ptr imports_handler; 33 | std::unique_ptr ast_tree; 34 | std::unique_ptr sema_tree; 35 | std::unique_ptr builtin_context; 36 | std::unique_ptr strings_container; 37 | }; 38 | -------------------------------------------------------------------------------- /tools/lib/completer.cpp: -------------------------------------------------------------------------------- 1 | #include "completer.hpp" 2 | #include "cmsl_complete.hpp" 3 | #include "cmsl_parsed_source.hpp" 4 | #include "completion_context_finder.hpp" 5 | #include "completion_contextes_visitor.hpp" 6 | 7 | namespace cmsl::tools { 8 | completer::completer(const cmsl_parsed_source& parsed_source, 9 | unsigned absolute_position) 10 | : m_parsed_source{ parsed_source } 11 | , m_absolute_position{ absolute_position } 12 | { 13 | } 14 | 15 | cmsl_complete_results* completer::complete() 16 | { 17 | auto finder = completion_context_finder{ m_absolute_position }; 18 | m_parsed_source.sema_tree->visit(finder); 19 | const auto found_context = finder.result(); 20 | 21 | if (std::holds_alternative(found_context)) { 22 | return nullptr; 23 | } 24 | 25 | auto results = new cmsl_complete_results; 26 | auto visitor = completion_contextes_visitor{ m_parsed_source, *results }; 27 | std::visit(visitor, found_context); 28 | visitor.finalize(); 29 | 30 | return results; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tools/lib/completer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct cmsl_parsed_source; 4 | struct cmsl_complete_results; 5 | 6 | namespace cmsl::tools { 7 | class completer 8 | { 9 | public: 10 | explicit completer(const cmsl_parsed_source& parsed_source, 11 | unsigned absolute_position); 12 | 13 | cmsl_complete_results* complete(); 14 | 15 | private: 16 | const cmsl_parsed_source& m_parsed_source; 17 | unsigned m_absolute_position; 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /tools/lib/completion_context_finder.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/source_location.hpp" 4 | #include "completion_contextes.hpp" 5 | #include "sema/sema_node_visitor.hpp" 6 | 7 | #include 8 | 9 | namespace cmsl::tools { 10 | class completion_context_finder : public sema::empty_sema_node_visitor 11 | { 12 | public: 13 | explicit completion_context_finder(unsigned absolute_position); 14 | 15 | void visit(const sema::translation_unit_node& node) override; 16 | void visit(const sema::function_node& node) override; 17 | void visit(const sema::block_node& node) override; 18 | void visit(const sema::class_node& node) override; 19 | 20 | completion_context_t result() const; 21 | 22 | private: 23 | bool is_inside(const sema::sema_node& node) const; 24 | bool is_before(const sema::sema_node& node) const; 25 | bool is_pos_before_node_begin(const sema::sema_node& node) const; 26 | 27 | private: 28 | const source_location m_pos; 29 | completion_context_t m_result; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /tools/lib/completion_contextes.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace cmsl { 7 | namespace sema { 8 | class sema_node; 9 | class translation_unit_node; 10 | class class_node; 11 | } 12 | 13 | namespace tools { 14 | struct standalone_expression_context 15 | { 16 | std::reference_wrapper node; 17 | unsigned place; 18 | }; 19 | 20 | struct top_level_declaration_context 21 | { 22 | std::reference_wrapper node; 23 | unsigned place; 24 | }; 25 | 26 | struct class_member_declaration_context 27 | { 28 | std::reference_wrapper node; 29 | }; 30 | 31 | struct could_not_find_context 32 | { 33 | }; 34 | 35 | using completion_context_t = 36 | std::variant; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tools/lib/completion_contextes_visitor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "completion_contextes.hpp" 4 | 5 | struct cmsl_parsed_source; 6 | struct cmsl_complete_results; 7 | 8 | namespace cmsl::tools { 9 | struct standalone_expression_context; 10 | struct could_not_find_context; 11 | 12 | class completion_contextes_visitor 13 | { 14 | public: 15 | explicit completion_contextes_visitor( 16 | const cmsl_parsed_source& parsed_source, cmsl_complete_results& results); 17 | 18 | void operator()(const could_not_find_context&) {} 19 | void operator()(const standalone_expression_context& ctx); 20 | void operator()(const top_level_declaration_context& ctx); 21 | void operator()(const class_member_declaration_context& ctx); 22 | 23 | void finalize(); 24 | 25 | private: 26 | void add_standalone_expression_keywords(); 27 | void add_top_level_declaration_keywords(); 28 | 29 | template 30 | void add_results(Collection&& results); 31 | 32 | private: 33 | const cmsl_parsed_source& m_parsed_source; 34 | cmsl_complete_results& m_results; 35 | 36 | std::vector m_intermediate_results; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /tools/lib/identifier_names_collector.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace cmsl { 7 | namespace sema { 8 | class sema_node; 9 | class sema_context; 10 | } 11 | 12 | namespace tools { 13 | class identifier_names_collector 14 | { 15 | public: 16 | std::unordered_set collect( 17 | const sema::sema_node& start_node) const; 18 | }; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tools/lib/type_names_collector.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace cmsl { 7 | namespace sema { 8 | class sema_node; 9 | class sema_context; 10 | } 11 | 12 | namespace tools { 13 | class type_names_collector 14 | { 15 | public: 16 | std::unordered_set collect( 17 | const sema::sema_context& builtin_context, 18 | const sema::sema_node& start_node) const; 19 | }; 20 | } 21 | } 22 | --------------------------------------------------------------------------------