Add semantic passes
This commit is contained in:
parent
f080b75c52
commit
40306ac986
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user