Add semantic passes
This commit is contained in:
		| @@ -5,24 +5,24 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS 1) | |||||||
| set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) | ||||||
| set(CMAKE_CXX_STANDARD 17) | set(CMAKE_CXX_STANDARD 17) | ||||||
|  |  | ||||||
| find_package(Boost CONFIG COMPONENTS process program_options REQUIRED) | # find_package(Boost CONFIG COMPONENTS process program_options REQUIRED) | ||||||
| find_package(FLEX REQUIRED) | find_package(FLEX REQUIRED) | ||||||
| find_package(BISON REQUIRED) | find_package(BISON REQUIRED) | ||||||
|  |  | ||||||
| include_directories(${Boost_INCLUDE_DIR}) | # include_directories(${Boost_INCLUDE_DIR}) | ||||||
|  |  | ||||||
| FLEX_TARGET(lexer source/lexer.ll ${CMAKE_CURRENT_BINARY_DIR}/lexer.cpp) | FLEX_TARGET(lexer source/lexer.ll ${CMAKE_CURRENT_BINARY_DIR}/lexer.cc) | ||||||
| BISON_TARGET(parser source/parser.yy ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp) | BISON_TARGET(parser source/parser.yy ${CMAKE_CURRENT_BINARY_DIR}/parser.cc) | ||||||
| add_flex_bison_dependency(lexer parser) | add_flex_bison_dependency(lexer parser) | ||||||
|  |  | ||||||
| add_executable(elna cli/main.cpp | add_executable(elna cli/main.cc | ||||||
| 	source/ast.cpp include/elna/source/ast.hpp | 	source/ast.cc include/elna/source/ast.h | ||||||
| 	source/types.cpp include/elna/source/types.hpp | 	source/types.cc include/elna/source/types.h | ||||||
| 	source/driver.cpp include/elna/source/driver.hpp | 	source/driver.cc include/elna/source/driver.h | ||||||
| 	source/symbol_table.cpp include/elna/source/symbol_table.hpp | 	source/symbol_table.cc include/elna/source/symbol_table.h | ||||||
| 	source/result.cpp include/elna/source/result.hpp | 	source/result.cc include/elna/source/result.h | ||||||
| 	source/semantic.cpp include/elna/source/semantic.hpp | 	source/semantic.cc include/elna/source/semantic.h | ||||||
| 	${BISON_parser_OUTPUTS} ${FLEX_lexer_OUTPUTS} | 	${BISON_parser_OUTPUTS} ${FLEX_lexer_OUTPUTS} | ||||||
| ) | ) | ||||||
| target_include_directories(elna PRIVATE ${CMAKE_CURRENT_BINARY_DIR} include) | target_include_directories(elna PRIVATE ${CMAKE_CURRENT_BINARY_DIR} include) | ||||||
| target_link_libraries(elna LINK_PUBLIC ${Boost_LIBRARIES}) | # target_link_libraries(elna LINK_PUBLIC ${Boost_LIBRARIES}) | ||||||
|   | |||||||
| @@ -1,21 +1,21 @@ | |||||||
| #include <elna/source/driver.hpp> | #include <elna/source/driver.h> | ||||||
| #include "parser.hpp" | #include "elna/source/semantic.h" | ||||||
|  | #include "parser.hh" | ||||||
| #include <sstream> | #include <sstream> | ||||||
| 
 | 
 | ||||||
|  | constexpr std::size_t pointer_size = 4; | ||||||
|  | 
 | ||||||
| int main() | int main() | ||||||
| { | { | ||||||
|     elna::source::driver driver{ "-" }; |     elna::source::driver driver{ "-" }; | ||||||
|     std::istringstream inp(R"( |     std::istringstream inp(R"( | ||||||
|         const world = 5, hello = 7; |         var x: Int; | ||||||
|         var x: int, y: boolean; |  | ||||||
| 
 | 
 | ||||||
|         proc f(); |         proc f(); | ||||||
|         begin |         begin | ||||||
|             x := 8 |  | ||||||
|         end; |         end; | ||||||
| 
 | 
 | ||||||
|         begin |         begin | ||||||
|             while false do inc(5) |  | ||||||
|         end. |         end. | ||||||
|     )"); |     )"); | ||||||
| 
 | 
 | ||||||
| @@ -33,6 +33,12 @@ int main() | |||||||
|         } |         } | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |     auto symbol_table = elna::source::add_builtin_symbols(); | ||||||
|  |     elna::source::name_analysis_visitor name_analysis_visitor{ symbol_table, "-", pointer_size }; | ||||||
|  |     elna::source::type_analysis_visitor type_analysis_visitor{ symbol_table, "-", pointer_size }; | ||||||
|  | 
 | ||||||
|  |     name_analysis_visitor.visit(driver.tree.get()); | ||||||
|  | 
 | ||||||
|     for (auto& definition : driver.tree->definitions()) |     for (auto& definition : driver.tree->definitions()) | ||||||
|     { |     { | ||||||
|         if (auto const_definition = dynamic_cast<elna::source::constant_definition *>(definition.get())) |         if (auto const_definition = dynamic_cast<elna::source::constant_definition *>(definition.get())) | ||||||
							
								
								
									
										99
									
								
								gcc/Make-lang.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								gcc/Make-lang.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | |||||||
|  | GCCELNA_INSTALL_NAME := $(shell echo gccelna|sed '$(program_transform_name)') | ||||||
|  | GCCELNA_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo gccelna|sed '$(program_transform_name)') | ||||||
|  |  | ||||||
|  | elna: elna1$(exeext) | ||||||
|  |  | ||||||
|  | .PHONY: elna | ||||||
|  |  | ||||||
|  | # Driver | ||||||
|  |  | ||||||
|  | GCCELNA_OBJS = \ | ||||||
|  |    $(GCC_OBJS) \ | ||||||
|  |    elna/elna-spec.o \ | ||||||
|  |    $(END) | ||||||
|  |  | ||||||
|  | gccelna$(exeext): $(GCCELNA_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS) | ||||||
|  | 	+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ | ||||||
|  | 	  $(GCCELNA_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \ | ||||||
|  | 	  $(EXTRA_GCC_LIBS) $(LIBS) | ||||||
|  |  | ||||||
|  | # The compiler proper | ||||||
|  |  | ||||||
|  | elna_OBJS = \ | ||||||
|  | 	elna/elna1.o \ | ||||||
|  | 	elna/generic-visitor.o \ | ||||||
|  | 	elna/ast.o \ | ||||||
|  | 	elna/driver.o \ | ||||||
|  | 	elna/lexer.o \ | ||||||
|  | 	elna/parser.o \ | ||||||
|  | 	elna/result.o \ | ||||||
|  | 	elna/semantic.o \ | ||||||
|  | 	elna/symbol_table.o \ | ||||||
|  | 	elna/types.o \ | ||||||
|  | 	$(END) | ||||||
|  |  | ||||||
|  | elna1$(exeext): attribs.o $(elna_OBJS) $(BACKEND) $(LIBDEPS) | ||||||
|  | 	+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ | ||||||
|  | 	      attribs.o $(elna_OBJS) $(BACKEND) $(LIBS) $(BACKENDLIBS) | ||||||
|  |  | ||||||
|  | elna.all.cross: | ||||||
|  |  | ||||||
|  | elna.start.encap: gccelna$(exeext) | ||||||
|  | elna.rest.encap: | ||||||
|  |  | ||||||
|  | # No elna-specific selftests. | ||||||
|  | selftest-elna: | ||||||
|  |  | ||||||
|  | elna.install-common: installdirs | ||||||
|  | 	-rm -f $(DESTDIR)$(bindir)/$(GCCELNA_INSTALL_NAME)$(exeext) | ||||||
|  | 	$(INSTALL_PROGRAM) gccelna$(exeext) $(DESTDIR)$(bindir)/$(GCCELNA_INSTALL_NAME)$(exeext) | ||||||
|  | 	rm -f $(DESTDIR)$(bindir)/$(GCCELNA_TARGET_INSTALL_NAME)$(exeext); \ | ||||||
|  | 	( cd $(DESTDIR)$(bindir) && \ | ||||||
|  |       $(LN) $(GCCELNA_INSTALL_NAME)$(exeext) $(GCCELNA_TARGET_INSTALL_NAME)$(exeext) ); \ | ||||||
|  |  | ||||||
|  | # Required goals, they still do nothing | ||||||
|  | elna.install-man: | ||||||
|  | elna.install-info: | ||||||
|  | elna.install-pdf: | ||||||
|  | elna.install-plugin: | ||||||
|  | elna.install-html: | ||||||
|  | elna.info: | ||||||
|  | elna.dvi: | ||||||
|  | elna.pdf: | ||||||
|  | elna.html: | ||||||
|  | elna.man: | ||||||
|  | elna.mostlyclean: | ||||||
|  | elna.clean: | ||||||
|  | elna.distclean: | ||||||
|  | elna.maintainer-clean: | ||||||
|  |  | ||||||
|  | # make uninstall | ||||||
|  | elna.uninstall: | ||||||
|  | 	-rm -f gccelna$(exeext) elna1$(exeext) | ||||||
|  | 	-rm -f $(elna_OBJS) | ||||||
|  |  | ||||||
|  | # Used for handling bootstrap | ||||||
|  | elna.stage1: stage1-start | ||||||
|  | 	-mv elna/*$(objext) stage1/elna | ||||||
|  | elna.stage2: stage2-start | ||||||
|  | 	-mv elna/*$(objext) stage2/elna | ||||||
|  | elna.stage3: stage3-start | ||||||
|  | 	-mv elna/*$(objext) stage3/elna | ||||||
|  | elna.stage4: stage4-start | ||||||
|  | 	-mv elna/*$(objext) stage4/elna | ||||||
|  | elna.stageprofile: stageprofile-start | ||||||
|  | 	-mv elna/*$(objext) stageprofile/elna | ||||||
|  | elna.stagefeedback: stagefeedback-start | ||||||
|  | 	-mv elna/*$(objext) stagefeedback/elna | ||||||
|  |  | ||||||
|  | ELNA_INCLUDES = -I $(srcdir)/elna -I $(srcdir)/elna/generated | ||||||
|  |  | ||||||
|  | CFLAGS-elna/elna1.o += $(ELNA_INCLUDES) | ||||||
|  |  | ||||||
|  | elna/%.o: elna/source/%.cc | ||||||
|  | 	$(COMPILE) $(ELNA_INCLUDES) $< | ||||||
|  | 	$(POSTCOMPILE) | ||||||
|  |  | ||||||
|  | elna/%.o: elna/generated/%.cc | ||||||
|  | 	$(COMPILE) $(ELNA_INCLUDES) $< | ||||||
|  | 	$(POSTCOMPILE) | ||||||
							
								
								
									
										13
									
								
								gcc/config-lang.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								gcc/config-lang.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | # gcc-src/gcc/config/config-lang.in | ||||||
|  | language="elna" | ||||||
|  |  | ||||||
|  | compilers="elna1\$(exeext)" | ||||||
|  |  | ||||||
|  | target_libs="" | ||||||
|  |  | ||||||
|  | gtfiles="\$(srcdir)/elna/elna1.cc" | ||||||
|  |  | ||||||
|  | lang_requires_boot_languages=c++ | ||||||
|  |  | ||||||
|  | # Do not build by default | ||||||
|  | build_by_default="no" | ||||||
							
								
								
									
										16
									
								
								gcc/elna-spec.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								gcc/elna-spec.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | void | ||||||
|  | lang_specific_driver (struct cl_decoded_option ** /* in_decoded_options */, | ||||||
|  | 		      unsigned int * /* in_decoded_options_count */, | ||||||
|  | 		      int * /*in_added_libraries */) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Called before linking.  Returns 0 on success and -1 on failure.  */ | ||||||
|  | int | ||||||
|  | lang_specific_pre_link (void) | ||||||
|  | { | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Number of extra output files that lang_specific_pre_link may generate.  */ | ||||||
|  | int lang_specific_extra_outfiles = 0; | ||||||
							
								
								
									
										252
									
								
								gcc/elna1.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										252
									
								
								gcc/elna1.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,252 @@ | |||||||
|  | #include "config.h" | ||||||
|  | #include "system.h" | ||||||
|  | #include "coretypes.h" | ||||||
|  | #include "target.h" | ||||||
|  | #include "tree.h" | ||||||
|  | #include "tree-iterator.h" | ||||||
|  | #include "gimple-expr.h" | ||||||
|  | #include "diagnostic.h" | ||||||
|  | #include "opts.h" | ||||||
|  | #include "fold-const.h" | ||||||
|  | #include "stor-layout.h" | ||||||
|  | #include "debug.h" | ||||||
|  | #include "convert.h" | ||||||
|  | #include "langhooks.h" | ||||||
|  | #include "langhooks-def.h" | ||||||
|  | #include "common/common-target.h" | ||||||
|  |  | ||||||
|  | #include <fstream> | ||||||
|  | #include <elna/source/driver.h> | ||||||
|  | #include "elna/source/semantic.h" | ||||||
|  | #include "elna/gcc/generic-visitor.h" | ||||||
|  | #include "parser.hh" | ||||||
|  |  | ||||||
|  | /* Language-dependent contents of a type.  */ | ||||||
|  |  | ||||||
|  | struct GTY (()) lang_type | ||||||
|  | { | ||||||
|  |   char dummy; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Language-dependent contents of a decl.  */ | ||||||
|  |  | ||||||
|  | struct GTY (()) lang_decl | ||||||
|  | { | ||||||
|  |   char dummy; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Language-dependent contents of an identifier.  This must include a | ||||||
|  |    tree_identifier.  */ | ||||||
|  |  | ||||||
|  | struct GTY (()) lang_identifier | ||||||
|  | { | ||||||
|  |   struct tree_identifier common; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* The resulting tree type.  */ | ||||||
|  |  | ||||||
|  | union GTY ((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), | ||||||
|  | 	    chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), " | ||||||
|  | 			"TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN " | ||||||
|  | 			"(&%h.generic)) : NULL"))) lang_tree_node | ||||||
|  | { | ||||||
|  |   union tree_node GTY ((tag ("0"), desc ("tree_node_structure (&%h)"))) generic; | ||||||
|  |   struct lang_identifier GTY ((tag ("1"))) identifier; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* We don't use language_function.  */ | ||||||
|  |  | ||||||
|  | struct GTY (()) language_function | ||||||
|  | { | ||||||
|  |   int dummy; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Creates an expression whose value is that of EXPR, converted to type TYPE. | ||||||
|  |    This function implements all reasonable scalar conversions.  */ | ||||||
|  |  | ||||||
|  | tree | ||||||
|  | convert (tree type, tree expr) | ||||||
|  | { | ||||||
|  |   return expr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Language hooks.  */ | ||||||
|  |  | ||||||
|  | static bool | ||||||
|  | elna_langhook_init (void) | ||||||
|  | { | ||||||
|  |   /* NOTE: Newer versions of GCC use only: | ||||||
|  |            build_common_tree_nodes (false); | ||||||
|  |      See Eugene's comment in the comments section. */ | ||||||
|  |   build_common_tree_nodes (false); | ||||||
|  |  | ||||||
|  |   /* I don't know why this has to be done explicitly.  */ | ||||||
|  |   void_list_node = build_tree_list (NULL_TREE, void_type_node); | ||||||
|  |  | ||||||
|  |   build_common_builtin_nodes (); | ||||||
|  |  | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | constexpr std::size_t pointer_size = 4; | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | elna_parse_file (const char *filename) | ||||||
|  | { | ||||||
|  |   std::ifstream file{ filename, std::ios::in }; | ||||||
|  |  | ||||||
|  |   if (!file) | ||||||
|  |     { | ||||||
|  |       fatal_error (UNKNOWN_LOCATION, "cannot open filename %s: %m", filename); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   elna::source::driver driver{ filename }; | ||||||
|  |   elna::source::lexer lexer(file); | ||||||
|  |   yy::parser parser(lexer, driver); | ||||||
|  |  | ||||||
|  |   if (auto result = parser()) | ||||||
|  |     { | ||||||
|  |       for (const auto& error : driver.errors()) | ||||||
|  |         { | ||||||
|  |           linemap_add (line_table, LC_ENTER, 0, filename, 1); | ||||||
|  |  | ||||||
|  |             linemap_line_start (line_table, error->line (), 0); | ||||||
|  |             auto gcc_location = linemap_position_for_column (line_table, error->column ()); | ||||||
|  |       linemap_add (line_table, LC_LEAVE, 0, NULL, 0); | ||||||
|  |  | ||||||
|  |             error_at (gcc_location, error->what ().c_str ()); | ||||||
|  |         } | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |    | ||||||
|  |     auto symbol_table = elna::source::add_builtin_symbols(); | ||||||
|  |     elna::source::name_analysis_visitor name_analysis_visitor{ symbol_table, filename, pointer_size }; | ||||||
|  |     elna::source::type_analysis_visitor type_analysis_visitor{ symbol_table, filename, pointer_size }; | ||||||
|  |     elna::gcc::generic_visitor generic_visitor; | ||||||
|  |  | ||||||
|  |     name_analysis_visitor.visit(driver.tree.get()); | ||||||
|  |     type_analysis_visitor.visit(driver.tree.get()); | ||||||
|  |     generic_visitor.visit(driver.tree.get()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | elna_langhook_parse_file (void) | ||||||
|  | { | ||||||
|  |   for (int i = 0; i < num_in_fnames; i++) | ||||||
|  |     { | ||||||
|  |       elna_parse_file (in_fnames[i]); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static tree | ||||||
|  | elna_langhook_type_for_mode (enum machine_mode mode, int unsignedp) | ||||||
|  | { | ||||||
|  |   if (mode == TYPE_MODE (float_type_node)) | ||||||
|  |     return float_type_node; | ||||||
|  |  | ||||||
|  |   if (mode == TYPE_MODE (double_type_node)) | ||||||
|  |     return double_type_node; | ||||||
|  |  | ||||||
|  |   if (mode == TYPE_MODE (intQI_type_node)) | ||||||
|  |     return unsignedp ? unsigned_intQI_type_node : intQI_type_node; | ||||||
|  |   if (mode == TYPE_MODE (intHI_type_node)) | ||||||
|  |     return unsignedp ? unsigned_intHI_type_node : intHI_type_node; | ||||||
|  |   if (mode == TYPE_MODE (intSI_type_node)) | ||||||
|  |     return unsignedp ? unsigned_intSI_type_node : intSI_type_node; | ||||||
|  |   if (mode == TYPE_MODE (intDI_type_node)) | ||||||
|  |     return unsignedp ? unsigned_intDI_type_node : intDI_type_node; | ||||||
|  |   if (mode == TYPE_MODE (intTI_type_node)) | ||||||
|  |     return unsignedp ? unsigned_intTI_type_node : intTI_type_node; | ||||||
|  |  | ||||||
|  |   if (mode == TYPE_MODE (integer_type_node)) | ||||||
|  |     return unsignedp ? unsigned_type_node : integer_type_node; | ||||||
|  |  | ||||||
|  |   if (mode == TYPE_MODE (long_integer_type_node)) | ||||||
|  |     return unsignedp ? long_unsigned_type_node : long_integer_type_node; | ||||||
|  |  | ||||||
|  |   if (mode == TYPE_MODE (long_long_integer_type_node)) | ||||||
|  |     return unsignedp ? long_long_unsigned_type_node | ||||||
|  | 		     : long_long_integer_type_node; | ||||||
|  |  | ||||||
|  |   if (COMPLEX_MODE_P (mode)) | ||||||
|  |     { | ||||||
|  |       if (mode == TYPE_MODE (complex_float_type_node)) | ||||||
|  | 	return complex_float_type_node; | ||||||
|  |       if (mode == TYPE_MODE (complex_double_type_node)) | ||||||
|  | 	return complex_double_type_node; | ||||||
|  |       if (mode == TYPE_MODE (complex_long_double_type_node)) | ||||||
|  | 	return complex_long_double_type_node; | ||||||
|  |       if (mode == TYPE_MODE (complex_integer_type_node) && !unsignedp) | ||||||
|  | 	return complex_integer_type_node; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   /* gcc_unreachable */ | ||||||
|  |   return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static tree | ||||||
|  | elna_langhook_type_for_size (unsigned int bits ATTRIBUTE_UNUSED, | ||||||
|  | 			     int unsignedp ATTRIBUTE_UNUSED) | ||||||
|  | { | ||||||
|  |   gcc_unreachable (); | ||||||
|  |   return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Record a builtin function.  We just ignore builtin functions.  */ | ||||||
|  |  | ||||||
|  | static tree | ||||||
|  | elna_langhook_builtin_function (tree decl) | ||||||
|  | { | ||||||
|  |   return decl; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static bool | ||||||
|  | elna_langhook_global_bindings_p (void) | ||||||
|  | { | ||||||
|  |   gcc_unreachable (); | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static tree | ||||||
|  | elna_langhook_pushdecl (tree decl ATTRIBUTE_UNUSED) | ||||||
|  | { | ||||||
|  |   gcc_unreachable (); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static tree | ||||||
|  | elna_langhook_getdecls (void) | ||||||
|  | { | ||||||
|  |   return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_NAME | ||||||
|  | #define LANG_HOOKS_NAME "Elna" | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_INIT | ||||||
|  | #define LANG_HOOKS_INIT elna_langhook_init | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_PARSE_FILE | ||||||
|  | #define LANG_HOOKS_PARSE_FILE elna_langhook_parse_file | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_TYPE_FOR_MODE | ||||||
|  | #define LANG_HOOKS_TYPE_FOR_MODE elna_langhook_type_for_mode | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_TYPE_FOR_SIZE | ||||||
|  | #define LANG_HOOKS_TYPE_FOR_SIZE elna_langhook_type_for_size | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_BUILTIN_FUNCTION | ||||||
|  | #define LANG_HOOKS_BUILTIN_FUNCTION elna_langhook_builtin_function | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_GLOBAL_BINDINGS_P | ||||||
|  | #define LANG_HOOKS_GLOBAL_BINDINGS_P elna_langhook_global_bindings_p | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_PUSHDECL | ||||||
|  | #define LANG_HOOKS_PUSHDECL elna_langhook_pushdecl | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_GETDECLS | ||||||
|  | #define LANG_HOOKS_GETDECLS elna_langhook_getdecls | ||||||
|  |  | ||||||
|  | struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; | ||||||
|  |  | ||||||
|  | #include "gt-elna-elna1.h" | ||||||
|  | #include "gtype-elna.h" | ||||||
							
								
								
									
										68
									
								
								gcc/generic-visitor.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								gcc/generic-visitor.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | |||||||
|  | #include "elna/gcc/generic-visitor.h" | ||||||
|  |  | ||||||
|  | #include "input.h" | ||||||
|  | #include "cgraph.h" | ||||||
|  | #include "gimplify.h" | ||||||
|  |  | ||||||
|  | namespace elna | ||||||
|  | { | ||||||
|  | namespace gcc | ||||||
|  | { | ||||||
|  |     void generic_visitor::visit(source::call_statement *statement) | ||||||
|  |     { | ||||||
|  |         const char *format_integer = "%d\n"; | ||||||
|  |         tree args[] = { | ||||||
|  |             build_string_literal(strlen(format_integer) + 1, format_integer), | ||||||
|  |             build_int_cst_type(integer_type_node, 8) | ||||||
|  |         }; | ||||||
|  |         tree fndecl_type_param[] = { | ||||||
|  |             build_pointer_type (build_qualified_type(char_type_node, TYPE_QUAL_CONST)) /* const char* */ | ||||||
|  |         }; | ||||||
|  |         tree fndecl_type = build_varargs_function_type_array(integer_type_node, 1, fndecl_type_param); | ||||||
|  |  | ||||||
|  |         tree printf_fn_decl = build_fn_decl("printf", fndecl_type); | ||||||
|  |         DECL_EXTERNAL (printf_fn_decl) = 1; | ||||||
|  |  | ||||||
|  |         tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), printf_fn_decl); | ||||||
|  |  | ||||||
|  |         tree stmt = build_call_array(integer_type_node, printf_fn, 2, args); | ||||||
|  |  | ||||||
|  |         append_to_statement_list(stmt, &this->current_statements); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void generic_visitor::visit(source::program *program) | ||||||
|  |     { | ||||||
|  |         tree main_fndecl_type_param[] = { | ||||||
|  |             integer_type_node, | ||||||
|  |             build_pointer_type (build_pointer_type (char_type_node)) | ||||||
|  |         }; | ||||||
|  |         tree main_fndecl_type = build_function_type_array(integer_type_node, 2, main_fndecl_type_param); | ||||||
|  |         tree main_fndecl = build_fn_decl("main", main_fndecl_type); | ||||||
|  |         tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node); | ||||||
|  |         DECL_RESULT(main_fndecl) = resdecl; | ||||||
|  |         tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(main_fndecl), | ||||||
|  |                 build_int_cst_type(integer_type_node, 0)); | ||||||
|  |         tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result); | ||||||
|  |         | ||||||
|  |         this->current_statements = alloc_stmt_list(); | ||||||
|  |         | ||||||
|  |         empty_visitor::visit(program); | ||||||
|  |  | ||||||
|  |         append_to_statement_list(return_stmt, &this->current_statements); | ||||||
|  |         | ||||||
|  |         tree new_block = build_block(NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE); | ||||||
|  |         tree bind_expr = build3(BIND_EXPR, void_type_node, NULL_TREE,  this->current_statements, new_block); | ||||||
|  |         | ||||||
|  |         BLOCK_SUPERCONTEXT(new_block) = main_fndecl; | ||||||
|  |         DECL_INITIAL(main_fndecl) = new_block; | ||||||
|  |         DECL_SAVED_TREE(main_fndecl) = bind_expr; | ||||||
|  |         | ||||||
|  |         DECL_EXTERNAL(main_fndecl) = 0; | ||||||
|  |         DECL_PRESERVE_P(main_fndecl) = 1; | ||||||
|  |         | ||||||
|  |         gimplify_function_tree(main_fndecl); | ||||||
|  |         | ||||||
|  |         cgraph_node::finalize_function(main_fndecl, true); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								gcc/lang-specs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								gcc/lang-specs.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | /* gcc-src/gcc/config/lang-specs.in */ | ||||||
|  | {".elna",  "@elna", 0, 1, 0}, | ||||||
|  | {"@elna",  "elna1 %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}", 0, 1, 0}, | ||||||
							
								
								
									
										250
									
								
								gcc/tiny1.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								gcc/tiny1.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,250 @@ | |||||||
|  | #include "config.h" | ||||||
|  | #include "system.h" | ||||||
|  | #include "coretypes.h" | ||||||
|  | #include "target.h" | ||||||
|  | #include "tree.h" | ||||||
|  | #include "tree-iterator.h" | ||||||
|  | #include "gimple-expr.h" | ||||||
|  | #include "diagnostic.h" | ||||||
|  | #include "opts.h" | ||||||
|  | #include "fold-const.h" | ||||||
|  | #include "cgraph.h" | ||||||
|  | #include "gimplify.h" | ||||||
|  | #include "stor-layout.h" | ||||||
|  | #include "debug.h" | ||||||
|  | #include "convert.h" | ||||||
|  | #include "langhooks.h" | ||||||
|  | #include "langhooks-def.h" | ||||||
|  | #include "common/common-target.h" | ||||||
|  |  | ||||||
|  | /* Language-dependent contents of a type.  */ | ||||||
|  |  | ||||||
|  | struct GTY (()) lang_type | ||||||
|  | { | ||||||
|  |   char dummy; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Language-dependent contents of a decl.  */ | ||||||
|  |  | ||||||
|  | struct GTY (()) lang_decl | ||||||
|  | { | ||||||
|  |   char dummy; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Language-dependent contents of an identifier.  This must include a | ||||||
|  |    tree_identifier.  */ | ||||||
|  |  | ||||||
|  | struct GTY (()) lang_identifier | ||||||
|  | { | ||||||
|  |   struct tree_identifier common; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* The resulting tree type.  */ | ||||||
|  |  | ||||||
|  | union GTY ((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), | ||||||
|  | 	    chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), " | ||||||
|  | 			"TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN " | ||||||
|  | 			"(&%h.generic)) : NULL"))) lang_tree_node | ||||||
|  | { | ||||||
|  |   union tree_node GTY ((tag ("0"), desc ("tree_node_structure (&%h)"))) generic; | ||||||
|  |   struct lang_identifier GTY ((tag ("1"))) identifier; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* We don't use language_function.  */ | ||||||
|  |  | ||||||
|  | struct GTY (()) language_function | ||||||
|  | { | ||||||
|  |   int dummy; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Creates an expression whose value is that of EXPR, converted to type TYPE. | ||||||
|  |    This function implements all reasonable scalar conversions.  */ | ||||||
|  |  | ||||||
|  | tree | ||||||
|  | convert (tree type, tree expr) | ||||||
|  | { | ||||||
|  |   return expr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Language hooks.  */ | ||||||
|  |  | ||||||
|  | static bool | ||||||
|  | elna_langhook_init (void) | ||||||
|  | { | ||||||
|  |   /* NOTE: Newer versions of GCC use only: | ||||||
|  |            build_common_tree_nodes (false); | ||||||
|  |      See Eugene's comment in the comments section. */ | ||||||
|  |   build_common_tree_nodes (false); | ||||||
|  |  | ||||||
|  |   /* I don't know why this has to be done explicitly.  */ | ||||||
|  |   void_list_node = build_tree_list (NULL_TREE, void_type_node); | ||||||
|  |  | ||||||
|  |   build_common_builtin_nodes (); | ||||||
|  |  | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | elna_parse_file (const char *filename) | ||||||
|  | { | ||||||
|  |   FILE *file = fopen (filename, "r"); | ||||||
|  |   if (file == NULL) | ||||||
|  |     { | ||||||
|  |       fatal_error (UNKNOWN_LOCATION, "cannot open filename %s: %m", filename); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   tree main_fndecl_type_param[] = { | ||||||
|  |       integer_type_node, | ||||||
|  |       build_pointer_type (build_pointer_type (char_type_node)) | ||||||
|  |   }; | ||||||
|  |   tree main_fndecl_type = build_function_type_array (integer_type_node, 2, main_fndecl_type_param); | ||||||
|  |   tree main_fndecl = build_fn_decl ("main", main_fndecl_type); | ||||||
|  |   tree resdecl = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node); | ||||||
|  |   DECL_RESULT (main_fndecl) = resdecl; | ||||||
|  |   tree set_result | ||||||
|  |     = build2 (INIT_EXPR, void_type_node, DECL_RESULT (main_fndecl), | ||||||
|  | 	      build_int_cst_type (integer_type_node, 3)); | ||||||
|  |   tree return_stmt = build1 (RETURN_EXPR, void_type_node, set_result); | ||||||
|  |  | ||||||
|  |   tree list = alloc_stmt_list (); | ||||||
|  |  | ||||||
|  |   append_to_statement_list (return_stmt, &list); | ||||||
|  |  | ||||||
|  |   tree new_block = build_block (NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE); | ||||||
|  |   tree bind_expr = build3 (BIND_EXPR, void_type_node, NULL_TREE,  list, new_block); | ||||||
|  |  | ||||||
|  |   BLOCK_SUPERCONTEXT (new_block) = main_fndecl; | ||||||
|  |   DECL_INITIAL (main_fndecl) = new_block; | ||||||
|  |   DECL_SAVED_TREE (main_fndecl) = bind_expr; | ||||||
|  |  | ||||||
|  |   DECL_EXTERNAL (main_fndecl) = 0; | ||||||
|  |   DECL_PRESERVE_P (main_fndecl) = 1; | ||||||
|  |  | ||||||
|  |   gimplify_function_tree (main_fndecl); | ||||||
|  |  | ||||||
|  |   cgraph_node::finalize_function (main_fndecl, true); | ||||||
|  |  | ||||||
|  |   fclose(file); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | elna_langhook_parse_file (void) | ||||||
|  | { | ||||||
|  |   for (int i = 0; i < num_in_fnames; i++) | ||||||
|  |     { | ||||||
|  |       elna_parse_file (in_fnames[i]); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static tree | ||||||
|  | elna_langhook_type_for_mode (enum machine_mode mode, int unsignedp) | ||||||
|  | { | ||||||
|  |   if (mode == TYPE_MODE (float_type_node)) | ||||||
|  |     return float_type_node; | ||||||
|  |  | ||||||
|  |   if (mode == TYPE_MODE (double_type_node)) | ||||||
|  |     return double_type_node; | ||||||
|  |  | ||||||
|  |   if (mode == TYPE_MODE (intQI_type_node)) | ||||||
|  |     return unsignedp ? unsigned_intQI_type_node : intQI_type_node; | ||||||
|  |   if (mode == TYPE_MODE (intHI_type_node)) | ||||||
|  |     return unsignedp ? unsigned_intHI_type_node : intHI_type_node; | ||||||
|  |   if (mode == TYPE_MODE (intSI_type_node)) | ||||||
|  |     return unsignedp ? unsigned_intSI_type_node : intSI_type_node; | ||||||
|  |   if (mode == TYPE_MODE (intDI_type_node)) | ||||||
|  |     return unsignedp ? unsigned_intDI_type_node : intDI_type_node; | ||||||
|  |   if (mode == TYPE_MODE (intTI_type_node)) | ||||||
|  |     return unsignedp ? unsigned_intTI_type_node : intTI_type_node; | ||||||
|  |  | ||||||
|  |   if (mode == TYPE_MODE (integer_type_node)) | ||||||
|  |     return unsignedp ? unsigned_type_node : integer_type_node; | ||||||
|  |  | ||||||
|  |   if (mode == TYPE_MODE (long_integer_type_node)) | ||||||
|  |     return unsignedp ? long_unsigned_type_node : long_integer_type_node; | ||||||
|  |  | ||||||
|  |   if (mode == TYPE_MODE (long_long_integer_type_node)) | ||||||
|  |     return unsignedp ? long_long_unsigned_type_node | ||||||
|  | 		     : long_long_integer_type_node; | ||||||
|  |  | ||||||
|  |   if (COMPLEX_MODE_P (mode)) | ||||||
|  |     { | ||||||
|  |       if (mode == TYPE_MODE (complex_float_type_node)) | ||||||
|  | 	return complex_float_type_node; | ||||||
|  |       if (mode == TYPE_MODE (complex_double_type_node)) | ||||||
|  | 	return complex_double_type_node; | ||||||
|  |       if (mode == TYPE_MODE (complex_long_double_type_node)) | ||||||
|  | 	return complex_long_double_type_node; | ||||||
|  |       if (mode == TYPE_MODE (complex_integer_type_node) && !unsignedp) | ||||||
|  | 	return complex_integer_type_node; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   /* gcc_unreachable */ | ||||||
|  |   return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static tree | ||||||
|  | elna_langhook_type_for_size (unsigned int bits ATTRIBUTE_UNUSED, | ||||||
|  | 			     int unsignedp ATTRIBUTE_UNUSED) | ||||||
|  | { | ||||||
|  |   gcc_unreachable (); | ||||||
|  |   return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Record a builtin function.  We just ignore builtin functions.  */ | ||||||
|  |  | ||||||
|  | static tree | ||||||
|  | elna_langhook_builtin_function (tree decl) | ||||||
|  | { | ||||||
|  |   return decl; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static bool | ||||||
|  | elna_langhook_global_bindings_p (void) | ||||||
|  | { | ||||||
|  |   gcc_unreachable (); | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static tree | ||||||
|  | elna_langhook_pushdecl (tree decl ATTRIBUTE_UNUSED) | ||||||
|  | { | ||||||
|  |   gcc_unreachable (); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static tree | ||||||
|  | elna_langhook_getdecls (void) | ||||||
|  | { | ||||||
|  |   return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_NAME | ||||||
|  | #define LANG_HOOKS_NAME "Tiny" | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_INIT | ||||||
|  | #define LANG_HOOKS_INIT elna_langhook_init | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_PARSE_FILE | ||||||
|  | #define LANG_HOOKS_PARSE_FILE elna_langhook_parse_file | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_TYPE_FOR_MODE | ||||||
|  | #define LANG_HOOKS_TYPE_FOR_MODE elna_langhook_type_for_mode | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_TYPE_FOR_SIZE | ||||||
|  | #define LANG_HOOKS_TYPE_FOR_SIZE elna_langhook_type_for_size | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_BUILTIN_FUNCTION | ||||||
|  | #define LANG_HOOKS_BUILTIN_FUNCTION elna_langhook_builtin_function | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_GLOBAL_BINDINGS_P | ||||||
|  | #define LANG_HOOKS_GLOBAL_BINDINGS_P elna_langhook_global_bindings_p | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_PUSHDECL | ||||||
|  | #define LANG_HOOKS_PUSHDECL elna_langhook_pushdecl | ||||||
|  |  | ||||||
|  | #undef LANG_HOOKS_GETDECLS | ||||||
|  | #define LANG_HOOKS_GETDECLS elna_langhook_getdecls | ||||||
|  |  | ||||||
|  | struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; | ||||||
|  |  | ||||||
|  | #include "gt-tiny-tiny1.h" | ||||||
|  | #include "gtype-tiny.h" | ||||||
							
								
								
									
										16
									
								
								gcc/tinyspec.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								gcc/tinyspec.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | void | ||||||
|  | lang_specific_driver (struct cl_decoded_option ** /* in_decoded_options */, | ||||||
|  | 		      unsigned int * /* in_decoded_options_count */, | ||||||
|  | 		      int * /*in_added_libraries */) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Called before linking.  Returns 0 on success and -1 on failure.  */ | ||||||
|  | int | ||||||
|  | lang_specific_pre_link (void) | ||||||
|  | { | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Number of extra output files that lang_specific_pre_link may generate.  */ | ||||||
|  | int lang_specific_extra_outfiles = 0; | ||||||
							
								
								
									
										24
									
								
								include/elna/gcc/generic-visitor.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								include/elna/gcc/generic-visitor.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "elna/source/ast.h" | ||||||
|  |  | ||||||
|  | #include "config.h" | ||||||
|  | #include "system.h" | ||||||
|  | #include "coretypes.h" | ||||||
|  | #include "tree.h" | ||||||
|  | #include "tree-iterator.h" | ||||||
|  |  | ||||||
|  | namespace elna | ||||||
|  | { | ||||||
|  | namespace gcc | ||||||
|  | { | ||||||
|  |     class generic_visitor final : public source::empty_visitor | ||||||
|  |     { | ||||||
|  |         tree current_statements{ NULL_TREE }; | ||||||
|  |  | ||||||
|  |     public: | ||||||
|  |         void visit(source::program *program) override; | ||||||
|  |         void visit(source::call_statement *statement) override; | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | } | ||||||
| @@ -1,10 +1,12 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <memory> | #include <memory> | ||||||
| #include "elna/source/result.hpp" | #include "elna/source/result.h" | ||||||
| #include "elna/source/types.hpp" | #include "elna/source/types.h" | ||||||
| 
 | 
 | ||||||
| namespace elna::source | namespace elna | ||||||
|  | { | ||||||
|  | namespace source | ||||||
| { | { | ||||||
|     enum class binary_operator |     enum class binary_operator | ||||||
|     { |     { | ||||||
| @@ -481,3 +483,4 @@ namespace elna::source | |||||||
|         unary_operator operation() const noexcept; |         unary_operator operation() const noexcept; | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  | } | ||||||
| @@ -1,10 +1,12 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <list> | #include <list> | ||||||
| #include "elna/source/ast.hpp" | #include "elna/source/ast.h" | ||||||
| #include "location.hh" | #include "location.hh" | ||||||
| 
 | 
 | ||||||
| namespace elna::source | namespace elna | ||||||
|  | { | ||||||
|  | namespace source | ||||||
| { | { | ||||||
|     position make_position(const yy::location& location); |     position make_position(const yy::location& location); | ||||||
| 
 | 
 | ||||||
| @@ -33,3 +35,4 @@ namespace elna::source | |||||||
|         const std::list<std::unique_ptr<struct error>>& errors() const noexcept; |         const std::list<std::unique_ptr<struct error>>& errors() const noexcept; | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  | } | ||||||
| @@ -2,9 +2,11 @@ | |||||||
| 
 | 
 | ||||||
| #include <cstddef> | #include <cstddef> | ||||||
| #include <filesystem> | #include <filesystem> | ||||||
| #include "elna/source/types.hpp" | #include "elna/source/types.h" | ||||||
| 
 | 
 | ||||||
| namespace elna::source | namespace elna | ||||||
|  | { | ||||||
|  | namespace source | ||||||
| { | { | ||||||
|     /**
 |     /**
 | ||||||
|      * Position in the source text. |      * Position in the source text. | ||||||
| @@ -100,3 +102,4 @@ namespace elna::source | |||||||
|         operation kind; |         operation kind; | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  | } | ||||||
| @@ -1,10 +1,12 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <list> | #include <list> | ||||||
| #include "elna/source/ast.hpp" | #include "elna/source/ast.h" | ||||||
| #include "elna/source/symbol_table.hpp" | #include "elna/source/symbol_table.h" | ||||||
| 
 | 
 | ||||||
| namespace elna::source | namespace elna | ||||||
|  | { | ||||||
|  | namespace source | ||||||
| { | { | ||||||
|     class name_analysis_visitor final : public empty_visitor |     class name_analysis_visitor final : public empty_visitor | ||||||
|     { |     { | ||||||
| @@ -92,3 +94,4 @@ namespace elna::source | |||||||
|         void visit(assign_statement *statement) override; |         void visit(assign_statement *statement) override; | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  | } | ||||||
| @@ -5,9 +5,18 @@ | |||||||
| #include <string> | #include <string> | ||||||
| #include <memory> | #include <memory> | ||||||
| 
 | 
 | ||||||
| namespace elna::source | namespace elna | ||||||
|  | { | ||||||
|  | namespace source | ||||||
| { | { | ||||||
|     class symbol_table; |     class symbol_table; | ||||||
|  |     class type_info; | ||||||
|  |     class typed_info; | ||||||
|  |     class constant_info; | ||||||
|  |     class variable_info; | ||||||
|  |     class parameter_info; | ||||||
|  |     class intrinsic_info; | ||||||
|  |     class procedure_info; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Generic language entity information. |      * Generic language entity information. | ||||||
| @@ -17,6 +26,14 @@ namespace elna::source | |||||||
|     public: |     public: | ||||||
|         virtual ~info() = 0; |         virtual ~info() = 0; | ||||||
| 
 | 
 | ||||||
|  |         virtual type_info *is_type_info() noexcept; | ||||||
|  |         virtual typed_info *is_typed_info() noexcept; | ||||||
|  |         virtual constant_info *is_constant_info() noexcept; | ||||||
|  |         virtual variable_info *is_variable_info() noexcept; | ||||||
|  |         virtual parameter_info *is_parameter_info() noexcept; | ||||||
|  |         virtual intrinsic_info *is_intrinsic_info() noexcept; | ||||||
|  |         virtual procedure_info *is_procedure_info() noexcept; | ||||||
|  | 
 | ||||||
|     protected: |     protected: | ||||||
|         info(); |         info(); | ||||||
|     }; |     }; | ||||||
| @@ -26,11 +43,13 @@ namespace elna::source | |||||||
|      */ |      */ | ||||||
|     class type_info final : public info |     class type_info final : public info | ||||||
|     { |     { | ||||||
|         std::shared_ptr<class type> m_type; |         std::shared_ptr<const class type> m_type; | ||||||
| 
 | 
 | ||||||
|     public: |     public: | ||||||
|         explicit type_info(const class type& type); |         explicit type_info(std::shared_ptr<class type> type); | ||||||
|         ~type_info() override; |         ~type_info() override; | ||||||
|  | 
 | ||||||
|  |         virtual type_info *is_type_info() noexcept override; | ||||||
|         std::shared_ptr<const class type> type() const noexcept; |         std::shared_ptr<const class type> type() const noexcept; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| @@ -47,6 +66,7 @@ namespace elna::source | |||||||
|     public: |     public: | ||||||
|         ~typed_info() override; |         ~typed_info() override; | ||||||
| 
 | 
 | ||||||
|  |         virtual typed_info *is_typed_info() noexcept override; | ||||||
|         std::shared_ptr<const class type> type() const noexcept; |         std::shared_ptr<const class type> type() const noexcept; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| @@ -60,6 +80,7 @@ namespace elna::source | |||||||
|     public: |     public: | ||||||
|         constant_info(std::shared_ptr<const class type> type, const std::int32_t value); |         constant_info(std::shared_ptr<const class type> type, const std::int32_t value); | ||||||
| 
 | 
 | ||||||
|  |         virtual constant_info *is_constant_info() noexcept override; | ||||||
|         std::int32_t value() const noexcept; |         std::int32_t value() const noexcept; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| @@ -72,6 +93,8 @@ namespace elna::source | |||||||
|         std::ptrdiff_t offset{ 0 }; |         std::ptrdiff_t offset{ 0 }; | ||||||
| 
 | 
 | ||||||
|         explicit variable_info(std::shared_ptr<const class type> type); |         explicit variable_info(std::shared_ptr<const class type> type); | ||||||
|  | 
 | ||||||
|  |         virtual variable_info *is_variable_info() noexcept override; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
| @@ -83,6 +106,8 @@ namespace elna::source | |||||||
|         std::ptrdiff_t offset{ 0 }; |         std::ptrdiff_t offset{ 0 }; | ||||||
| 
 | 
 | ||||||
|         explicit parameter_info(std::shared_ptr<const class type> type); |         explicit parameter_info(std::shared_ptr<const class type> type); | ||||||
|  | 
 | ||||||
|  |         virtual parameter_info *is_parameter_info() noexcept override; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
| @@ -98,6 +123,7 @@ namespace elna::source | |||||||
| 
 | 
 | ||||||
|         std::shared_ptr<const class procedure_type> type() const noexcept; |         std::shared_ptr<const class procedure_type> type() const noexcept; | ||||||
|         std::size_t parameter_stack_size() const noexcept; |         std::size_t parameter_stack_size() const noexcept; | ||||||
|  |         virtual intrinsic_info *is_intrinsic_info() noexcept override; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
| @@ -116,6 +142,7 @@ namespace elna::source | |||||||
| 
 | 
 | ||||||
|         std::shared_ptr<symbol_table> scope(); |         std::shared_ptr<symbol_table> scope(); | ||||||
|         std::size_t stack_size() const noexcept; |         std::size_t stack_size() const noexcept; | ||||||
|  |         virtual procedure_info *is_procedure_info() noexcept override; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
| @@ -158,4 +185,11 @@ namespace elna::source | |||||||
|          */ |          */ | ||||||
|         std::shared_ptr<symbol_table> scope(); |         std::shared_ptr<symbol_table> scope(); | ||||||
|     }; |     }; | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Creates a symbol table with predefined symbols. | ||||||
|  |      * | ||||||
|  |      * \return A symbol table with predefined symbols. | ||||||
|  |      */ | ||||||
|  |     std::shared_ptr<source::symbol_table> add_builtin_symbols();} | ||||||
| } | } | ||||||
| @@ -4,8 +4,14 @@ | |||||||
| #include <string> | #include <string> | ||||||
| #include <vector> | #include <vector> | ||||||
| 
 | 
 | ||||||
| namespace elna::source | namespace elna | ||||||
| { | { | ||||||
|  | namespace source | ||||||
|  | { | ||||||
|  |     class primitive_type; | ||||||
|  |     class pointer_type; | ||||||
|  |     class procedure_type; | ||||||
|  | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Type representation. |      * Type representation. | ||||||
|      */ |      */ | ||||||
| @@ -27,6 +33,13 @@ namespace elna::source | |||||||
|          */ |          */ | ||||||
|         virtual std::size_t size() const noexcept; |         virtual std::size_t size() const noexcept; | ||||||
| 
 | 
 | ||||||
|  |         /**
 | ||||||
|  |          * \return Unique type representation. | ||||||
|  |          */ | ||||||
|  |         virtual std::string type_name() const = 0; | ||||||
|  | 
 | ||||||
|  |         virtual const pointer_type *is_pointer_type() const; | ||||||
|  | 
 | ||||||
|         friend bool operator==(const type& lhs, const type& rhs) noexcept; |         friend bool operator==(const type& lhs, const type& rhs) noexcept; | ||||||
|         friend bool operator!=(const type& lhs, const type& rhs) noexcept; |         friend bool operator!=(const type& lhs, const type& rhs) noexcept; | ||||||
|     }; |     }; | ||||||
| @@ -34,11 +47,12 @@ namespace elna::source | |||||||
|     /**
 |     /**
 | ||||||
|      * Built-in type representation. |      * Built-in type representation. | ||||||
|      */ |      */ | ||||||
|     struct primitive_type : public type |     class primitive_type final : public type | ||||||
|     { |     { | ||||||
|         /// Type name.
 |         /// Type name.
 | ||||||
|         const std::string type_name; |         const std::string m_type_name; | ||||||
| 
 | 
 | ||||||
|  |     public: | ||||||
|         /**
 |         /**
 | ||||||
|          * Constructor. |          * Constructor. | ||||||
|          * |          * | ||||||
| @@ -47,14 +61,13 @@ namespace elna::source | |||||||
|          */ |          */ | ||||||
|         primitive_type(const std::string& type_name, const std::size_t byte_size); |         primitive_type(const std::string& type_name, const std::size_t byte_size); | ||||||
| 
 | 
 | ||||||
|         bool operator==(const primitive_type& that) const noexcept; |         virtual std::string type_name() const override; | ||||||
|         bool operator!=(const primitive_type& that) const noexcept; |  | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Typed pointer. |      * Typed pointer. | ||||||
|      */ |      */ | ||||||
|     struct pointer_type : public type |     struct pointer_type final : public type | ||||||
|     { |     { | ||||||
|         /// Pointer target type.
 |         /// Pointer target type.
 | ||||||
|         std::shared_ptr<const type> base_type; |         std::shared_ptr<const type> base_type; | ||||||
| @@ -67,14 +80,15 @@ namespace elna::source | |||||||
|          */ |          */ | ||||||
|         pointer_type(std::shared_ptr<const type> base_type, const std::size_t byte_size); |         pointer_type(std::shared_ptr<const type> base_type, const std::size_t byte_size); | ||||||
| 
 | 
 | ||||||
|         bool operator==(const pointer_type& that) const noexcept; |         virtual std::string type_name() const override; | ||||||
|         bool operator!=(const pointer_type& that) const noexcept; | 
 | ||||||
|  |         virtual const pointer_type *is_pointer_type() const override; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Type of a procedure. |      * Type of a procedure. | ||||||
|      */ |      */ | ||||||
|     struct procedure_type : public type |     struct procedure_type final : public type | ||||||
|     { |     { | ||||||
|         /// Argument types.
 |         /// Argument types.
 | ||||||
|         std::vector<std::shared_ptr<const type>> arguments; |         std::vector<std::shared_ptr<const type>> arguments; | ||||||
| @@ -87,13 +101,13 @@ namespace elna::source | |||||||
|          */ |          */ | ||||||
|         procedure_type(std::vector<std::shared_ptr<const type>> arguments, const std::size_t byte_size); |         procedure_type(std::vector<std::shared_ptr<const type>> arguments, const std::size_t byte_size); | ||||||
| 
 | 
 | ||||||
|         bool operator==(const procedure_type& that) const noexcept; |         virtual std::string type_name() const override; | ||||||
|         bool operator!=(const procedure_type& that) const noexcept; |  | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     bool operator==(const type& lhs, const type& rhs) noexcept; |     bool operator==(const type& lhs, const type& rhs) noexcept; | ||||||
|     bool operator!=(const type& lhs, const type& rhs) noexcept; |     bool operator!=(const type& lhs, const type& rhs) noexcept; | ||||||
| 
 | 
 | ||||||
|     inline const primitive_type boolean_type{ "Boolean", 1 }; |     extern const primitive_type boolean_type; | ||||||
|     inline const primitive_type int_type{ "Int", 4 }; |     extern const primitive_type int_type; | ||||||
|  | } | ||||||
| } | } | ||||||
| @@ -1,7 +1,8 @@ | |||||||
| #include "elna/source/ast.hpp" | #include "elna/source/ast.h" | ||||||
| #include <stdexcept> |  | ||||||
| 
 | 
 | ||||||
| namespace elna::source | namespace elna | ||||||
|  | { | ||||||
|  | namespace source | ||||||
| { | { | ||||||
|     void empty_visitor::visit(declaration *declaration) |     void empty_visitor::visit(declaration *declaration) | ||||||
|     { |     { | ||||||
| @@ -69,7 +70,7 @@ namespace elna::source | |||||||
| 
 | 
 | ||||||
|     void empty_visitor::visit(program *program) |     void empty_visitor::visit(program *program) | ||||||
|     { |     { | ||||||
|         visit(dynamic_cast<block *>(program)); |         visit(reinterpret_cast<block *>(program)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void empty_visitor::visit(binary_expression *expression) |     void empty_visitor::visit(binary_expression *expression) | ||||||
| @@ -368,7 +369,7 @@ namespace elna::source | |||||||
|                 this->m_operator = binary_operator::greater_equal; |                 this->m_operator = binary_operator::greater_equal; | ||||||
|                 break; |                 break; | ||||||
|             default: |             default: | ||||||
|                 throw std::logic_error("Invalid binary operator"); |                 __builtin_unreachable(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @@ -405,7 +406,7 @@ namespace elna::source | |||||||
|                 this->m_operator = unary_operator::dereference; |                 this->m_operator = unary_operator::dereference; | ||||||
|                 break; |                 break; | ||||||
|             default: |             default: | ||||||
|                 throw std::logic_error("Invalid unary operator"); |                 __builtin_unreachable(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @@ -522,3 +523,4 @@ namespace elna::source | |||||||
|         return *m_body; |         return *m_body; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | } | ||||||
| @@ -1,6 +1,8 @@ | |||||||
| #include "elna/source/driver.hpp" | #include "elna/source/driver.h" | ||||||
| 
 | 
 | ||||||
| namespace elna::source | namespace elna | ||||||
|  | { | ||||||
|  | namespace source | ||||||
| { | { | ||||||
|     position make_position(const yy::location& location) |     position make_position(const yy::location& location) | ||||||
|     { |     { | ||||||
| @@ -36,3 +38,4 @@ namespace elna::source | |||||||
|         return m_errors; |         return m_errors; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | } | ||||||
| @@ -3,10 +3,10 @@ | |||||||
| #define YY_USER_ACTION this->location.columns(yyleng); | #define YY_USER_ACTION this->location.columns(yyleng); | ||||||
|  |  | ||||||
| #include <sstream> | #include <sstream> | ||||||
| #include "parser.hpp" | #include "parser.hh" | ||||||
|  |  | ||||||
| #undef YY_DECL | #undef YY_DECL | ||||||
| #define YY_DECL yy::parser::symbol_type elna::source::lexer::lex() | #define YY_DECL yy::parser::symbol_type elna::source::lexer::lex(elna::source::driver& driver) | ||||||
| #define yyterminate() return yy::parser::make_YYEOF(this->location) | #define yyterminate() return yy::parser::make_YYEOF(this->location) | ||||||
| %} | %} | ||||||
|  |  | ||||||
| @@ -126,6 +126,6 @@ false                   { | |||||||
|                             std::stringstream ss; |                             std::stringstream ss; | ||||||
|  |  | ||||||
|                             ss << "Illegal character 0x" << std::hex << static_cast<unsigned int>(yytext[0]); |                             ss << "Illegal character 0x" << std::hex << static_cast<unsigned int>(yytext[0]); | ||||||
|                             throw yy::parser::syntax_error(this->location, ss.str()); |                             driver.error(this->location, ss.str()); | ||||||
|                         } |                         } | ||||||
| %% | %% | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
| %code requires { | %code requires { | ||||||
|     #include <cstdint> |     #include <cstdint> | ||||||
|     #include <iostream> |     #include <iostream> | ||||||
|     #include "elna/source/driver.hpp" |     #include "elna/source/driver.h" | ||||||
|  |  | ||||||
|     #if !defined(yyFlexLexerOnce) |     #if !defined(yyFlexLexerOnce) | ||||||
|         #include <FlexLexer.h> |         #include <FlexLexer.h> | ||||||
| @@ -30,7 +30,7 @@ | |||||||
|         { |         { | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         yy::parser::symbol_type lex(); |         yy::parser::symbol_type lex(elna::source::driver& driver); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     } |     } | ||||||
| @@ -39,10 +39,9 @@ | |||||||
| %define api.token.raw | %define api.token.raw | ||||||
| %define api.token.constructor | %define api.token.constructor | ||||||
| %define api.value.type variant | %define api.value.type variant | ||||||
| %define parse.assert |  | ||||||
|  |  | ||||||
| %parse-param {elna::source::lexer& lexer} | %parse-param {elna::source::lexer& lexer} | ||||||
| %parse-param {elna::source::driver& driver} | %param {elna::source::driver& driver} | ||||||
| %locations | %locations | ||||||
|  |  | ||||||
| %header | %header | ||||||
| @@ -58,7 +57,6 @@ | |||||||
| %token IF THEN WHILE DO | %token IF THEN WHILE DO | ||||||
| %token CONST VAR PROCEDURE | %token CONST VAR PROCEDURE | ||||||
| %token BEGIN_BLOCK END_BLOCK | %token BEGIN_BLOCK END_BLOCK | ||||||
| %token TRUE FALSE |  | ||||||
| %token LEFT_PAREN RIGHT_PAREN SEMICOLON DOT COMMA | %token LEFT_PAREN RIGHT_PAREN SEMICOLON DOT COMMA | ||||||
| %token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS | %token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS | ||||||
| %token PLUS MINUS MULTIPLICATION DIVISION | %token PLUS MINUS MULTIPLICATION DIVISION | ||||||
|   | |||||||
| @@ -1,6 +1,8 @@ | |||||||
| #include "elna/source/result.hpp" | #include "elna/source/result.h" | ||||||
| 
 | 
 | ||||||
| namespace elna::source | namespace elna | ||||||
|  | { | ||||||
|  | namespace source | ||||||
| { | { | ||||||
|     error::error(const std::filesystem::path& path, const position position) |     error::error(const std::filesystem::path& path, const position position) | ||||||
|         : m_position(position), m_path(path) |         : m_position(position), m_path(path) | ||||||
| @@ -33,8 +35,8 @@ namespace elna::source | |||||||
|         return "Name '" + name + "' was already defined"; |         return "Name '" + name + "' was already defined"; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     type_mismatch::type_mismatch(std::shared_ptr<const type> got, operation kind, const std::filesystem::path& path, |     type_mismatch::type_mismatch(std::shared_ptr<const type> got, operation kind, | ||||||
|             const struct position position) |             const std::filesystem::path& path, const struct position position) | ||||||
|         : error(path, position), kind(kind), got(got) |         : error(path, position), kind(kind), got(got) | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
| @@ -44,3 +46,4 @@ namespace elna::source | |||||||
|         return "Type cannot be used here."; |         return "Type cannot be used here."; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | } | ||||||
| @@ -1,8 +1,10 @@ | |||||||
| #include "elna/source/semantic.hpp" | #include "elna/source/semantic.h" | ||||||
| #include "elna/source/result.hpp" | #include "elna/source/result.h" | ||||||
| #include <cstdlib> | #include <cstdlib> | ||||||
| 
 | 
 | ||||||
| namespace elna::source | namespace elna | ||||||
|  | { | ||||||
|  | namespace source | ||||||
| { | { | ||||||
|     name_analysis_visitor::name_analysis_visitor(std::shared_ptr<symbol_table> table, |     name_analysis_visitor::name_analysis_visitor(std::shared_ptr<symbol_table> table, | ||||||
|             const std::filesystem::path& filename, const std::size_t target_pointer_size) |             const std::filesystem::path& filename, const std::size_t target_pointer_size) | ||||||
| @@ -12,15 +14,14 @@ namespace elna::source | |||||||
| 
 | 
 | ||||||
|     void name_analysis_visitor::visit(constant_definition *definition) |     void name_analysis_visitor::visit(constant_definition *definition) | ||||||
|     { |     { | ||||||
|         auto constant_type = std::make_shared<const class type>(int_type); |         auto constant_type = std::make_shared<const class primitive_type>(int_type); | ||||||
|         this->table->enter(definition->identifier(), |         this->table->enter(definition->identifier(), | ||||||
|                 std::make_shared<constant_info>(constant_type, definition->body().number())); |                 std::make_shared<constant_info>(constant_type, definition->body().number())); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::shared_ptr<const type> name_analysis_visitor::convert_declaration_type(const type_expression& ast_type) const |     std::shared_ptr<const type> name_analysis_visitor::convert_declaration_type(const type_expression& ast_type) const | ||||||
|     { |     { | ||||||
|         auto variable_type = std::dynamic_pointer_cast<type_info>(table->lookup(ast_type.base())) |         auto variable_type = table->lookup(ast_type.base())->is_type_info()->type(); | ||||||
|             ->type(); |  | ||||||
|         std::shared_ptr<type> declaration_type; |         std::shared_ptr<type> declaration_type; | ||||||
| 
 | 
 | ||||||
|         if (ast_type.is_pointer()) |         if (ast_type.is_pointer()) | ||||||
| @@ -33,11 +34,11 @@ namespace elna::source | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void name_analysis_visitor::visit(declaration *declaration) |     void name_analysis_visitor::visit(declaration *declarationx) | ||||||
|     { |     { | ||||||
|         std::shared_ptr<const type> declaration_type = convert_declaration_type(declaration->type()); |         std::shared_ptr<const type> declaration_type = convert_declaration_type(declarationx->type()); | ||||||
| 
 | 
 | ||||||
|         this->table->enter(declaration->identifier(), |         this->table->enter(declarationx->identifier(), | ||||||
|                 std::make_shared<variable_info>(declaration_type)); |                 std::make_shared<variable_info>(declaration_type)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @@ -87,12 +88,12 @@ namespace elna::source | |||||||
|     { |     { | ||||||
|         auto declaration_info = this->table->lookup(declaration->identifier()); |         auto declaration_info = this->table->lookup(declaration->identifier()); | ||||||
| 
 | 
 | ||||||
|         if (auto variable = std::dynamic_pointer_cast<variable_info>(declaration_info)) |         if (auto variable = declaration_info->is_variable_info()) | ||||||
|         { |         { | ||||||
|             this->local_offset -= sizeof(std::int32_t); |             this->local_offset -= sizeof(std::int32_t); | ||||||
|             variable->offset = this->local_offset; |             variable->offset = this->local_offset; | ||||||
|         } |         } | ||||||
|         else if (auto parameter = std::dynamic_pointer_cast<parameter_info>(declaration_info)) |         else if (auto parameter = declaration_info->is_parameter_info()) | ||||||
|         { |         { | ||||||
|             parameter->offset = this->argument_offset; |             parameter->offset = this->argument_offset; | ||||||
|             this->argument_offset += sizeof(std::int32_t); |             this->argument_offset += sizeof(std::int32_t); | ||||||
| @@ -105,7 +106,7 @@ namespace elna::source | |||||||
|         this->argument_offset = 0; |         this->argument_offset = 0; | ||||||
| 
 | 
 | ||||||
|         empty_visitor::visit(program); |         empty_visitor::visit(program); | ||||||
|         std::dynamic_pointer_cast<procedure_info>(table->lookup("_start"))->local_stack_size = |         table->lookup("_start")->is_procedure_info()->local_stack_size = | ||||||
|             std::abs(this->local_offset); |             std::abs(this->local_offset); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @@ -113,7 +114,7 @@ namespace elna::source | |||||||
|     { |     { | ||||||
|         this->local_offset = 0; |         this->local_offset = 0; | ||||||
|         this->argument_offset = 0; |         this->argument_offset = 0; | ||||||
|         auto info = std::dynamic_pointer_cast<procedure_info>(this->table->lookup(procedure->identifier())); |         auto info = this->table->lookup(procedure->identifier())->is_procedure_info(); | ||||||
|         this->table = info->scope(); |         this->table = info->scope(); | ||||||
| 
 | 
 | ||||||
|         empty_visitor::visit(procedure); |         empty_visitor::visit(procedure); | ||||||
| @@ -125,7 +126,7 @@ namespace elna::source | |||||||
| 
 | 
 | ||||||
|     void allocator_visitor::visit(call_statement *statement) |     void allocator_visitor::visit(call_statement *statement) | ||||||
|     { |     { | ||||||
|         auto call_info = std::dynamic_pointer_cast<intrinsic_info>(this->table->lookup(statement->name())); |         auto call_info = this->table->lookup(statement->name())->is_intrinsic_info(); | ||||||
| 
 | 
 | ||||||
|         this->argument_offset = std::max(static_cast<std::size_t>(this->argument_offset), |         this->argument_offset = std::max(static_cast<std::size_t>(this->argument_offset), | ||||||
|                 call_info->parameter_stack_size()); |                 call_info->parameter_stack_size()); | ||||||
| @@ -140,18 +141,15 @@ namespace elna::source | |||||||
|     void type_analysis_visitor::visit(program *program) |     void type_analysis_visitor::visit(program *program) | ||||||
|     { |     { | ||||||
|         for (auto& definition : program->definitions()) |         for (auto& definition : program->definitions()) | ||||||
|         { |  | ||||||
|             if (dynamic_cast<procedure_definition *>(definition.get()) != nullptr) |  | ||||||
|         { |         { | ||||||
|             definition->accept(this); |             definition->accept(this); | ||||||
|         } |         } | ||||||
|         } |  | ||||||
|         program->body().accept(this); |         program->body().accept(this); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void type_analysis_visitor::visit(procedure_definition *procedure) |     void type_analysis_visitor::visit(procedure_definition *procedure) | ||||||
|     { |     { | ||||||
|         auto info = std::dynamic_pointer_cast<procedure_info>(this->table->lookup(procedure->identifier())); |         auto info = this->table->lookup(procedure->identifier())->is_procedure_info(); | ||||||
|         this->table = info->scope(); |         this->table = info->scope(); | ||||||
| 
 | 
 | ||||||
|         procedure->body().accept(this); |         procedure->body().accept(this); | ||||||
| @@ -161,17 +159,17 @@ namespace elna::source | |||||||
| 
 | 
 | ||||||
|     void type_analysis_visitor::visit(integer_literal *literal) |     void type_analysis_visitor::visit(integer_literal *literal) | ||||||
|     { |     { | ||||||
|         literal->data_type = std::dynamic_pointer_cast<type_info>(table->lookup("Int"))->type(); |         literal->data_type = table->lookup("Int")->is_type_info()->type(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void type_analysis_visitor::visit(boolean_literal *literal) |     void type_analysis_visitor::visit(boolean_literal *literal) | ||||||
|     { |     { | ||||||
|         literal->data_type = std::dynamic_pointer_cast<type_info>(table->lookup("Boolean"))->type(); |         literal->data_type = table->lookup("Boolean")->is_type_info()->type(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void type_analysis_visitor::visit(variable_expression *expression) |     void type_analysis_visitor::visit(variable_expression *expression) | ||||||
|     { |     { | ||||||
|         expression->data_type = std::dynamic_pointer_cast<typed_info>(table->lookup(expression->name()))->type(); |         expression->data_type = table->lookup(expression->name())->is_typed_info()->type(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void type_analysis_visitor::visit(unary_expression *expression) |     void type_analysis_visitor::visit(unary_expression *expression) | ||||||
| @@ -187,9 +185,9 @@ namespace elna::source | |||||||
|             case unary_operator::dereference: |             case unary_operator::dereference: | ||||||
|                 auto operand_type = expression->operand().data_type; |                 auto operand_type = expression->operand().data_type; | ||||||
| 
 | 
 | ||||||
|                 if (auto referenced_type = std::dynamic_pointer_cast<const pointer_type>(operand_type)) |                 if (operand_type->is_pointer_type() != nullptr) | ||||||
|                 { |                 { | ||||||
|                     expression->data_type = referenced_type; |                     expression->data_type = operand_type; | ||||||
|                 } |                 } | ||||||
|                 else if (operand_type != nullptr) |                 else if (operand_type != nullptr) | ||||||
|                 { |                 { | ||||||
| @@ -217,18 +215,16 @@ namespace elna::source | |||||||
|             case binary_operator::greater_equal: |             case binary_operator::greater_equal: | ||||||
|                 if (expression->lhs().data_type != nullptr && expression->rhs().data_type != nullptr) |                 if (expression->lhs().data_type != nullptr && expression->rhs().data_type != nullptr) | ||||||
|                 { |                 { | ||||||
|                     auto lhs_type = std::dynamic_pointer_cast<const primitive_type>(expression->lhs().data_type); |  | ||||||
|                     auto rhs_type = std::dynamic_pointer_cast<const primitive_type>(expression->rhs().data_type); |  | ||||||
| 
 |  | ||||||
|                     std::unique_ptr<type_mismatch> new_error; |                     std::unique_ptr<type_mismatch> new_error; | ||||||
|                     if (lhs_type == nullptr || *lhs_type != int_type) | 
 | ||||||
|  |                     if (*expression->lhs().data_type != int_type) | ||||||
|                     { |                     { | ||||||
|                         new_error = std::make_unique<type_mismatch>(lhs_type, |                         new_error = std::make_unique<type_mismatch>(expression->lhs().data_type, | ||||||
|                                 type_mismatch::operation::arithmetic, this->filename, expression->lhs().position()); |                                 type_mismatch::operation::arithmetic, this->filename, expression->lhs().position()); | ||||||
|                     } |                     } | ||||||
|                     if (rhs_type == nullptr || *rhs_type != int_type) |                     if (*expression->rhs().data_type != int_type) | ||||||
|                     { |                     { | ||||||
|                         new_error = std::make_unique<type_mismatch>(rhs_type, |                         new_error = std::make_unique<type_mismatch>(expression->rhs().data_type, | ||||||
|                                 type_mismatch::operation::arithmetic, this->filename, expression->rhs().position()); |                                 type_mismatch::operation::arithmetic, this->filename, expression->rhs().position()); | ||||||
|                     } |                     } | ||||||
|                     if (new_error != nullptr) |                     if (new_error != nullptr) | ||||||
| @@ -253,7 +249,7 @@ namespace elna::source | |||||||
| 
 | 
 | ||||||
|     void type_analysis_visitor::visit(call_statement *statement) |     void type_analysis_visitor::visit(call_statement *statement) | ||||||
|     { |     { | ||||||
|         auto call_info = std::dynamic_pointer_cast<intrinsic_info>(this->table->lookup(statement->name())); |         auto call_info = this->table->lookup(statement->name())->is_intrinsic_info(); | ||||||
| 
 | 
 | ||||||
|         std::size_t i{ 0 }; |         std::size_t i{ 0 }; | ||||||
|         for (const auto& argument : statement->arguments()) |         for (const auto& argument : statement->arguments()) | ||||||
| @@ -280,7 +276,7 @@ namespace elna::source | |||||||
|     void type_analysis_visitor::visit(while_statement *statement) |     void type_analysis_visitor::visit(while_statement *statement) | ||||||
|     { |     { | ||||||
|         statement->prerequisite().accept(this); |         statement->prerequisite().accept(this); | ||||||
|         auto condition_type = std::dynamic_pointer_cast<const primitive_type>(statement->prerequisite().data_type); |         auto condition_type = statement->prerequisite().data_type; | ||||||
| 
 | 
 | ||||||
|         if (condition_type != nullptr && *condition_type != boolean_type) |         if (condition_type != nullptr && *condition_type != boolean_type) | ||||||
|         { |         { | ||||||
| @@ -294,7 +290,7 @@ namespace elna::source | |||||||
|     void type_analysis_visitor::visit(if_statement *statement) |     void type_analysis_visitor::visit(if_statement *statement) | ||||||
|     { |     { | ||||||
|         statement->prerequisite().accept(this); |         statement->prerequisite().accept(this); | ||||||
|         auto condition_type = std::dynamic_pointer_cast<const primitive_type>(statement->prerequisite().data_type); |         auto condition_type = statement->prerequisite().data_type; | ||||||
| 
 | 
 | ||||||
|         if (condition_type != nullptr && *condition_type != boolean_type) |         if (condition_type != nullptr && *condition_type != boolean_type) | ||||||
|         { |         { | ||||||
| @@ -308,7 +304,7 @@ namespace elna::source | |||||||
|     void type_analysis_visitor::visit(assign_statement *statement) |     void type_analysis_visitor::visit(assign_statement *statement) | ||||||
|     { |     { | ||||||
|         statement->rvalue().accept(this); |         statement->rvalue().accept(this); | ||||||
|         auto lvalue_info = std::dynamic_pointer_cast<typed_info>(this->table->lookup(statement->lvalue())); |         auto lvalue_info = this->table->lookup(statement->lvalue())->is_typed_info(); | ||||||
| 
 | 
 | ||||||
|         if (statement->rvalue().data_type != nullptr && lvalue_info->type() == statement->rvalue().data_type) |         if (statement->rvalue().data_type != nullptr && lvalue_info->type() == statement->rvalue().data_type) | ||||||
|         { |         { | ||||||
| @@ -323,3 +319,4 @@ namespace elna::source | |||||||
|         return m_errors; |         return m_errors; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | } | ||||||
							
								
								
									
										230
									
								
								source/symbol_table.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								source/symbol_table.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,230 @@ | |||||||
|  | #include "elna/source/types.h" | ||||||
|  | #include "elna/source/symbol_table.h" | ||||||
|  |  | ||||||
|  | namespace elna | ||||||
|  | { | ||||||
|  | namespace source | ||||||
|  | { | ||||||
|  |     symbol_table::symbol_table(std::shared_ptr<symbol_table> scope) | ||||||
|  |         : outer_scope(scope) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::shared_ptr<info> symbol_table::lookup(const std::string& name) | ||||||
|  |     { | ||||||
|  |         auto entry = entries.find(name); | ||||||
|  |  | ||||||
|  |         if (entry != entries.cend()) | ||||||
|  |         { | ||||||
|  |             return entry->second; | ||||||
|  |         } | ||||||
|  |         if (this->outer_scope != nullptr) | ||||||
|  |         { | ||||||
|  |             return this->outer_scope->lookup(name); | ||||||
|  |         } | ||||||
|  |         return nullptr; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void symbol_table::enter(const std::string& name, std::shared_ptr<info> entry) | ||||||
|  |     { | ||||||
|  |         entries.insert({ name, entry }); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::shared_ptr<symbol_table> symbol_table::scope() | ||||||
|  |     { | ||||||
|  |         return this->outer_scope; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     info::~info() | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     type_info *info::is_type_info() noexcept | ||||||
|  |     { | ||||||
|  |         return nullptr; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     typed_info *info::is_typed_info() noexcept | ||||||
|  |     { | ||||||
|  |         return nullptr; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     constant_info *info::is_constant_info() noexcept | ||||||
|  |     { | ||||||
|  |         return nullptr; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variable_info *info::is_variable_info() noexcept | ||||||
|  |     { | ||||||
|  |         return nullptr; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     parameter_info *info::is_parameter_info() noexcept | ||||||
|  |     { | ||||||
|  |         return nullptr; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     intrinsic_info *info::is_intrinsic_info() noexcept | ||||||
|  |     { | ||||||
|  |         return nullptr; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     procedure_info *info::is_procedure_info() noexcept | ||||||
|  |     { | ||||||
|  |         return nullptr; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     info::info() | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     type_info::type_info(std::shared_ptr<class type> type) | ||||||
|  |         : info(), m_type(type) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     type_info::~type_info() | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::shared_ptr<const class type> type_info::type() const noexcept | ||||||
|  |     { | ||||||
|  |         return m_type; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     type_info *type_info::is_type_info() noexcept | ||||||
|  |     { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     typed_info::typed_info(std::shared_ptr<const class type> type) | ||||||
|  |         : m_type(type) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     typed_info::~typed_info() | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     typed_info *typed_info::is_typed_info() noexcept | ||||||
|  |     { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::shared_ptr<const class type> typed_info::type() const noexcept | ||||||
|  |     { | ||||||
|  |         return m_type; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     constant_info::constant_info(const std::shared_ptr<const class type> type, const std::int32_t value) | ||||||
|  |         : typed_info(type), m_value(value) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     constant_info *constant_info::is_constant_info() noexcept | ||||||
|  |     { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::int32_t constant_info::value() const noexcept | ||||||
|  |     { | ||||||
|  |         return m_value; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variable_info::variable_info(std::shared_ptr<const class type> type) | ||||||
|  |         : typed_info(type) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variable_info *variable_info::is_variable_info() noexcept | ||||||
|  |     { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     parameter_info::parameter_info(std::shared_ptr<const class type> type) | ||||||
|  |         : typed_info(type) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     parameter_info *parameter_info::is_parameter_info() noexcept | ||||||
|  |     { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     intrinsic_info::intrinsic_info(const class procedure_type& type) | ||||||
|  |         : m_type(std::make_shared<procedure_type>(type)) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     intrinsic_info::~intrinsic_info() | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::shared_ptr<const class procedure_type> intrinsic_info::type() const noexcept | ||||||
|  |     { | ||||||
|  |         return m_type; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::size_t intrinsic_info::parameter_stack_size() const noexcept | ||||||
|  |     { | ||||||
|  |         return type()->arguments.size() * sizeof(std::int32_t); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     intrinsic_info *intrinsic_info::is_intrinsic_info() noexcept | ||||||
|  |     { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     procedure_info::procedure_info(const class procedure_type& type, std::shared_ptr<symbol_table> outer_scope) | ||||||
|  |         : intrinsic_info(type), local_table(std::make_shared<symbol_table>(outer_scope)) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     procedure_info::~procedure_info() | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::shared_ptr<symbol_table> procedure_info::scope() | ||||||
|  |     { | ||||||
|  |         return local_table; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::size_t procedure_info::stack_size() const noexcept | ||||||
|  |     { | ||||||
|  |         return local_stack_size + argument_stack_size; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     procedure_info *procedure_info::is_procedure_info() noexcept | ||||||
|  |     { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     constexpr std::size_t pointer_size = 4; | ||||||
|  |  | ||||||
|  |     std::shared_ptr<source::symbol_table> add_builtin_symbols() | ||||||
|  |     { | ||||||
|  |         source::symbol_table result; | ||||||
|  |         std::vector<std::shared_ptr<const source::type>> intrinsic_arguments; | ||||||
|  |  | ||||||
|  |         auto prim = boolean_type; | ||||||
|  |         auto boolean_info = std::make_shared<type_info>(std::make_shared<primitive_type>(boolean_type)); | ||||||
|  |         auto int_info = std::make_shared<source::type_info>(std::make_shared<primitive_type>(int_type)); | ||||||
|  |         result.enter("Boolean", boolean_info); | ||||||
|  |         result.enter("Int", int_info); | ||||||
|  |  | ||||||
|  |         intrinsic_arguments.push_back(int_info->type()); | ||||||
|  |         auto writei = std::make_shared<source::intrinsic_info>( | ||||||
|  |                 source::procedure_type{ intrinsic_arguments, pointer_size }); | ||||||
|  |         result.enter("writei", writei); | ||||||
|  |         intrinsic_arguments.clear(); | ||||||
|  |  | ||||||
|  |         intrinsic_arguments.push_back(boolean_info->type()); | ||||||
|  |         auto writeb = std::make_shared<source::intrinsic_info>( | ||||||
|  |                 source::procedure_type{ intrinsic_arguments, pointer_size }); | ||||||
|  |         result.enter("writeb", writeb); | ||||||
|  |         intrinsic_arguments.clear(); | ||||||
|  |  | ||||||
|  |         return std::make_shared<source::symbol_table>(std::move(result)); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | } | ||||||
| @@ -1,129 +0,0 @@ | |||||||
| #include "elna/source/types.hpp" |  | ||||||
| #include "elna/source/symbol_table.hpp" |  | ||||||
|  |  | ||||||
| namespace elna::source |  | ||||||
| { |  | ||||||
|     symbol_table::symbol_table(std::shared_ptr<symbol_table> scope) |  | ||||||
|         : outer_scope(scope) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     std::shared_ptr<info> symbol_table::lookup(const std::string& name) |  | ||||||
|     { |  | ||||||
|         auto entry = entries.find(name); |  | ||||||
|  |  | ||||||
|         if (entry != entries.cend()) |  | ||||||
|         { |  | ||||||
|             return entry->second; |  | ||||||
|         } |  | ||||||
|         if (this->outer_scope != nullptr) |  | ||||||
|         { |  | ||||||
|             return this->outer_scope->lookup(name); |  | ||||||
|         } |  | ||||||
|         return nullptr; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void symbol_table::enter(const std::string& name, std::shared_ptr<info> entry) |  | ||||||
|     { |  | ||||||
|         entries.insert_or_assign(name, entry); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     std::shared_ptr<symbol_table> symbol_table::scope() |  | ||||||
|     { |  | ||||||
|         return this->outer_scope; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     info::~info() |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     info::info() |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     type_info::type_info(const class type& type) |  | ||||||
|         : info(), m_type(std::make_shared<class type>(type)) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     type_info::~type_info() |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     std::shared_ptr<const class type> type_info::type() const noexcept |  | ||||||
|     { |  | ||||||
|         return m_type; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     typed_info::typed_info(std::shared_ptr<const class type> type) |  | ||||||
|         : m_type(type) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     typed_info::~typed_info() |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     std::shared_ptr<const class type> typed_info::type() const noexcept |  | ||||||
|     { |  | ||||||
|         return m_type; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     constant_info::constant_info(const std::shared_ptr<const class type> type, const std::int32_t value) |  | ||||||
|         : typed_info(type), m_value(value) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     std::int32_t constant_info::value() const noexcept |  | ||||||
|     { |  | ||||||
|         return m_value; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     variable_info::variable_info(std::shared_ptr<const class type> type) |  | ||||||
|         : typed_info(type) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     parameter_info::parameter_info(std::shared_ptr<const class type> type) |  | ||||||
|         : typed_info(type) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     intrinsic_info::intrinsic_info(const class procedure_type& type) |  | ||||||
|         : m_type(std::make_shared<procedure_type>(type)) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     intrinsic_info::~intrinsic_info() |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     std::shared_ptr<const class procedure_type> intrinsic_info::type() const noexcept |  | ||||||
|     { |  | ||||||
|         return m_type; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     std::size_t intrinsic_info::parameter_stack_size() const noexcept |  | ||||||
|     { |  | ||||||
|         return type()->arguments.size() * sizeof(std::int32_t); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     procedure_info::procedure_info(const class procedure_type& type, std::shared_ptr<symbol_table> outer_scope) |  | ||||||
|         : intrinsic_info(type), local_table(std::make_shared<symbol_table>(outer_scope)) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     procedure_info::~procedure_info() |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     std::shared_ptr<symbol_table> procedure_info::scope() |  | ||||||
|     { |  | ||||||
|         return local_table; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     std::size_t procedure_info::stack_size() const noexcept |  | ||||||
|     { |  | ||||||
|         return local_stack_size + argument_stack_size; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
							
								
								
									
										80
									
								
								source/types.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								source/types.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | |||||||
|  | #include <elna/source/types.h> | ||||||
|  |  | ||||||
|  | namespace elna | ||||||
|  | { | ||||||
|  | namespace source | ||||||
|  | { | ||||||
|  |     type::type(const std::size_t byte_size) | ||||||
|  |         : byte_size(byte_size) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::size_t type::size() const noexcept | ||||||
|  |     { | ||||||
|  |         return this->byte_size; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const pointer_type *type::is_pointer_type() const | ||||||
|  |     { | ||||||
|  |         return nullptr; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     primitive_type::primitive_type(const std::string& type_name, const std::size_t byte_size) | ||||||
|  |         : type(byte_size), m_type_name(type_name) | ||||||
|  |    { | ||||||
|  |    } | ||||||
|  |  | ||||||
|  |     std::string primitive_type::type_name() const | ||||||
|  |     { | ||||||
|  |         return m_type_name; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pointer_type::pointer_type(std::shared_ptr<const type> base_type, const std::size_t byte_size) | ||||||
|  |         : type(byte_size), base_type(base_type) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const pointer_type *pointer_type::is_pointer_type() const | ||||||
|  |     { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::string pointer_type::type_name() const | ||||||
|  |     { | ||||||
|  |         return '^' + base_type->type_name(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     procedure_type::procedure_type(std::vector<std::shared_ptr<const type>> arguments, const std::size_t byte_size) | ||||||
|  |         : arguments(std::move(arguments)), type(byte_size) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::string procedure_type::type_name() const | ||||||
|  |     { | ||||||
|  |         std::string result{ "proc(" }; | ||||||
|  |         for (const auto& argument : arguments) | ||||||
|  |         { | ||||||
|  |             result += argument->type_name() + ','; | ||||||
|  |         } | ||||||
|  |         result.at(result.size() - 1) = ')'; | ||||||
|  |  | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     bool operator==(const type& lhs, const type& rhs) noexcept | ||||||
|  |     { | ||||||
|  |         auto lhs_type = lhs.type_name(); | ||||||
|  |         auto rhs_type = rhs.type_name(); | ||||||
|  |  | ||||||
|  |         return lhs_type == rhs_type; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     bool operator!=(const type& lhs, const type& rhs) noexcept | ||||||
|  |     { | ||||||
|  |         return !(lhs == rhs); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const primitive_type boolean_type{ "Boolean", 1 }; | ||||||
|  |     const primitive_type int_type{ "Int", 4 }; | ||||||
|  | } | ||||||
|  | } | ||||||
| @@ -1,96 +0,0 @@ | |||||||
| #include <elna/source/types.hpp> |  | ||||||
|  |  | ||||||
| namespace elna::source |  | ||||||
| { |  | ||||||
|     type::type(const std::size_t byte_size) |  | ||||||
|         : byte_size(byte_size) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     std::size_t type::size() const noexcept |  | ||||||
|     { |  | ||||||
|         return this->byte_size; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     primitive_type::primitive_type(const std::string& type_name, const std::size_t byte_size) |  | ||||||
|         : type(byte_size), type_name(type_name) |  | ||||||
|    { |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|     bool primitive_type::operator==(const primitive_type& that) const noexcept |  | ||||||
|     { |  | ||||||
|         return this->type_name == that.type_name; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool primitive_type::operator!=(const primitive_type& that) const noexcept |  | ||||||
|     { |  | ||||||
|         return this->type_name != that.type_name; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     pointer_type::pointer_type(std::shared_ptr<const type> base_type, const std::size_t byte_size) |  | ||||||
|         : type(byte_size), base_type(base_type) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool pointer_type::operator==(const pointer_type& that) const noexcept |  | ||||||
|     { |  | ||||||
|         return this->base_type == that.base_type; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool pointer_type::operator!=(const pointer_type& that) const noexcept |  | ||||||
|     { |  | ||||||
|         return this->base_type != that.base_type; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     procedure_type::procedure_type(std::vector<std::shared_ptr<const type>> arguments, const std::size_t byte_size) |  | ||||||
|         : arguments(std::move(arguments)), type(byte_size) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool procedure_type::operator==(const procedure_type &that) const noexcept |  | ||||||
|     { |  | ||||||
|         return this->arguments == that.arguments; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool procedure_type::operator!=(const procedure_type &that) const noexcept |  | ||||||
|     { |  | ||||||
|         return this->arguments != that.arguments; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool operator==(const type& lhs, const type& rhs) noexcept |  | ||||||
|     { |  | ||||||
|         { |  | ||||||
|             auto lhs_type = dynamic_cast<const primitive_type *>(&lhs); |  | ||||||
|             auto rhs_type = dynamic_cast<const primitive_type *>(&rhs); |  | ||||||
|  |  | ||||||
|             if (lhs_type != nullptr && rhs_type != nullptr) |  | ||||||
|             { |  | ||||||
|                 return *lhs_type == *rhs_type; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         { |  | ||||||
|             auto lhs_type = dynamic_cast<const pointer_type *>(&lhs); |  | ||||||
|             auto rhs_type = dynamic_cast<const pointer_type *>(&rhs); |  | ||||||
|  |  | ||||||
|             if (lhs_type != nullptr && rhs_type != nullptr) |  | ||||||
|             { |  | ||||||
|                 return *lhs_type == *rhs_type; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         { |  | ||||||
|             auto lhs_type = dynamic_cast<const procedure_type *>(&lhs); |  | ||||||
|             auto rhs_type = dynamic_cast<const procedure_type *>(&rhs); |  | ||||||
|  |  | ||||||
|             if (lhs_type != nullptr && rhs_type != nullptr) |  | ||||||
|             { |  | ||||||
|                 return *lhs_type == *rhs_type; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool operator!=(const type& lhs, const type& rhs) noexcept |  | ||||||
|     { |  | ||||||
|         return !(lhs == rhs); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
		Reference in New Issue
	
	Block a user