diff --git a/.gitignore b/.gitignore index 69e119b13c3a4684fae34e56b8eda332a0db3a30..98b4e68d36d6a718e9c19e986779544089e5f0bf 100644 --- a/.gitignore +++ b/.gitignore @@ -134,3 +134,5 @@ Makefile *.bc *.s src/yacc_stuff/tokenizer.cpp +config.guess~ +config.sub~ diff --git a/.vscode/settings.json b/.vscode/settings.json index 6d68035cdb5a9faf5dc3959684e90bde661d692a..6a03129a3ba7f7ac318f2d00fa072ec5b13e2087 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -18,6 +18,73 @@ "*.inc": "cpp", "deque": "cpp", "string": "cpp", - "vector": "cpp" + "vector": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "csetjmp": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "strstream": "cpp", + "bit": "cpp", + "bitset": "cpp", + "cfenv": "cpp", + "charconv": "cpp", + "chrono": "cpp", + "cinttypes": "cpp", + "codecvt": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "cstdint": "cpp", + "cuchar": "cpp", + "forward_list": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "string_view": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "scoped_allocator": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "valarray": "cpp", + "variant": "cpp", + "compare": "cpp", + "concepts": "cpp", + "numbers": "cpp", + "ranges": "cpp", + "span": "cpp", + "stop_token": "cpp" } } \ No newline at end of file diff --git a/config.h.in~ b/config.h.in~ index e2993a5e4a460ca4ec793365c992529b5a6fa859..06b702338705227c595d9eca7d5ff3dac204365c 100644 --- a/config.h.in~ +++ b/config.h.in~ @@ -1,5 +1,8 @@ /* config.h.in. Generated from configure.ac by autoheader. */ +/* define if the compiler supports basic C++17 syntax */ +#undef HAVE_CXX17 + /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H @@ -51,6 +54,9 @@ /* Define to 1 if the system has the type `_Bool'. */ #undef HAVE__BOOL +/* Name of package */ +#undef PACKAGE + /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT @@ -74,6 +80,9 @@ backward compatibility; new code need not use it. */ #undef STDC_HEADERS +/* Version number of package */ +#undef VERSION + /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a `char[]'. */ #undef YYTEXT_POINTER diff --git a/configure.ac b/configure.ac index 3b4eb5de4d6ea30227ff6fde4774f23030ea0f9d..dc5d0eb03225375ad3383de7cf6658f963bd093a 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,7 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. +AC_CONFIG_MACRO_DIR([m4]) AC_PREREQ([2.69]) AC_INIT([AloLang Compiler], [Dev Beta], [https://github.com/XJTU-Youth/AloLang-Dev/issues]) @@ -49,5 +50,8 @@ AC_CONFIG_FILES([ src/lib/Makefile ]) +AX_CXX_COMPILE_STDCXX(17, [noext], [mandatory]) + AM_INIT_AUTOMAKE +LT_INIT AC_OUTPUT diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4 new file mode 100644 index 0000000000000000000000000000000000000000..db7638c50aa005ddd814d2e86735d93379c2c484 --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx.m4 @@ -0,0 +1,962 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) +# or '14' (for the C++14 standard). +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for no added switch, and then for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016, 2018 Krzesimir Nowak +# Copyright (c) 2019 Enji Cooper +# Copyright (c) 2020 Jason Merrill +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 12 + +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). + +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], + [$1], [14], [ax_cxx_compile_alternatives="14 1y"], + [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + + m4_if([$2], [], [dnl + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then + ac_success=yes + fi]) + + m4_if([$2], [noext], [], [dnl + if test x$ac_success = xno; then + for alternative in ${ax_cxx_compile_alternatives}; do + switch="-std=gnu++${alternative}" + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [], [dnl + if test x$ac_success = xno; then + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + for alternative in ${ax_cxx_compile_alternatives}; do + for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + if test x$ac_success = xyes; then + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + AC_SUBST(HAVE_CXX$1) +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 +) + + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 +) + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 +) + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual ~Base() {} + virtual void f() {} + }; + + struct Derived : public Base + { + virtual ~Derived() override {} + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) + + +dnl Tests for new features in C++17 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ + +// If the compiler admits that it is not ready for C++17, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201703L + +#error "This is not a C++17 compiler" + +#else + +#include +#include +#include + +namespace cxx17 +{ + + namespace test_constexpr_lambdas + { + + constexpr int foo = [](){return 42;}(); + + } + + namespace test::nested_namespace::definitions + { + + } + + namespace test_fold_expression + { + + template + int multiply(Args... args) + { + return (args * ... * 1); + } + + template + bool all(Args... args) + { + return (args && ...); + } + + } + + namespace test_extended_static_assert + { + + static_assert (true); + + } + + namespace test_auto_brace_init_list + { + + auto foo = {5}; + auto bar {5}; + + static_assert(std::is_same, decltype(foo)>::value); + static_assert(std::is_same::value); + } + + namespace test_typename_in_template_template_parameter + { + + template typename X> struct D; + + } + + namespace test_fallthrough_nodiscard_maybe_unused_attributes + { + + int f1() + { + return 42; + } + + [[nodiscard]] int f2() + { + [[maybe_unused]] auto unused = f1(); + + switch (f1()) + { + case 17: + f1(); + [[fallthrough]]; + case 42: + f1(); + } + return f1(); + } + + } + + namespace test_extended_aggregate_initialization + { + + struct base1 + { + int b1, b2 = 42; + }; + + struct base2 + { + base2() { + b3 = 42; + } + int b3; + }; + + struct derived : base1, base2 + { + int d; + }; + + derived d1 {{1, 2}, {}, 4}; // full initialization + derived d2 {{}, {}, 4}; // value-initialized bases + + } + + namespace test_general_range_based_for_loop + { + + struct iter + { + int i; + + int& operator* () + { + return i; + } + + const int& operator* () const + { + return i; + } + + iter& operator++() + { + ++i; + return *this; + } + }; + + struct sentinel + { + int i; + }; + + bool operator== (const iter& i, const sentinel& s) + { + return i.i == s.i; + } + + bool operator!= (const iter& i, const sentinel& s) + { + return !(i == s); + } + + struct range + { + iter begin() const + { + return {0}; + } + + sentinel end() const + { + return {5}; + } + }; + + void f() + { + range r {}; + + for (auto i : r) + { + [[maybe_unused]] auto v = i; + } + } + + } + + namespace test_lambda_capture_asterisk_this_by_value + { + + struct t + { + int i; + int foo() + { + return [*this]() + { + return i; + }(); + } + }; + + } + + namespace test_enum_class_construction + { + + enum class byte : unsigned char + {}; + + byte foo {42}; + + } + + namespace test_constexpr_if + { + + template + int f () + { + if constexpr(cond) + { + return 13; + } + else + { + return 42; + } + } + + } + + namespace test_selection_statement_with_initializer + { + + int f() + { + return 13; + } + + int f2() + { + if (auto i = f(); i > 0) + { + return 3; + } + + switch (auto i = f(); i + 4) + { + case 17: + return 2; + + default: + return 1; + } + } + + } + + namespace test_template_argument_deduction_for_class_templates + { + + template + struct pair + { + pair (T1 p1, T2 p2) + : m1 {p1}, + m2 {p2} + {} + + T1 m1; + T2 m2; + }; + + void f() + { + [[maybe_unused]] auto p = pair{13, 42u}; + } + + } + + namespace test_non_type_auto_template_parameters + { + + template + struct B + {}; + + B<5> b1; + B<'a'> b2; + + } + + namespace test_structured_bindings + { + + int arr[2] = { 1, 2 }; + std::pair pr = { 1, 2 }; + + auto f1() -> int(&)[2] + { + return arr; + } + + auto f2() -> std::pair& + { + return pr; + } + + struct S + { + int x1 : 2; + volatile double y1; + }; + + S f3() + { + return {}; + } + + auto [ x1, y1 ] = f1(); + auto& [ xr1, yr1 ] = f1(); + auto [ x2, y2 ] = f2(); + auto& [ xr2, yr2 ] = f2(); + const auto [ x3, y3 ] = f3(); + + } + + namespace test_exception_spec_type_system + { + + struct Good {}; + struct Bad {}; + + void g1() noexcept; + void g2(); + + template + Bad + f(T*, T*); + + template + Good + f(T1*, T2*); + + static_assert (std::is_same_v); + + } + + namespace test_inline_variables + { + + template void f(T) + {} + + template inline T g(T) + { + return T{}; + } + + template<> inline void f<>(int) + {} + + template<> int g<>(int) + { + return 5; + } + + } + +} // namespace cxx17 + +#endif // __cplusplus < 201703L + +]]) \ No newline at end of file diff --git a/src/CompileError.hpp b/src/CompileError.hpp index 5e3da65e917dfb3e3c73a7c3f18672f2469b5a4d..1444486e3e147a1ec3e5242adc20e96e93246964 100644 --- a/src/CompileError.hpp +++ b/src/CompileError.hpp @@ -1,6 +1,7 @@ // compileerror.hpp header for CompileError exeption class #ifndef _COMPILE_ERROR_ #define _COMPILE_ERROR_ +#include "TokenSource.h" #include #include @@ -9,26 +10,26 @@ class CompileError : public std::exception private: std::string error; std::string message; - std::string file; - uint64_t line; + TokenSource source; public: const char *what() const throw() { return message.c_str(); } - CompileError(const char *whatError, std::string whatFile = "", - uint64_t whatLine = 0) + CompileError(const char *whatError, + TokenSource source = TokenSource("", 0)) { - error = whatError; - file = whatFile; - line = whatLine; - message = file + ":" + std::to_string(line) + ": " + error; + error = whatError; + this->source = source; + message = + source.file + ":" + std::to_string(source.lineno) + ": " + error; } - CompileError(const std::string &whatError, std::string whatFile = "", - uint64_t whatLine = 0) + + CompileError(const std::string &whatError, + TokenSource source = TokenSource("", 0)) { - error = whatError; - file = whatFile; - line = whatLine; - message = file + ":" + std::to_string(line) + ": " + error; + error = whatError; + this->source = source; + message = + source.file + ":" + std::to_string(source.lineno) + ": " + error; } }; #endif diff --git a/src/CompileUnit.cpp b/src/CompileUnit.cpp index de656c64d4af5cc2e642ecd0e7930e8c6f7668e7..2e78095758b0d02a1750c1a7d0656dc953bacc22 100644 --- a/src/CompileUnit.cpp +++ b/src/CompileUnit.cpp @@ -33,6 +33,8 @@ void initInnerType(CompileUnit *unit) "double", llvm::Type::getDoubleTy(*unit->context))); unit->types.insert(std::pair( "bool", llvm::Type::getInt1Ty(*unit->context))); + unit->types.insert(std::pair( + "char", llvm::Type::getInt32Ty(*unit->context))); } void initInnerOperations(CompileUnit *unit) @@ -89,6 +91,17 @@ void initInnerOperations(CompileUnit *unit) std::pair>( {"int", "int", "=="}, std::pair( nullptr, new TypeAST(unit, "bool")))); + + unit->binOperators.insert(std::pair, + std::pair>( + {"int", "int", ">>"}, std::pair( + nullptr, new TypeAST(unit, "int")))); + + unit->binOperators.insert(std::pair, + std::pair>( + {"int", "int", "<<"}, std::pair( + nullptr, new TypeAST(unit, "int")))); + // double unit->binOperators.insert(std::pair, std::pair>( @@ -109,6 +122,11 @@ void initInnerOperations(CompileUnit *unit) {"double", "double", "/"}, std::pair( nullptr, new TypeAST(unit, "double")))); + unit->binOperators.insert(std::pair, + std::pair>( + {"double", "double", "%"}, std::pair( + nullptr, new TypeAST(unit, "double")))); + unit->binOperators.insert(std::pair, std::pair>( {"double", "double", ">"}, std::pair( @@ -149,8 +167,7 @@ void scanToken(CompileUnit *unit) while (1) { int tokenid = lexer->yylex(); token.type = TokenType(tokenid); - token.file = line.first.first; - token.lineno = line.first.second; + token.source = line.first; token.tokenValue = lexer->YYText(); // Deal with numbers if (token.type == tok_number) { @@ -217,8 +234,7 @@ void CompileUnit::compile() switch (icurTok->type) { case tok_fun: { FunctionAST *func_ast = FunctionAST::ParseFunction(this); - functions.insert(std::pair( - func_ast->getDemangledName(), func_ast)); + functions.push_back(func_ast); // llvm::Function *func = func_ast->Codegen(); /*llvm::Type* type=llvm::FunctionType::get(llvm::Type::getVoidTy(*context), @@ -234,8 +250,7 @@ void CompileUnit::compile() } case tok_extern: { ExternAST *externast = ExternAST::ParseExtern(this); - externs.insert(std::pair( - externast->getDemangledName(), externast)); + functions.push_back(externast); break; } case tok_identifier: { @@ -243,19 +258,18 @@ void CompileUnit::compile() VariableDefExprAST *var = VariableDefExprAST::ParseVar(this, nullptr); Token token = next_tok(); - globalVariables.insert( - std::pair(var->idName, var)); + globalVariables.push_back(var); break; } case tok_key_class: { ClassAST *classAST = ClassAST::ParseClass(this); classes.insert(std::pair( classAST->className, classAST)); - classesO.push_back(classAST); break; } default: { - CompileError e("unexpected token:" + icurTok->dump()); + CompileError e("unexpected token:" + icurTok->dump(), + icurTok->source); throw e; } } @@ -265,20 +279,26 @@ void CompileUnit::compile() llvm::Type *classType = classAST->Codegen(); }*/ - std::map::iterator gVar_iter; - for (gVar_iter = globalVariables.begin(); - gVar_iter != globalVariables.end(); gVar_iter++) { - gVar_iter->second->Codegen(nullptr); + for (VariableDefExprAST *v : globalVariables) { + v->Codegen(nullptr); //自动插入globalVariablesValue } std::map::iterator extern_iter; - for (extern_iter = externs.begin(); extern_iter != externs.end(); - extern_iter++) { - extern_iter->second->Codegen(); - } - std::map::iterator function_iter; - for (function_iter = functions.begin(); function_iter != functions.end(); - function_iter++) { - function_iter->second->Codegen(); + for (BaseAST *func : functions) { + if (ExternAST *v = dynamic_cast(func)) { + llvm::Function *f = v->Codegen(); + globalFunctions.insert( + std::pair>( + f->getName(), + std::pair(v->proto, f))); + + } else if (FunctionAST *v = dynamic_cast(func)) { + llvm::Function *f = v->Codegen(); //自动插入globalFunctions + + } else { + CompileError e("Unknown internal error."); + throw e; + } } build(); diff --git a/src/CompileUnit.h b/src/CompileUnit.h index 7c620ab9ca54e2c3e86c21de5072479bb94cde46..b852f6225f4a5023306fe811cad7f29f1a5e6ba8 100644 --- a/src/CompileUnit.h +++ b/src/CompileUnit.h @@ -17,10 +17,10 @@ #include class TypeAST; -class FunctionAST; -class ExternAST; +class BaseAST; class VariableDefExprAST; class ClassAST; +class PrototypeAST; class CompileUnit { public: @@ -30,23 +30,23 @@ class CompileUnit Token next_tok(); void build(); - std::string name; - std::vector srclines; - llvm::LLVMContext * context; - llvm::Module * module; - std::vector tokenList; - std::vector::iterator icurTok; - std::map classes; - std::vector classesO; - std::map globalVariables; - std::vector globalVariablesO; - std::map functions; - std::map externs; + std::string name; + std::vector srclines; + llvm::LLVMContext * context; + llvm::Module * module; + std::vector tokenList; + std::vector::iterator icurTok; + std::map classes; + std::vector globalVariables; + std::vector functions; //泛指function(包括extern) + std::map, std::pair> binOperators; // LHS type,RHS type,binOP std::map types; // Codgen用 std::map> globalVariablesValue; // Codgen用 + std::map> + globalFunctions; // Codegen用 }; #endif /* COMPILER_COMPILEUNIT_H_ */ diff --git a/src/Makefile.am b/src/Makefile.am index 325ae091924fc5f4fc560a65acadf56cb8eb82d3..7205c3667aa0e730f119c89acbf1179c8e79bd76 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,7 +5,7 @@ aloc_SOURCES = aloc.cpp CompileUnit.cpp preprocessor.cpp Token.cpp utils.cpp\ ast/CallExprAST.cpp ast/ClassAST.cpp ast/CodeBlockAST.cpp ast/DoubleExprAST.cpp ast/EmptyExprAST.cpp\ ast/ExprAST.cpp ast/ExternAST.cpp ast/FunctionAST.cpp ast/IntExprAST.cpp\ ast/IfExprAST.cpp ast/MemberExprAST.cpp ast/PrototypeAST.cpp\ - ast/ReturnExprAST.cpp ast/TypeAST.cpp ast/VariableDefExprAST.cpp ast/VariableExprAST.cpp\ + ast/ReturnExprAST.cpp ast/SizeofExprAST.cpp ast/StringExprAST.cpp ast/TypeAST.cpp ast/VariableDefExprAST.cpp ast/VariableExprAST.cpp\ ast/WhileExprAST.cpp ast/UnaryExprAST.cpp yacc_stuff/tokenizer.lpp AM_LFLAGS = -o lex.yy.c @@ -17,4 +17,4 @@ includeLLVM := $(shell llvm-config --includedir) aloc_CPPFLAGS = $(cxxflagsLLVM) -I$(includeLLVM) -I$(srcdir) -fexceptions aloc_LDFLAGS = $(ldflagsLLVM) #$(libLLVM) -lboost_program_options -aloc_LDADD = -lLLVM-11 -lboost_program_options \ No newline at end of file +aloc_LDADD = -lLLVM-11 -lboost_program_options -lboost_filesystem -lboost_system \ No newline at end of file diff --git a/src/Token.cpp b/src/Token.cpp index bc963b83ef748cbcf660bce28cd805203de1c544..6433a85d83d19f764400ee48e00589efeb81e2d4 100644 --- a/src/Token.cpp +++ b/src/Token.cpp @@ -13,7 +13,6 @@ Token::Token() { tokenValue = ""; type = tok_err; - lineno = 0; } Token::~Token() @@ -99,8 +98,8 @@ std::string Token::dump() default: typeStr = "not defined"; } - ss << std::right << std::setw(25) << file << ":" << std::left - << std::setw(6) << lineno << " type:" << std::setw(16) << typeStr + ss << std::right << std::setw(25) << source.file << ":" << std::left + << std::setw(6) << source.lineno << " type:" << std::setw(16) << typeStr << " data:" << tokenValue; return ss.str(); } diff --git a/src/Token.h b/src/Token.h index 7943dd79b996258597eee1a554e3260a5f6b9884..55d720aa0195583099b671b0861002f16fe6432e 100644 --- a/src/Token.h +++ b/src/Token.h @@ -8,6 +8,7 @@ #ifndef COMPILER_TOKEN_H_ #define COMPILER_TOKEN_H_ +#include "TokenSource.h" #include enum TokenType { @@ -33,7 +34,8 @@ enum TokenType { tok_key_if, tok_key_while, tok_key_switch, - tok_key_class + tok_key_class, + tok_key_sizeof }; class Token @@ -44,8 +46,7 @@ class Token std::string dump(); TokenType type; std::string tokenValue; - uint64_t lineno; - std::string file; + TokenSource source; }; #endif /* COMPILER_TOKEN_H_ */ diff --git a/src/TokenSource.h b/src/TokenSource.h new file mode 100644 index 0000000000000000000000000000000000000000..af8d81a3a08ef49996e0b5177f471d649ee0bbeb --- /dev/null +++ b/src/TokenSource.h @@ -0,0 +1,22 @@ +/* + * TokenSource.h + * + * Created on: Mar 10, 2021 + * Author: zbc + */ + +#ifndef SRC_TOKENSOURCE_H_ +#define SRC_TOKENSOURCE_H_ + +#include + +struct TokenSource { + std::string file; + uint64_t lineno; + TokenSource(std::string file, uint64_t lineno) : file(file), lineno(lineno) + { + } + TokenSource() : file(""), lineno(0) {} +}; + +#endif /* SRC_TOKENSOURCE_H_ */ diff --git a/src/aloc.cpp b/src/aloc.cpp index b8ee59e8a956abf2e0e2dd8b3ecab8a371db74c1..397ca5c011c4ca88701139480a14b2d50f83eef4 100644 --- a/src/aloc.cpp +++ b/src/aloc.cpp @@ -107,7 +107,9 @@ int main(int argc, char *argv[]) // buff = header + buff; try { preProcessed = preProcess(buff, 0, input_file_name); - // cout << preProcessed; + for (Tline line : preProcessed) { + std::cout << line.second << std::endl; + } // todo:这行代码写的极不规范,尽快修改 CompileUnit(input_file_name, preProcessed).compile(); system(("llc ./" + input_file_name + @@ -126,10 +128,11 @@ int main(int argc, char *argv[]) for (std::string input_file_name : input_file_names) { objs += "./" + input_file_name + ".s "; } - std::string cmdline = "gcc -O0" + objs + + std::string cmdline = "g++ -O0" + objs + (vm.count("static") ? "-static " : "") + " -fPIE -L " + alolanglibdir + - " -l alolangcore" + " -o " + output_file_name; + " -l m -l stdc++ -l alolangcore -std=c++17" + + " -o " + output_file_name; std::cout << "debug info:" << cmdline << std::endl; system(cmdline.c_str()); return 0; diff --git a/src/ast/BaseAST.h b/src/ast/BaseAST.h index 33d4f13f77b92493e0619c89eea9f427c56acd16..a333ab15cd350eeb4e9afcfe06a9ff6a0252b7ec 100644 --- a/src/ast/BaseAST.h +++ b/src/ast/BaseAST.h @@ -15,6 +15,7 @@ class BaseAST BaseAST(CompileUnit *unit); virtual ~BaseAST(); CompileUnit *unit; + TokenSource source; }; #endif /* COMPILER_AST_ASTBASE_H_ */ diff --git a/src/ast/BinaryExprAST.cpp b/src/ast/BinaryExprAST.cpp index 4f5dd4ac9e0f6175a41f261f7f164f1990c5342d..a0a55c26ab7ecc7d381935aeb07e984f91fcedda 100644 --- a/src/ast/BinaryExprAST.cpp +++ b/src/ast/BinaryExprAST.cpp @@ -31,7 +31,7 @@ llvm::Value * BinaryExprAST::processInnerBinaryOperator(llvm::Value *L, llvm::Value *R, llvm::IRBuilder<> *builder) { - if (LHS->type[0]->name == "int" && RHS->type[0]->name == "int") { + if (LHS->type[0]->getName() == "int" && RHS->type[0]->getName() == "int") { if (binOP == "+") { return builder->CreateAdd(L, R); } else if (binOP == "-") { @@ -57,9 +57,13 @@ BinaryExprAST::processInnerBinaryOperator(llvm::Value *L, llvm::Value *R, return builder->CreateICmpSGE(L, R); } else if (binOP == "<=") { return builder->CreateICmpSLE(L, R); + } else if (binOP == "<<") { + return builder->CreateShl(L, R); + } else if (binOP == ">>") { + return builder->CreateLShr(L, R); } - } else if (LHS->type[0]->name == "double" && - RHS->type[0]->name == "double") { + } else if (LHS->type[0]->getName() == "double" && + RHS->type[0]->getName() == "double") { if (binOP == "+") { return builder->CreateFAdd(L, R); } else if (binOP == "-") { @@ -68,6 +72,8 @@ BinaryExprAST::processInnerBinaryOperator(llvm::Value *L, llvm::Value *R, return builder->CreateFMul(L, R); } else if (binOP == "/") { return builder->CreateFDiv(L, R); + } else if (binOP == "%") { + return builder->CreateFRem(L, R); } else if (binOP == "==") { return builder->CreateFCmpOEQ(L, R); } else if (binOP == "!=") { @@ -86,6 +92,7 @@ BinaryExprAST::processInnerBinaryOperator(llvm::Value *L, llvm::Value *R, } std::vector BinaryExprAST::Codegen(llvm::IRBuilder<> *builder) { + type.clear(); std::vector result; if (binOP == "=") { @@ -97,101 +104,28 @@ std::vector BinaryExprAST::Codegen(llvm::IRBuilder<> *builder) curExpr = curExpr->subExpr; } if (RHSV.size() != LHS.size()) { - CompileError e("the length of expression isn't equal."); + CompileError e("the length of expression isn't equal.", source); throw e; } for (unsigned int i = 0; i < LHS.size(); i++) { - ExprAST * curAST = LHS[i]; - std::vector chain; - llvm::Value * pointer; - bool pointerFlag; - if (UnaryExprAST *v = dynamic_cast(curAST)) { - if (v->op != "*") { - CompileError e("Operator " + v->op + - " can not be used as assignment"); - throw e; - } else { - pointer = v->operand->Codegen(builder)[0]; - } - } else { - while (true) { - chain.push_back(curAST); - if (MemberExprAST *v = - dynamic_cast(curAST)) { - if (v->isPointer) { - pointerFlag = true; - chain.push_back(v->LHS); - break; - } - curAST = v->LHS; - } else if (VariableExprAST *v = - dynamic_cast(curAST)) { - pointerFlag = false; - break; - } else { - CompileError e("Unknown AST."); - throw e; - } - } - std::string curType, startType; - if (pointerFlag) { - ExprAST *start = chain[chain.size() - 1]; - pointer = start->Codegen(builder)[0]; - curType = start->type[0]->pointee->baseClass; - startType = start->type[0]->pointee->name; - } else { - VariableExprAST *start = dynamic_cast( - chain[chain.size() - 1]); - pointer = start->getAlloca(); - curType = start->type[0]->baseClass; - startType = start->type[0]->name; - } - std::vector idx; - for (int i = chain.size() - 2; i >= 0; i--) { - MemberExprAST *v = dynamic_cast(chain[i]); - std::string member = v->member; - ClassAST * baseClass = unit->classes[curType]; - auto memberAST = baseClass->members.find(member); - if (memberAST == baseClass->members.end()) { - CompileError e("Member" + member + " not found."); - throw e; - } - unsigned int index = std::distance( - std::begin(baseClass->members), memberAST); - idx.push_back(index); - curType = baseClass->members[member]->variableType->name; - } - std::vector idxl; - llvm::IntegerType * itype = - llvm::IntegerType::get(*unit->context, 32); - - idxl.push_back(llvm::ConstantInt::get(itype, 0, true)); - for (unsigned int pid : idx) { - idxl.push_back(llvm::ConstantInt::get(itype, pid, true)); - } - if (idx.size() != 0) { - auto typeAST = unit->types.find(startType); - - pointer = - builder->CreateGEP(typeAST->second, pointer, idxl); - } - } - + ExprAST * curAST = LHS[i]; + llvm::Value *pointer = curAST->getAlloca(builder); builder->CreateStore(RHSV[i], pointer); } } else { std::vector L = LHS->CodegenChain(builder); std::vector R = RHS->CodegenChain(builder); if (L.size() != 1 || R.size() != 1) { - CompileError e("Bin Expr length != 1"); + CompileError e("Bin Expr length != 1", source); throw e; } - std::string LHStype = LHS->type[0]->name; - std::string RHStype = RHS->type[0]->name; + std::string LHStype = LHS->type[0]->getName(); + std::string RHStype = RHS->type[0]->getName(); auto operate = unit->binOperators.find({LHStype, RHStype, binOP}); if (operate == unit->binOperators.end()) { CompileError e("Unknown operator " + binOP + "with type " + - LHStype + " and " + RHStype); + LHStype + " and " + RHStype, + source); throw e; } this->type.push_back(operate->second.second); @@ -200,7 +134,7 @@ std::vector BinaryExprAST::Codegen(llvm::IRBuilder<> *builder) result.push_back(processInnerBinaryOperator(L[0], R[0], builder)); } else { //用户定义运算符 - CompileError e("User-def operator not implemented"); + CompileError e("User-def operator not implemented", source); throw e; } } diff --git a/src/ast/BoolExprAST.cpp b/src/ast/BoolExprAST.cpp index 5b9f7d4956276db7b1f8ba1e322db85dcf7afc77..0e49e3cfdc09cd55f6b74582ebe2023a1b79dea8 100644 --- a/src/ast/BoolExprAST.cpp +++ b/src/ast/BoolExprAST.cpp @@ -21,6 +21,8 @@ BoolExprAST::~BoolExprAST() std::vector BoolExprAST::Codegen(llvm::IRBuilder<> *builder) { + this->type.clear(); + this->type.push_back(new TypeAST(unit, "bool")); std::vector result; llvm::IntegerType * type = llvm::IntegerType::get(*unit->context, 1); llvm::ConstantInt * res = llvm::ConstantInt::get(type, val, true); diff --git a/src/ast/CallExprAST.cpp b/src/ast/CallExprAST.cpp index 5fe2ced3ddb9df2cec1bd2a0caaeb1c9a5fd425f..1cb1eedaae26f1f09cbe5ec6eebb7382cb76b456 100644 --- a/src/ast/CallExprAST.cpp +++ b/src/ast/CallExprAST.cpp @@ -7,19 +7,23 @@ #include "CallExprAST.h" #include "../CompileError.hpp" +#include "ClassAST.h" #include "ExternAST.h" #include "FunctionAST.h" +#include "TypeAST.h" #include #include "../utils.h" -CallExprAST::CallExprAST(CompileUnit *unit, const std::string &callee, - ExprAST *args) +CallExprAST::CallExprAST(CompileUnit *unit, FunctionAST *parentFunction, + const std::string &callee, ExprAST *args, ExprAST *LHS) : ExprAST(unit) { - this->callee = callee; - this->args = args; + this->callee = callee; + this->args = args; + this->LHS = LHS; + this->parentFunction = parentFunction; std::cout << std::left << std::setw(35) << "Function call found:" << this->callee << std::endl; } @@ -31,34 +35,97 @@ CallExprAST::~CallExprAST() std::vector CallExprAST::Codegen(llvm::IRBuilder<> *builder) { + type.clear(); std::vector result; + std::vector argStr; std::vector argsV = args->CodegenChain(builder); + if (LHS != nullptr) { + llvm::Value *thisV = nullptr; + if (Lpointer) { + thisV = LHS->Codegen(builder)[0]; + } else { + thisV = LHS->getAlloca(builder); + } + if (thisV == nullptr) { + CompileError e("No memory allocaed"); + throw e; + } + argsV.insert(argsV.begin(), thisV); + if (LHS->type.size() != 1) { + CompileError e("Multi/void value detected"); + throw e; + } + if (Lpointer) { + if (parentFunction->parentClass == nullptr) { + argStr.push_back(new TypeAST(unit, LHS->type[0]->pointee)); + } else { + argStr.push_back(parentFunction->parentClass->getRealType( + new TypeAST(unit, LHS->type[0]->pointee))); + } - std::vector argStr; + } else { + if (parentFunction->parentClass == nullptr) { + argStr.push_back(new TypeAST(unit, LHS->type[0])); + } else { + argStr.push_back(parentFunction->parentClass->getRealType( + new TypeAST(unit, LHS->type[0]))); + } + } + } for (TypeAST *ast : args->type) { - argStr.push_back(ast); + if (parentFunction->parentClass == nullptr) { + argStr.push_back(ast); + } else { + argStr.push_back(parentFunction->parentClass->getRealType(ast)); + } + } + std::string dname; + if (LHS == nullptr) { + dname = demangle(callee, argStr); + } else { + if (Lpointer) { + ClassAST *baseClass = + unit->classes[LHS->type[0]->pointee->baseClass]; + std::string typeMangledName = + baseClass->getRealNameForMangle(LHS->type[0]->genericTypes); + + dname = demangle(callee, argStr, typeMangledName); + + } else { + ClassAST * baseClass = unit->classes[LHS->type[0]->baseClass]; + std::string typeMangledName = + baseClass->getRealNameForMangle(LHS->type[0]->genericTypes); + + dname = demangle(callee, argStr, typeMangledName); + } } - std::string dname = demangle(callee, argStr); if (callee == "main") { dname = "main"; } PrototypeAST *proto = nullptr; - auto externAST = unit->externs.find(dname); - if (externAST != unit->externs.end()) { - proto = externAST->second->proto; - } - - auto functionAST = unit->functions.find(dname); - if (functionAST != unit->functions.end()) { - proto = functionAST->second->proto; + auto functionAST = unit->globalFunctions.find(dname); + if (functionAST != unit->globalFunctions.end()) { + proto = functionAST->second.first; } if (proto == nullptr) { - CompileError e("Function " + dname + " not found."); + CompileError e("Function " + dname + " not found.", source); throw e; } - type = proto->returnTypes; + for (TypeAST *tAST : proto->returnTypes) { + if (LHS == nullptr) { + type.push_back(tAST); + } else { + ClassAST *baseClass; + if (Lpointer) { + baseClass = unit->classes[LHS->type[0]->pointee->baseClass]; + } else { + baseClass = unit->classes[LHS->type[0]->baseClass]; + } + type.push_back(baseClass->getRealType(tAST)); + } + } llvm::Function *CalleeF = unit->module->getFunction(dname); if (CalleeF == 0) { @@ -70,16 +137,8 @@ std::vector CallExprAST::Codegen(llvm::IRBuilder<> *builder) result.push_back(retD); } else { for (unsigned i = 0; i < type.size(); i++) { - /*llvm::IntegerType *type = - llvm::IntegerType::get(*unit->context, 32); - llvm::ConstantInt *res = llvm::ConstantInt::get(type, i, true);*/ llvm::Value *member = builder->CreateExtractValue(retD, {i}); - - /*llvm::Value *member_ptr = builder->CreateGEP( - CalleeF->getReturnType(), retD, - {llvm::ConstantInt::get(type, 0, true), res});*/ result.push_back(member); - // builder->CreateLoad(member_ptr); } } return result; diff --git a/src/ast/CallExprAST.h b/src/ast/CallExprAST.h index 2c5531bfc5656a22b84765499ddac8d1520bbc14..df93aa79d2783c6076086bf1c454d899101c1c4f 100644 --- a/src/ast/CallExprAST.h +++ b/src/ast/CallExprAST.h @@ -10,15 +10,21 @@ #include "ExprAST.h" +class FunctionAST; class CallExprAST : public ExprAST { public: - CallExprAST(CompileUnit *unit, const std::string &callee, ExprAST *args); + CallExprAST(CompileUnit *unit, FunctionAST *parentFunction, + const std::string &callee, ExprAST *args, + ExprAST *LHS = nullptr); virtual ~CallExprAST(); std::vector Codegen(llvm::IRBuilder<> *builder); - std::string callee; - ExprAST * args; + FunctionAST *parentFunction; + std::string callee; + bool Lpointer = false; + ExprAST * args; + ExprAST * LHS; }; #endif /* COMPILER_AST_CALLEXPRAST_H_ */ diff --git a/src/ast/ClassAST.cpp b/src/ast/ClassAST.cpp index d9f935f5eda454831705e75ea2d2c784697b89da..a76be9e668c111572e4d24a264c0faa27db8dc77 100644 --- a/src/ast/ClassAST.cpp +++ b/src/ast/ClassAST.cpp @@ -7,16 +7,23 @@ #include "ClassAST.h" #include "../CompileError.hpp" +#include "FunctionAST.h" #include "TypeAST.h" ClassAST::ClassAST(CompileUnit *unit, const std::string &className, - std::map members, - std::vector genericTypes) + std::vector members, + std::vector functions, + std::vector genericTypes) : BaseAST(unit) { this->className = className; - this->members = members; + this->omembers = members; + this->functions = functions; this->genericTypes = genericTypes; + for (VariableDefExprAST *member : members) { + this->members.insert(std::pair( + member->idName, member)); + } } ClassAST::~ClassAST() @@ -26,9 +33,10 @@ ClassAST::~ClassAST() ClassAST *ClassAST::ParseClass(CompileUnit *unit) { - Token token = unit->next_tok(); + Token token = unit->next_tok(); + TokenSource source = token.source; if (token.type != tok_identifier) { - CompileError e("Expected identifier", token.file, token.lineno); + CompileError e("Expected identifier", source); throw e; } std::string className = token.tokenValue; @@ -48,78 +56,115 @@ ClassAST *ClassAST::ParseClass(CompileUnit *unit) token = unit->next_tok(); } if (token.type != tok_syntax || token.tokenValue != "{") { - CompileError e("Expected {", token.file, token.lineno); + CompileError e("Expected {", source); throw e; } - std::map members; + + ClassAST *classAST = + new ClassAST(unit, className, std::vector(), + std::vector(), genericTypes); + classAST->source = source; + unit->next_tok(); while (true) { - token = unit->next_tok(); //解析成员方法,成员变量 + token = *(unit->icurTok); if (token.type == tok_syntax && token.tokenValue == "}") { break; } - VariableDefExprAST *memberDef = - VariableDefExprAST::ParseVar(unit, nullptr); - members.insert(std::pair( - memberDef->idName, memberDef)); + if (token.type == tok_fun) { + FunctionAST *funDef = FunctionAST::ParseFunction(unit, classAST); + classAST->functions.push_back(funDef); + + } else { + VariableDefExprAST *memberDef = + VariableDefExprAST::ParseVar(unit, nullptr); + classAST->omembers.push_back(memberDef); + classAST->members.insert( + std::pair(memberDef->idName, + memberDef)); + + unit->next_tok(); + } } - token = unit->next_tok(); - ClassAST *classAST = new ClassAST(unit, className, members, genericTypes); + + token = unit->next_tok(); return classAST; } -TypeAST *ClassAST::getRealType(TypeAST * type, +TypeAST *ClassAST::getRealType(const TypeAST * type, std::vector igenericTypes) { + TypeAST *realType = new TypeAST(unit, type->baseClass); if (type->pointee != nullptr) { - type->pointee = getRealType(type->pointee, igenericTypes); + realType->pointee = getRealType(type->pointee, igenericTypes); } for (unsigned int i = 0; i < type->genericTypes.size(); i++) { - type->genericTypes[i] = - getRealType(type->genericTypes[i], igenericTypes); + realType->genericTypes.push_back( + getRealType(type->genericTypes[i], igenericTypes)); } - auto it = find(genericTypes.begin(), genericTypes.end(), type->name); - - type->initName(); + auto it = find(genericTypes.begin(), genericTypes.end(), type->baseClass); if (it != genericTypes.end()) { //泛型 int index = it - genericTypes.begin(); return igenericTypes[index]; } else { - return type; + return realType; } } -llvm::Type *ClassAST::Codegen(std::vector igenericTypes) +TypeAST *ClassAST::getRealType(const TypeAST *type) +{ + return getRealType(type, this->igenericTypes); +} + +std::string ClassAST::getRealName(std::vector igenericTypes) { - if (igenericTypes.size() != genericTypes.size()) { - CompileError e("generic isn't equal"); - throw e; - } std::string name = className; if (igenericTypes.size() != 0) { name += "<"; for (unsigned int i = 0; i < igenericTypes.size() - 1; i++) { - name += igenericTypes[i]->name + ","; + name += igenericTypes[i]->getName() + ","; + } + name += igenericTypes[igenericTypes.size() - 1]->getName() + ">"; + } + return name; +} + +std::string ClassAST::getRealNameForMangle(std::vector igenericTypes) +{ + std::stringstream ss; + ss << "C" << className.length() << className; + if (igenericTypes.size() != 0) { + for (unsigned int i = 0; i < igenericTypes.size() - 1; i++) { + std::string typeMangleName = igenericTypes[i]->getMangleName(); + ss << typeMangleName.length() << typeMangleName; } - name += igenericTypes[igenericTypes.size() - 1]->name + ">"; } + ss << "E"; + return ss.str(); +} +llvm::Type *ClassAST::Codegen(std::vector igenericTypes) +{ + if (igenericTypes.size() != genericTypes.size()) { + CompileError e("generic isn't equal", source); + throw e; + } + this->igenericTypes = igenericTypes; + std::string name = getRealName(igenericTypes); llvm::StructType *llvm_S = llvm::StructType::create(*unit->context, className); unit->types.insert(std::pair(name, llvm_S)); - std::vector sMembers; - std::map::iterator member_iter; - for (member_iter = members.begin(); member_iter != members.end(); - member_iter++) { - - VariableDefExprAST *memberVariable = member_iter->second; - TypeAST * mType = - getRealType(memberVariable->variableType, igenericTypes); + std::vector sMembers; + for (VariableDefExprAST *member : this->omembers) { + TypeAST *mType = getRealType(member->variableType, igenericTypes); sMembers.push_back(mType->Codegen()); } llvm_S->setBody(sMembers); + for (FunctionAST *function : functions) { + function->Codegen(igenericTypes); + } return llvm_S; } diff --git a/src/ast/ClassAST.h b/src/ast/ClassAST.h index 4ef01e14da2f3688bf21879c87309f32f14ebb71..91081d8731f827583d30bd201680999beda60c4b 100644 --- a/src/ast/ClassAST.h +++ b/src/ast/ClassAST.h @@ -11,19 +11,30 @@ #include "BaseAST.h" #include "VariableDefExprAST.h" +class FunctionAST; class ClassAST : public BaseAST { public: ClassAST(CompileUnit *unit, const std::string &className, - std::map members, - std::vector genericTypes); + std::vector members, + std::vector functions, + std::vector genericTypes); virtual ~ClassAST(); llvm::Type *Codegen(std::vector genericTypes); - TypeAST *getRealType(TypeAST *type, std::vector igenericTypes); + TypeAST * getRealType(const TypeAST * type, + std::vector igenericTypes); + TypeAST * getRealType(const TypeAST *type); + std::string getRealName(std::vector igenericTypes); + + std::string getRealNameForMangle(std::vector igenericTypes); + static ClassAST * ParseClass(CompileUnit *unit); - std::map members; + std::map members; //查找用 + std::vector omembers; //记录顺序用 + std::vector functions; std::vector genericTypes; std::string className; + std::vector igenericTypes; // todo:注意多线程的情形 }; #endif /* SRC_AST_CLASSAST_H_ */ diff --git a/src/ast/CodeBlockAST.cpp b/src/ast/CodeBlockAST.cpp index 7c599dbe0b1d99855a96349172c01e66b2e6664b..68e5ba7f9d70654e9e57910413aee9ab56556c6f 100644 --- a/src/ast/CodeBlockAST.cpp +++ b/src/ast/CodeBlockAST.cpp @@ -11,14 +11,16 @@ #include CodeBlockAST::CodeBlockAST(CompileUnit *unit, std::vector body, - std::string name, CodeBlockAST *parent) + std::string name, FunctionAST *baseFunction, + CodeBlockAST *parent) : BaseAST(unit) { - this->builder = new llvm::IRBuilder<>(*unit->context); - this->body = body; - this->name = name; - this->parent = parent; - this->endBB = nullptr; + this->builder = new llvm::IRBuilder<>(*unit->context); + this->body = body; + this->name = name; + this->parent = parent; + this->endBB = nullptr; + this->baseFunction = baseFunction; } CodeBlockAST::~CodeBlockAST() @@ -28,12 +30,12 @@ CodeBlockAST::~CodeBlockAST() CodeBlockAST * CodeBlockAST::ParseCodeBlock(CompileUnit *unit, std::string name, - CodeBlockAST * parent, + FunctionAST *baseFunction, CodeBlockAST *parent, const std::vector args) { - Token token = *unit->icurTok; - CodeBlockAST *codeblock = - new CodeBlockAST(unit, std::vector(), name, parent); + Token token = *unit->icurTok; + CodeBlockAST *codeblock = new CodeBlockAST(unit, std::vector(), + name, baseFunction, parent); if (token.type == tok_syntax && token.tokenValue == "{") { std::vector &body = codeblock->body; @@ -70,6 +72,7 @@ CodeBlockAST::ParseCodeBlock(CompileUnit *unit, std::string name, llvm::BasicBlock *CodeBlockAST::Codegen(llvm::Function *function) { + namedValues.clear(); llvm::BasicBlock *bb = llvm::BasicBlock::Create(*unit->context, name, function); endBB = bb; diff --git a/src/ast/CodeBlockAST.h b/src/ast/CodeBlockAST.h index 6ec37d027e2aa5d9494387796838238e341ae12c..12b8e7acdccc2fb09c0b1dddbaa6369597e2d55c 100644 --- a/src/ast/CodeBlockAST.h +++ b/src/ast/CodeBlockAST.h @@ -14,15 +14,17 @@ #include class VariableDefExprAST; +class FunctionAST; class CodeBlockAST : public BaseAST { public: CodeBlockAST(CompileUnit *unit, std::vector exprs, - std::string name, CodeBlockAST *parent = nullptr); + std::string name, FunctionAST *baseFunction, + CodeBlockAST *parent = nullptr); virtual ~CodeBlockAST(); static CodeBlockAST * ParseCodeBlock(CompileUnit *unit, std::string name, - CodeBlockAST * parent = nullptr, + FunctionAST *baseFunction, CodeBlockAST *parent = nullptr, const std::vector args = std::vector()); llvm::BasicBlock *Codegen(llvm::Function *function); @@ -34,6 +36,8 @@ class CodeBlockAST : public BaseAST std::string name; CodeBlockAST * parent; llvm::BasicBlock *endBB; + FunctionAST * baseFunction; + bool jumped = false; //是否有跳出语句 }; #endif /* COMPILER_AST_CODEBLOCKAST_H_ */ diff --git a/src/ast/DoubleExprAST.cpp b/src/ast/DoubleExprAST.cpp index f31d35cae9ccf5020fa43225bf1f51403b73d981..ac51f0a2f8ed05d0fb0b83f6c7561701aee19f01 100644 --- a/src/ast/DoubleExprAST.cpp +++ b/src/ast/DoubleExprAST.cpp @@ -21,6 +21,8 @@ DoubleExprAST::~DoubleExprAST() std::vector DoubleExprAST::Codegen(llvm::IRBuilder<> *builder) { + this->type.clear(); + this->type.push_back(new TypeAST(unit, "double")); std::vector result; llvm::Type * rtype = llvm::Type::getDoubleTy(*unit->context); llvm::Value * res = llvm::ConstantFP::get(rtype, val); diff --git a/src/ast/ExprAST.cpp b/src/ast/ExprAST.cpp index b227f253ec4e02d855f5437d05b8681ceb562398..6dd3a502b9b7aeaa2a22ac0d3352556c84ca2317 100644 --- a/src/ast/ExprAST.cpp +++ b/src/ast/ExprAST.cpp @@ -7,10 +7,13 @@ #include "CodeBlockAST.h" #include "DoubleExprAST.h" #include "EmptyExprAST.h" +#include "FunctionAST.h" #include "IfExprAST.h" #include "IntExprAST.h" #include "MemberExprAST.h" #include "ReturnExprAST.h" +#include "SizeofExprAST.h" +#include "StringExprAST.h" #include "UnaryExprAST.h" #include "VariableDefExprAST.h" #include "VariableExprAST.h" @@ -114,12 +117,15 @@ ExprAST::~ExprAST() // TODO Auto-generated destructor stub } +llvm::Value *ExprAST::getAlloca(llvm::IRBuilder<> *builder) { return nullptr; } + ExprAST *ExprAST::ParsePrimary(CompileUnit *unit, CodeBlockAST *codeblock, bool root) { ExprAST *result; // todo:除了函数调用之外的语句解析 - Token token = *unit->icurTok; + Token token = *unit->icurTok; + TokenSource source = token.source; switch (token.type) { case tok_number: { unit->next_tok(); @@ -155,7 +161,7 @@ ExprAST *ExprAST::ParsePrimary(CompileUnit *unit, CodeBlockAST *codeblock, result = ParseExpression(unit, codeblock, false); token = *unit->icurTok; if (token.type != tok_syntax || token.tokenValue != ")") { - CompileError e("missing ')'"); + CompileError e("missing ')'", source); throw e; } unit->next_tok(); @@ -172,7 +178,8 @@ ExprAST *ExprAST::ParsePrimary(CompileUnit *unit, CodeBlockAST *codeblock, //函数调用 token = unit->next_tok(); ExprAST *args = ExprAST::ParseExpression(unit, codeblock, false); - result = new CallExprAST(unit, idName, args); + result = new CallExprAST(unit, codeblock->baseFunction, idName, + args, nullptr); } else { //变量或变量定义 int i = 1, ci = 1; @@ -184,11 +191,11 @@ ExprAST *ExprAST::ParsePrimary(CompileUnit *unit, CodeBlockAST *codeblock, ci++; continue; } - if (token.tokenValue != "<") { + if (token.tokenValue != "<" || !root) { //变量 unit->next_tok(); result = new VariableExprAST(unit, codeblock, idName); - } else if (token.tokenValue == "<") { + } else if (token.tokenValue == "<" && root) { //变量定义 result = VariableDefExprAST::ParseVar(unit, codeblock); } @@ -204,33 +211,51 @@ ExprAST *ExprAST::ParsePrimary(CompileUnit *unit, CodeBlockAST *codeblock, break; } case tok_return: { - return ReturnExprAST::ParseReturnExprAST(unit, codeblock); + result = ReturnExprAST::ParseReturnExprAST(unit, codeblock); + codeblock->jumped = true; + break; + } + case tok_key_sizeof: { + unit->next_tok(); // sizeof + unit->next_tok(); //( + TypeAST *type = + TypeAST::ParseType(unit, codeblock->baseFunction->parentClass); + unit->next_tok(); //) + result = new SizeofExprAST(unit, type); + break; + } + case tok_str: { + //字符串字面值 + result = new StringExprAST(unit, token.tokenValue); + result->source = token.source; + unit->next_tok(); + break; } default: { - CompileError e("不期待的token:" + token.dump(), token.file, - token.lineno); + CompileError e("不期待的token:" + token.dump(), source); throw e; } } - /*if (token.type == tok_syntax && token.tokenValue == ",") { - unit->next_tok(); - ExprAST *subExpr = ParseBinOpRHS(unit, codeblock, 200, result); - if (BinaryExprAST *v = dynamic_cast(subExpr)) { - subExpr = v->RHS; - } - result->subExpr = subExpr; - }*/ + result->source = source; return result; } +void ExprAST::appendSubExpr(ExprAST *expr) +{ + ExprAST *curAST = this; + while (curAST->subExpr != nullptr) { + curAST = curAST->subExpr; + } + curAST->subExpr = expr; +} + static ExprAST *ParseBinOpRHS(CompileUnit *unit, CodeBlockAST *codeblock, int ExprPrec, ExprAST *LHS) { - ExprAST *cExpr = LHS; while (1) { Token token = *unit->icurTok; int TokPrec; - if (LHS == nullptr) { + if (EmptyExprAST *v = dynamic_cast(LHS)) { TokPrec = GetLUnaryTokPrecedence(token); } else { TokPrec = GetBinTokPrecedence(token); @@ -252,20 +277,26 @@ static ExprAST *ParseBinOpRHS(CompileUnit *unit, CodeBlockAST *codeblock, } } if (token.tokenValue == ",") { - cExpr->subExpr = RHS; - cExpr = RHS; + LHS->appendSubExpr(RHS); } else if (token.tokenValue == ".") { if (VariableExprAST *v = dynamic_cast(RHS)) { LHS = new MemberExprAST(unit, LHS, v->idName, false); + } else if (CallExprAST *v = dynamic_cast(RHS)) { + v->LHS = LHS; + LHS = v; } else { - CompileError e("成员方法调用未实现"); + CompileError e("未知的操作", token.source); throw e; } } else if (token.tokenValue == "->") { if (VariableExprAST *v = dynamic_cast(RHS)) { LHS = new MemberExprAST(unit, LHS, v->idName, true); + } else if (CallExprAST *v = dynamic_cast(RHS)) { + v->LHS = LHS; + v->Lpointer = true; + LHS = v; } else { - CompileError e("成员方法调用未实现"); + CompileError e("未知的操作", token.source); throw e; } } else if (dynamic_cast(LHS) != nullptr && @@ -276,9 +307,11 @@ static ExprAST *ParseBinOpRHS(CompileUnit *unit, CodeBlockAST *codeblock, GetRUnaryTokPrecedence(token) != -1) { //右一元运算符 LHS = new UnaryExprAST(unit, token.tokenValue, LHS, false); + } else { LHS = new BinaryExprAST(unit, token.tokenValue, LHS, RHS); } + LHS->source = token.source; } } @@ -286,13 +319,7 @@ ExprAST *ExprAST::ParseExpression(CompileUnit *unit, CodeBlockAST *codeblock, bool root) { ExprAST *result = ParsePrimary(unit, codeblock, root); - - /*while (unit->icurTok->type == tok_syntax && - unit->icurTok->tokenValue == ".") { - LHS = MemberExprAST::ParseMemberExprAST(unit, codeblock, LHS); - }*/ - - result = ParseBinOpRHS(unit, codeblock, 0, result); + result = ParseBinOpRHS(unit, codeblock, 0, result); if (IfExprAST *v = dynamic_cast(result)) { return result; //跳过分号 @@ -303,8 +330,8 @@ ExprAST *ExprAST::ParseExpression(CompileUnit *unit, CodeBlockAST *codeblock, Token token = *(unit->icurTok); if (root) { if (token.type != tok_syntax || token.tokenValue != ";") { - CompileError e("丟失分号: \"" + token.dump() + "\" 前", token.file, - token.lineno); + CompileError e("丟失分号: \"" + token.dump() + "\" 前", + token.source); throw e; } unit->next_tok(); @@ -314,9 +341,10 @@ ExprAST *ExprAST::ParseExpression(CompileUnit *unit, CodeBlockAST *codeblock, std::vector ExprAST::CodegenChain(llvm::IRBuilder<> *builder) { + type.clear(); std::vector result = this->Codegen(builder); if (subExpr != nullptr) { - std::vector subResult = subExpr->Codegen(builder); + std::vector subResult = subExpr->CodegenChain(builder); std::vector subType = subExpr->type; result.insert(result.end(), subResult.begin(), subResult.end()); type.insert(type.end(), subType.begin(), subType.end()); diff --git a/src/ast/ExprAST.h b/src/ast/ExprAST.h index f76f396af5897ecb45bd094bac1ab939b3590864..f0108854dfede921d4489ba5be18645e7cb589a7 100644 --- a/src/ast/ExprAST.h +++ b/src/ast/ExprAST.h @@ -11,10 +11,12 @@ class ExprAST : public BaseAST virtual ~ExprAST(); virtual std::vector Codegen(llvm::IRBuilder<> *builder) = 0; std::vector CodegenChain(llvm::IRBuilder<> *builder); + virtual llvm::Value * getAlloca(llvm::IRBuilder<> *builder); static ExprAST *ParseExpression(CompileUnit *unit, CodeBlockAST *codeblock, bool root); static ExprAST *ParsePrimary(CompileUnit *unit, CodeBlockAST *codeblock, bool root = false); + void appendSubExpr(ExprAST *expr); std::vector type; ExprAST * subExpr; }; diff --git a/src/ast/ExternAST.cpp b/src/ast/ExternAST.cpp index 3f6c5bd50d720c80cdc27a3fb17d45caa1d38160..0985aa4e15b39465ae1fa54fd5527ad9f0a97d0a 100644 --- a/src/ast/ExternAST.cpp +++ b/src/ast/ExternAST.cpp @@ -30,7 +30,7 @@ ExternAST *ExternAST::ParseExtern(CompileUnit *unit) } else if (flag.tokenValue == "C") { C = true; } else { - CompileError e("Unknown flag:" + flag.tokenValue,flag.file,flag.lineno); + CompileError e("Unknown flag:" + flag.tokenValue, flag.source); throw e; } } @@ -44,8 +44,7 @@ ExternAST *ExternAST::ParseExtern(CompileUnit *unit) << "Function extern found:" << proto->name << std::endl; Token token = *(unit->icurTok); if (token.type != tok_syntax || token.tokenValue != ";") { - CompileError e("丟失分号: \"" + token.dump() + "\" 前", token.file, - token.lineno); + CompileError e("丟失分号: \"" + token.dump() + "\" 前", token.source); throw e; } token = unit->next_tok(); @@ -53,10 +52,4 @@ ExternAST *ExternAST::ParseExtern(CompileUnit *unit) return new ExternAST(unit, proto); } -std::string ExternAST::getDemangledName() { return proto->demangledName; } - -llvm::Function *ExternAST::Codegen() -{ - proto->Codegen(); - return 0; -} +llvm::Function *ExternAST::Codegen() { return proto->Codegen(); } diff --git a/src/ast/ExternAST.h b/src/ast/ExternAST.h index 6549d762bea6766ba13ec89588d5a549596eb088..aa47819c6c3a7c31b3dd38208dcf10dcd4d4e2a3 100644 --- a/src/ast/ExternAST.h +++ b/src/ast/ExternAST.h @@ -19,7 +19,6 @@ class ExternAST : public BaseAST static ExternAST *ParseExtern(CompileUnit *unit); llvm::Function * Codegen(); PrototypeAST * proto; - std::string getDemangledName(); }; #endif /* COMPILER_AST_EXTERNAST_H_ */ diff --git a/src/ast/FunctionAST.cpp b/src/ast/FunctionAST.cpp index 8d70a59ae3015143c93c8e9fe197c7bc5aa0b7a4..694f441b3e55d756b65ccc56b664bd1957927647 100644 --- a/src/ast/FunctionAST.cpp +++ b/src/ast/FunctionAST.cpp @@ -7,8 +7,10 @@ #include "FunctionAST.h" #include "../CompileError.hpp" +#include "ClassAST.h" #include "CodeBlockAST.h" #include "PrototypeAST.h" +#include "TypeAST.h" #include "VariableDefExprAST.h" #include "VariableExprAST.h" #include @@ -16,11 +18,12 @@ #include FunctionAST::FunctionAST(CompileUnit *unit, PrototypeAST *proto, - CodeBlockAST *body) + CodeBlockAST *body, ClassAST *parentClass) : BaseAST(unit) { - this->proto = proto; - this->body = body; + this->proto = proto; + this->body = body; + this->parentClass = parentClass; } FunctionAST::~FunctionAST() @@ -28,28 +31,123 @@ FunctionAST::~FunctionAST() // TODO Auto-generated destructor stub } -llvm::Function *FunctionAST::Codegen() +void FunctionAST::processInnerFunction(llvm::Function *func) { - llvm::Function * func = proto->Codegen(); - llvm::BasicBlock *bb = body->Codegen(func); + llvm::IRBuilder<> *builder = new llvm::IRBuilder<>(*unit->context); + llvm::BasicBlock * bb = + llvm::BasicBlock::Create(*unit->context, "entry", func); + builder->SetInsertPoint(bb); + std::vector returnValue = std::vector(); + llvm::IRBuilder<> sBuilder(&func->getEntryBlock(), + func->getEntryBlock().begin()); + + llvm::StructType *sType = (llvm::StructType *)func->getReturnType(); + llvm::AllocaInst *alloca = sBuilder.CreateAlloca(sType); + + if (proto->name == "__alolang_inner_load") { + llvm::IntegerType *itype = llvm::IntegerType::get(*unit->context, 32); + llvm::Type * classType = + ((llvm::PointerType *)func->getArg(0)->getType())->getElementType(); + llvm::Type * realType = parentClass->igenericTypes[0]->Codegen(); + llvm::Value *thisValue = func->getArg(0); + llvm::Value *pointer = builder->CreateGEP( + classType, thisValue, + std::vector{llvm::ConstantInt::get(itype, 0, true), + llvm::ConstantInt::get(itype, 0, true)}); + pointer = builder->CreateLoad(pointer); + pointer = builder->CreateIntToPtr(pointer, + llvm::PointerType::get(realType, 0)); + returnValue.push_back(pointer); + } else if (proto->name == "__alolang_inner_toObj") { + llvm::IntegerType *itype = llvm::IntegerType::get(*unit->context, 32); + llvm::Type * classType = + ((llvm::PointerType *)func->getArg(0)->getType())->getElementType(); + + llvm::Type * realType = parentClass->igenericTypes[0]->Codegen(); + llvm::Value *pointer = builder->CreateGEP( + classType, func->getArg(0), + std::vector{llvm::ConstantInt::get(itype, 0, true), + llvm::ConstantInt::get(itype, 0, true)}); + llvm::Value *addr = builder->CreatePtrToInt( + func->getArg(1), llvm::IntegerType::get(*unit->context, 64)); + builder->CreateStore(addr, pointer); + + } else { + CompileError e("No inner function:" + proto->name); + throw e; + } + for (int i = 0; i < returnValue.size(); i++) { + llvm::IntegerType *type = llvm::IntegerType::get(*unit->context, 32); + llvm::ConstantInt *res = llvm::ConstantInt::get(type, i, true); + + llvm::Value *member_ptr = builder->CreateGEP( + sType, alloca, {llvm::ConstantInt::get(type, 0, true), res}); + builder->CreateStore(returnValue[i], member_ptr); + // builder->CreateLoad(member_ptr); + } + + for (int i = 0; i < returnValue.size(); i++) { + llvm::IntegerType *type = llvm::IntegerType::get(*unit->context, 32); + llvm::ConstantInt *res = llvm::ConstantInt::get(type, i, true); + + llvm::Value *member_ptr = builder->CreateGEP( + sType, alloca, {llvm::ConstantInt::get(type, 0, true), res}); + builder->CreateStore(returnValue[i], member_ptr); + // builder->CreateLoad(member_ptr); + } + builder->CreateRet(builder->CreateLoad(alloca)); +} + +llvm::Function *FunctionAST::Codegen(std::vector igenericTypes) +{ + this->igenericTypes = igenericTypes; + llvm::Function *func = proto->Codegen(igenericTypes); + unit->globalFunctions.insert( + std::pair>( + func->getName(), + std::pair(proto, func))); + if (proto->name.substr(0, 16) == "__alolang_inner_") { + processInnerFunction(func); + } else { + llvm::BasicBlock *bb = body->Codegen(func); + } // func->getBasicBlockList().push_back(bb); return func; } -FunctionAST *FunctionAST::ParseFunction(CompileUnit *unit) +FunctionAST *FunctionAST::ParseFunction(CompileUnit *unit, + ClassAST * parentClass) { - PrototypeAST *protoType = PrototypeAST::ParsePrototype(unit, true); + PrototypeAST *protoType = + PrototypeAST::ParsePrototype(unit, true, parentClass); + if (parentClass != nullptr) { + std::vector genericTypes; + for (std::string gType : parentClass->genericTypes) { + genericTypes.push_back(new TypeAST(unit, gType)); + } + protoType->args.insert( + protoType->args.begin(), + std::pair( + new TypeAST(unit, new TypeAST(unit, parentClass->className, + genericTypes, parentClass)), + "this")); + } std::cout << std::left << std::setw(35) << "Function definition found:" << protoType->name << std::endl; std::vector args; + for (unsigned int i = 0; i < protoType->args.size(); i++) { std::pair arg = protoType->args[i]; args.push_back(new VariableDefExprAST(unit, nullptr, arg.second, arg.first, nullptr, i)); } + FunctionAST *result = + new FunctionAST(unit, protoType, nullptr, parentClass); + CodeBlockAST *body = - CodeBlockAST::ParseCodeBlock(unit, "entry", nullptr, args); - return new FunctionAST(unit, protoType, body); + CodeBlockAST::ParseCodeBlock(unit, "entry", result, nullptr, args); + result->body = body; + + return result; } -std::string FunctionAST::getDemangledName() { return proto->demangledName; } diff --git a/src/ast/FunctionAST.h b/src/ast/FunctionAST.h index ea78823191735f0fd36e6ec7e28b43769d19e6d1..f08a24696fb4cf75bfa6f0d945050f6b6862a9c4 100644 --- a/src/ast/FunctionAST.h +++ b/src/ast/FunctionAST.h @@ -17,14 +17,20 @@ class FunctionAST : public BaseAST { public: - FunctionAST(CompileUnit *unit, PrototypeAST *proto, CodeBlockAST *body); + FunctionAST(CompileUnit *unit, PrototypeAST *proto, CodeBlockAST *body, + ClassAST *parentClass = nullptr); virtual ~FunctionAST(); - llvm::Function *Codegen(); - std::string getDemangledName(); - PrototypeAST * proto; + llvm::Function * + Codegen(std::vector igenericTypes = std::vector()); + void processInnerFunction(llvm::Function *func); - CodeBlockAST * body; - static FunctionAST *ParseFunction(CompileUnit *unit); + PrototypeAST *proto; + ClassAST * parentClass; + + CodeBlockAST * body; + std::vector igenericTypes; + static FunctionAST * ParseFunction(CompileUnit *unit, + ClassAST * parentClass = nullptr); }; #endif /* COMPILER_AST_FUNCTIONAST_H_ */ diff --git a/src/ast/IfExprAST.cpp b/src/ast/IfExprAST.cpp index d7997867fd34c2259592f77218e21d0996250500..76a98d22432eb9489e68aac77ddfedc101b27369 100644 --- a/src/ast/IfExprAST.cpp +++ b/src/ast/IfExprAST.cpp @@ -29,12 +29,14 @@ IfExprAST *IfExprAST::ParseIfExpr(CompileUnit *unit, CodeBlockAST *parent) { unit->next_tok(); ExprAST * condition = ExprAST::ParseExpression(unit, parent, false); - CodeBlockAST *thenBlock = CodeBlockAST::ParseCodeBlock(unit, "", parent); + CodeBlockAST *thenBlock = + CodeBlockAST::ParseCodeBlock(unit, "", parent->baseFunction, parent); CodeBlockAST *elseBlock = nullptr; - if ((unit->icurTok + 1)->type == tok_key_else) { + if (unit->icurTok->type == tok_key_else) { unit->next_tok(); - elseBlock = CodeBlockAST::ParseCodeBlock(unit, "", parent); + elseBlock = CodeBlockAST::ParseCodeBlock(unit, "", parent->baseFunction, + parent); } return new IfExprAST(unit, parent, condition, thenBlock, elseBlock); } @@ -54,13 +56,17 @@ std::vector IfExprAST::Codegen(llvm::IRBuilder<> *builder) if (elseBlock != nullptr) { llvm::BasicBlock *elseBB = elseBlock->Codegen(function); builder->CreateCondBr(conditionValue, thenBB, elseBB); - builder->SetInsertPoint(elseBlock->endBB); - builder->CreateBr(MergeBB); + if (!elseBlock->jumped) { + builder->SetInsertPoint(elseBlock->endBB); + builder->CreateBr(MergeBB); + } } else { builder->CreateCondBr(conditionValue, thenBB, MergeBB); } - builder->SetInsertPoint(thenBlock->endBB); - builder->CreateBr(MergeBB); + if (!thenBlock->jumped) { + builder->SetInsertPoint(thenBlock->endBB); + builder->CreateBr(MergeBB); + } builder->SetInsertPoint(MergeBB); parent->endBB = MergeBB; return std::vector(); diff --git a/src/ast/IntExprAST.cpp b/src/ast/IntExprAST.cpp index 7353b5fb6bbd0e434311eb5ad17a08634eb09ab5..fed6ac77962482721751bd600a3102b000722df6 100644 --- a/src/ast/IntExprAST.cpp +++ b/src/ast/IntExprAST.cpp @@ -11,7 +11,6 @@ IntExprAST::IntExprAST(CompileUnit *unit, long long val) : ExprAST(unit) { this->val = val; - this->type.push_back(new TypeAST(unit, "int")); } IntExprAST::~IntExprAST() @@ -21,6 +20,8 @@ IntExprAST::~IntExprAST() std::vector IntExprAST::Codegen(llvm::IRBuilder<> *builder) { + type.clear(); + this->type.push_back(new TypeAST(unit, "int")); std::vector result; llvm::IntegerType *rtype = llvm::IntegerType::get(*unit->context, 64); llvm::ConstantInt *res = llvm::ConstantInt::get(rtype, val, true); diff --git a/src/ast/MemberExprAST.cpp b/src/ast/MemberExprAST.cpp index b460a1553d3525ea722073368fdab0521f7ebcb5..372738000c5e81cdb53e1d777efb1ec2feaf8445 100644 --- a/src/ast/MemberExprAST.cpp +++ b/src/ast/MemberExprAST.cpp @@ -9,6 +9,8 @@ #include "../CompileError.hpp" #include "ClassAST.h" #include "TypeAST.h" +#include "UnaryExprAST.h" +#include "VariableExprAST.h" MemberExprAST::MemberExprAST(CompileUnit *unit, ExprAST *LHS, std::string member, bool isPointer) @@ -26,31 +28,135 @@ MemberExprAST::~MemberExprAST() std::vector MemberExprAST::Codegen(llvm::IRBuilder<> *builder) { - if (isPointer) { - CompileError e("未实现."); - throw e; - } + type.clear(); + std::vector result; std::vector bases = LHS->Codegen(builder); if (bases.size() != 1) { - CompileError e("Multi/Void type found."); + CompileError e("Multi/Void type found.", source); throw e; } - llvm::Value *base = bases[0]; - - ClassAST *baseClass = unit->classes[LHS->type[0]->baseClass]; - auto memberAST = baseClass->members.find(member); - if (memberAST == baseClass->members.end()) { - CompileError e("Member " + member + " not found."); + llvm::Value * base = bases[0]; + ClassAST * baseClass = unit->classes[LHS->type[0]->baseClass]; + std::vector genericTypes = LHS->type[0]->genericTypes; + if (isPointer) { + baseClass = unit->classes[LHS->type[0]->pointee->baseClass]; + base = builder->CreateLoad(base); + genericTypes = LHS->type[0]->pointee->genericTypes; + } + //查找变量位置 + unsigned int index = 0; + bool foundFlag = false; + for (; index < baseClass->omembers.size(); index++) { + if (baseClass->omembers[index]->idName == this->member) { + foundFlag = true; + break; + } + } + if (!foundFlag) { + CompileError e("Member " + this->member + " not found.", source); throw e; } - unsigned int index = - std::distance(std::begin(baseClass->members), memberAST); type.push_back(baseClass->getRealType( - baseClass->members[member]->variableType, LHS->type[0]->genericTypes)); + baseClass->members[member]->variableType, genericTypes)); llvm::Value *member = builder->CreateExtractValue(base, {index}); result.push_back(member); return result; } + +llvm::Value *MemberExprAST::getAlloca(llvm::IRBuilder<> *builder) +{ + type.clear(); + ExprAST * curAST = this; + std::vector chain; + llvm::Value * pointer; + bool pointerFlag = false; + while (true) { + chain.push_back(curAST); + if (MemberExprAST *v = dynamic_cast(curAST)) { + if (v->isPointer) { + pointerFlag = true; + chain.push_back(v->LHS); + break; + } + curAST = v->LHS; + } else if (VariableExprAST *v = + dynamic_cast(curAST)) { + pointerFlag = false; + break; + } else if (UnaryExprAST *v = dynamic_cast(curAST)) { + if (v->op == "*") { + pointerFlag = true; + chain.push_back(v->operand); + break; + } else { + CompileError e("Unknown AST.", source); + throw e; + } + break; + } else { + CompileError e("Unknown AST.", source); + throw e; + } + } + TypeAST *curType, *startType; + if (pointerFlag) { + ExprAST *start = chain[chain.size() - 1]; + pointer = start->Codegen(builder)[0]; + curType = start->type[0]->pointee; + startType = start->type[0]->pointee; + } else { + VariableExprAST *start = + dynamic_cast(chain[chain.size() - 1]); + pointer = start->getAlloca(builder); + if (pointer == nullptr) { + CompileError e("No memory allocaed", source); + throw e; + } + curType = start->type[0]; + startType = start->type[0]; + } + std::vector idx; + for (int i = chain.size() - 2; i >= 0; i--) { + MemberExprAST *v = dynamic_cast(chain[i]); + std::string cmember = v->member; + ClassAST * baseClass = unit->classes[curType->baseClass]; + if (baseClass == nullptr) { + CompileError e("Class " + curType->baseClass + " not found.", + source); + throw e; + } + unsigned int index = 0; + bool foundFlag = false; + for (; index < baseClass->omembers.size(); index++) { + if (baseClass->omembers[index]->idName == cmember) { + foundFlag = true; + break; + } + } + if (!foundFlag) { + CompileError e("Member " + cmember + " not found.", source); + throw e; + } + idx.push_back(index); + curType = baseClass->members[cmember]->variableType; + curType = baseClass->getRealType(curType); + } + std::vector idxl; + llvm::IntegerType *itype = llvm::IntegerType::get(*unit->context, 32); + + idxl.push_back(llvm::ConstantInt::get(itype, 0, true)); + for (unsigned int pid : idx) { + idxl.push_back(llvm::ConstantInt::get(itype, pid, true)); + } + if (idx.size() != 0) { + auto typeAST = unit->types.find(startType->getName()); + + pointer = builder->CreateGEP(typeAST->second, pointer, idxl); + } + type.push_back(curType); + + return pointer; +} diff --git a/src/ast/MemberExprAST.h b/src/ast/MemberExprAST.h index 410e5f468ee9b9b2614128e6d8032bfce05d1399..b084ede35db0c0aab998680c3b49018d3f0ab28e 100644 --- a/src/ast/MemberExprAST.h +++ b/src/ast/MemberExprAST.h @@ -16,6 +16,7 @@ class MemberExprAST : public ExprAST MemberExprAST(CompileUnit *unit, ExprAST *LHS, std::string member, bool isPointer); virtual ~MemberExprAST(); + virtual llvm::Value * getAlloca(llvm::IRBuilder<> *builder); std::vector Codegen(llvm::IRBuilder<> *builder); ExprAST * LHS; std::string member; diff --git a/src/ast/PrototypeAST.cpp b/src/ast/PrototypeAST.cpp index 044efe5873a4f0e95bc520addbfe169c5afdc549..d93bdf90ce2a7a4dad2785beba7e09c23efa911a 100644 --- a/src/ast/PrototypeAST.cpp +++ b/src/ast/PrototypeAST.cpp @@ -8,29 +8,21 @@ #include "PrototypeAST.h" #include "../CompileError.hpp" #include "../utils.h" +#include "ClassAST.h" #include "TypeAST.h" - #include PrototypeAST::PrototypeAST( CompileUnit *unit, const std::string &name, const std::vector> &args, - const std::vector & returnTypes) + const std::vector &returnTypes, ClassAST *parentClass) : BaseAST(unit) { this->name = name; this->args = args; this->returnDirectly = false; this->returnTypes = returnTypes; - std::vector argStr; - for (std::pair pair : args) { - argStr.push_back(pair.first); - } - if (name != "main") { - this->demangledName = demangle(name, argStr); - } else { - this->demangledName = "main"; - } + this->parentClass = parentClass; } PrototypeAST::~PrototypeAST() @@ -38,10 +30,12 @@ PrototypeAST::~PrototypeAST() // TODO Auto-generated destructor stub } -PrototypeAST *PrototypeAST::ParsePrototype(CompileUnit *unit, bool hasBody) +PrototypeAST *PrototypeAST::ParsePrototype(CompileUnit *unit, bool hasBody, + ClassAST *parentClass) { std::vector> args; - Token token = unit->next_tok(); + Token token = unit->next_tok(); + TokenSource source = token.source; if (token.type != tok_identifier) { std::cerr << "error1" << std::endl; // TODO:异常处理 @@ -69,8 +63,9 @@ PrototypeAST *PrototypeAST::ParsePrototype(CompileUnit *unit, bool hasBody) token = *unit->icurTok; std::string name = token.tokenValue; std::pair pair; - pair.first = type; - pair.second = name; + type->inClass = parentClass; + pair.first = type; + pair.second = name; args.push_back(pair); } if (token.type != tok_syntax || token.tokenValue != ")") { @@ -102,36 +97,63 @@ PrototypeAST *PrototypeAST::ParsePrototype(CompileUnit *unit, bool hasBody) break; } } - returnTypes.push_back(TypeAST::ParseType(unit)); + TypeAST *returnType = TypeAST::ParseType(unit); + returnType->inClass = parentClass; + returnTypes.push_back(returnType); } } else { if (token.tokenValue == "{") { if (!hasBody) { - CompileError e("Unexpected function body", token.file, - token.lineno); + CompileError e("Unexpected function body", token.source); throw e; } } if (token.tokenValue == ";") { if (hasBody) { - CompileError e("Unexpected ;", token.file, token.lineno); + CompileError e("Unexpected ;", token.source); throw e; } } } - return new PrototypeAST(unit, FnName, args, returnTypes); + PrototypeAST *retV = + new PrototypeAST(unit, FnName, args, returnTypes, parentClass); + retV->source = source; + return retV; } -llvm::Function *PrototypeAST::Codegen() +llvm::Function *PrototypeAST::Codegen(std::vector igenericTypes) { + std::vector argStr; + for (std::pair pair : args) { + if (parentClass == nullptr) { + argStr.push_back(pair.first); + } else { + argStr.push_back( + parentClass->getRealType(pair.first, igenericTypes)); + } + } + std::string demangledName; + if (name != "main") { + if (parentClass == nullptr) { + demangledName = demangle(name, argStr); + } else { + demangledName = demangle( + name, argStr, parentClass->getRealNameForMangle(igenericTypes)); + } + } else { + demangledName = "main"; + } + std::vector llvmArgs; - for (int i = 0; i < args.size(); i++) { - llvmArgs.push_back(args[i].first->Codegen()); + for (int i = 0; i < argStr.size(); i++) { + llvmArgs.push_back(argStr[i]->Codegen()); } llvm::Type *returnType; if (returnDirectly) { if (returnTypes.size() > 1) { - CompileError e("return more than one type:"); + CompileError e( + "Prototype with \"S\" flag returned more than one values.", + source); throw e; } else if (returnTypes.size() == 0) { returnType = llvm::Type::getVoidTy(*unit->context); @@ -178,17 +200,5 @@ llvm::Function *PrototypeAST::Codegen() return 0; } }*/ - // todo:参数处理 - // Set names for all arguments. - - unsigned Idx = 0; - for (llvm::Function::arg_iterator AI = F->arg_begin(); Idx != args.size(); - ++AI, ++Idx) { - AI->setName(args[Idx].second); - - // Add arguments to variable symbol table. - // NamedValues[args[Idx]] = AI; - } - return F; } diff --git a/src/ast/PrototypeAST.h b/src/ast/PrototypeAST.h index 886d3f750c92d03faed8b65ec5e7955ba2323ced..e8044927accfeca74e13878deb20e4783bfd02a8 100644 --- a/src/ast/PrototypeAST.h +++ b/src/ast/PrototypeAST.h @@ -15,17 +15,19 @@ class PrototypeAST : public BaseAST public: PrototypeAST(CompileUnit *unit, const std::string &name, const std::vector> &args, - const std::vector &returnTypes); + const std::vector &returnTypes, + ClassAST * parentClass); virtual ~PrototypeAST(); - llvm::Function * Codegen(); - static PrototypeAST *ParsePrototype(CompileUnit *unit, bool hasBody); + llvm::Function * + Codegen(std::vector igenericTypes = std::vector()); + static PrototypeAST *ParsePrototype(CompileUnit *unit, bool hasBody, + ClassAST *parentClass = nullptr); std::vector> args; - std::string demangledName; - std::vector returnTypes; std::string name; bool returnDirectly; //直接返回 + ClassAST * parentClass; }; #endif /* COMPILER_AST_PROTOTYPEAST_H_ */ diff --git a/src/ast/SizeofExprAST.cpp b/src/ast/SizeofExprAST.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f1927b5b21f5de68d40cee0d48bcff71f8c65db --- /dev/null +++ b/src/ast/SizeofExprAST.cpp @@ -0,0 +1,31 @@ +/* + * SizeofExprAST.cpp + * + * Created on: Mar 6, 2021 + * Author: zbc + */ + +#include "SizeofExprAST.h" +#include "IntExprAST.h" +#include "TypeAST.h" + +SizeofExprAST::SizeofExprAST(CompileUnit *unit, TypeAST *Stype) : ExprAST(unit) +{ + this->Stype = Stype; +} + +SizeofExprAST::~SizeofExprAST() +{ + // TODO Auto-generated destructor stub +} + +std::vector SizeofExprAST::Codegen(llvm::IRBuilder<> *builder) +{ + this->type.clear(); + std::vector result; + this->type.push_back(new TypeAST(unit, "int")); + llvm::DataLayout *TD = new llvm::DataLayout(unit->module); + int size = TD->getTypeAllocSize(Stype->Codegen()); + result.push_back((new IntExprAST(unit, size))->Codegen(builder)[0]); + return result; +} diff --git a/src/ast/SizeofExprAST.h b/src/ast/SizeofExprAST.h new file mode 100644 index 0000000000000000000000000000000000000000..db3272ee80d94f0e61dbf9c9e280ccdd644a44da --- /dev/null +++ b/src/ast/SizeofExprAST.h @@ -0,0 +1,21 @@ +/* + * SizeofExprAST.h + * + * Created on: Mar 6, 2021 + * Author: zbc + */ + +#ifndef SRC_AST_SIZEOFEXPRAST_H_ +#define SRC_AST_SIZEOFEXPRAST_H_ + +#include "ExprAST.h" + +class SizeofExprAST : public ExprAST +{ + public: + SizeofExprAST(CompileUnit *unit, TypeAST *type); + virtual ~SizeofExprAST(); + std::vector Codegen(llvm::IRBuilder<> *builder); + TypeAST * Stype; +}; +#endif /* SRC_AST_SIZEOFEXPRAST_H_ */ diff --git a/src/ast/StringExprAST.cpp b/src/ast/StringExprAST.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3ebd21ea9aa4705d70142d03cc60f7f77f612dd4 --- /dev/null +++ b/src/ast/StringExprAST.cpp @@ -0,0 +1,111 @@ +/* + * StringExprAST.cpp + * + * Created on: Mar 14, 2021 + * Author: zbc + */ + +#include "StringExprAST.h" +#include "../CompileError.hpp" +#include "CallExprAST.h" +#include "IntExprAST.h" +#include "TypeAST.h" + +StringExprAST::StringExprAST(CompileUnit *unit, const std::string &str) + : ExprAST(unit) +{ + this->str = str; +} + +StringExprAST::~StringExprAST() +{ + // TODO Auto-generated destructor stub +} + +std::vector StringExprAST::Codegen(llvm::IRBuilder<> *builder) +{ + type.clear(); + + /*llvm::Constant * strArray = + llvm::ConstantDataArray::getString(unit->module->getContext(), str);*/ + llvm::Value *strArray = builder->CreateGlobalString(str); + + llvm::Function *function = builder->GetInsertBlock()->getParent(); + + llvm::IRBuilder<> sBuilder(&function->getEntryBlock(), + function->getEntryBlock().begin()); + + llvm::StructType *sType = + (llvm::StructType *)TypeAST( + unit, "array", std::vector{new TypeAST(unit, "char")}) + .Codegen(); + llvm::AllocaInst *array_alloca = sBuilder.CreateAlloca(sType); + llvm::AllocaInst *result_alloca = + sBuilder.CreateAlloca(TypeAST(unit, "string").Codegen()); + std::string dname = + "_alolang_C5arrayE4initP5array4chare3inte"; // todo:硬编码 + llvm::Function *CalleeF = unit->module->getFunction(dname); + if (CalleeF == 0) { + CompileError e("Function " + dname + + " not found in LLVM IR when building string"); + throw e; + } + std::vector args; + args.push_back(array_alloca); + args.push_back((new IntExprAST(unit, str.length()))->Codegen(builder)[0]); + builder->CreateCall(CalleeF, args); + llvm::IntegerType *itype = llvm::IntegerType::get(*unit->context, 32); + llvm::IntegerType *itype64 = llvm::IntegerType::get(*unit->context, 64); + + std::vector genericTypes = std::vector(); + genericTypes.push_back(new TypeAST(unit, "char")); + llvm::Value *startPointer = builder->CreateLoad(builder->CreateGEP( + sType, array_alloca, + std::vector{llvm::ConstantInt::get(itype, 0, true), + llvm::ConstantInt::get(itype, 0, true), + llvm::ConstantInt::get(itype, 0, true)})); + llvm::Value *strValue = builder->CreateGEP( + llvm::ArrayType::get(llvm::IntegerType::get(*unit->context, 8), + str.length() + 1), + strArray, + std::vector{llvm::ConstantInt::get(itype64, 0, true), + llvm::ConstantInt::get(itype64, 0, true)}); + // llvm::Value *strValue = builder->CreateGlobalString(str); + dname = "__alolang_inner_load_string"; // todo:硬编码 + llvm::Function *CalleeF2 = unit->module->getFunction(dname); + if (CalleeF2 == nullptr) { + llvm::FunctionType *FT = llvm::FunctionType::get( + TypeAST(unit, "int").Codegen(), + std::vector{ + llvm::PointerType::get( + llvm::IntegerType::get(*unit->context, 8), 0), + llvm::IntegerType::get(*unit->context, 64)}, + false); + CalleeF2 = + llvm::Function::Create(FT, llvm::GlobalValue::ExternalLinkage, + "__alolang_inner_load_string", unit->module); + } + std::vector args2; + args2.push_back(strValue); + // args2.push_back(llvm::ConstantInt::get(itype64, 0, true)); + args2.push_back(startPointer); + llvm::Value *ret = builder->CreateCall(CalleeF2, args2); + builder->CreateStore( + ret, builder->CreateGEP(sType, array_alloca, + std::vector{ + llvm::ConstantInt::get(itype, 0, true), + llvm::ConstantInt::get(itype, 1, true)})); + //制作结果 + this->type.push_back(new TypeAST(unit, "string")); + // todo:待优化 + std::vector result; + builder->CreateStore( + builder->CreateLoad(array_alloca), + builder->CreateGEP(TypeAST(unit, "string").Codegen(), result_alloca, + std::vector{ + llvm::ConstantInt::get(itype, 0, true), + llvm::ConstantInt::get(itype, 0, true)})); + llvm::Value *resultValue = builder->CreateLoad(result_alloca); + result.push_back(resultValue); + return result; +} diff --git a/src/ast/StringExprAST.h b/src/ast/StringExprAST.h new file mode 100644 index 0000000000000000000000000000000000000000..cd6c29552251257a46c4eae4d45998b9a7f85fd1 --- /dev/null +++ b/src/ast/StringExprAST.h @@ -0,0 +1,22 @@ +/* + * StringExprAST.h + * + * Created on: Mar 14, 2021 + * Author: zbc + */ + +#ifndef SRC_AST_STRINGEXPRAST_H_ +#define SRC_AST_STRINGEXPRAST_H_ + +#include "ExprAST.h" + +class StringExprAST : public ExprAST +{ + public: + StringExprAST(CompileUnit *unit, const std::string &str); + virtual ~StringExprAST(); + std::vector Codegen(llvm::IRBuilder<> *builder); + std::string str; +}; + +#endif /* SRC_AST_STRINGEXPRAST_H_ */ diff --git a/src/ast/TypeAST.cpp b/src/ast/TypeAST.cpp index b6235b932a4dda81faf0d50f34f9ed3b7e2a19a0..8cd2c26aeaa1ecf4db3b1a72de1a3d4c4e3f09ae 100644 --- a/src/ast/TypeAST.cpp +++ b/src/ast/TypeAST.cpp @@ -11,33 +11,19 @@ #include "CompileUnit.h" TypeAST::TypeAST(CompileUnit *unit, std::string baseClass, - std::vector genericTypes) + std::vector genericTypes, ClassAST *inClass) : BaseAST(unit) { this->baseClass = baseClass; this->genericTypes = genericTypes; this->pointee = nullptr; - initName(); - //生成name -} - -void TypeAST::initName() -{ - this->name = baseClass; - if (genericTypes.size() != 0) { - this->name += "<"; - for (unsigned int i = 0; i < genericTypes.size() - 1; i++) { - this->name += genericTypes[i]->name + ","; - } - this->name += genericTypes[genericTypes.size() - 1]->name + ">"; - } + this->inClass = inClass; } TypeAST::TypeAST(CompileUnit *unit, TypeAST *pointee) : BaseAST(unit) { this->pointee = pointee; - //生成name - this->name = pointee->name + "*"; + this->inClass = nullptr; } TypeAST::~TypeAST() @@ -46,17 +32,23 @@ TypeAST::~TypeAST() } llvm::Type *TypeAST::Codegen() { + TypeAST *realType = this; + if (inClass != nullptr) { + realType = inClass->getRealType(realType); + } if (pointee == nullptr) { //非指针类型 - auto typeAST = unit->types.find(name); + auto typeAST = unit->types.find(realType->getName()); if (typeAST == unit->types.end()) { //没有找到实例化过的泛型 - auto classAST = unit->classes.find(baseClass); + auto classAST = unit->classes.find(realType->baseClass); if (classAST == unit->classes.end()) { - CompileError e("can't find class:" + baseClass); + CompileError e("can't find class:" + realType->baseClass, + source); throw e; } else { - llvm::Type *classType = classAST->second->Codegen(genericTypes); + llvm::Type *classType = + classAST->second->Codegen(realType->genericTypes); return classType; //构建泛型 } @@ -64,16 +56,16 @@ llvm::Type *TypeAST::Codegen() return typeAST->second; } } else { - return llvm::PointerType::get(pointee->Codegen(), 0); + return llvm::PointerType::get(realType->pointee->Codegen(), 0); } } -TypeAST *TypeAST::ParseType(CompileUnit *unit) +TypeAST *TypeAST::ParseType(CompileUnit *unit, ClassAST *inClass) { - Token token = *unit->icurTok; + Token token = *unit->icurTok; + TokenSource source = token.source; if (token.type != tok_identifier) { - CompileError e("Expected type but got " + token.dump(), token.file, - token.lineno); + CompileError e("Expected type but got " + token.dump(), token.source); throw e; } std::string baseClass = token.tokenValue; @@ -83,16 +75,72 @@ TypeAST *TypeAST::ParseType(CompileUnit *unit) if (token.type == tok_syntax && token.tokenValue == "<") { unit->next_tok(); - while (!(token.type == tok_syntax && token.tokenValue == ">")) { + while (true) { genericTypes.push_back(TypeAST::ParseType(unit)); token = *unit->icurTok; + if (token.type == tok_syntax) { + if (token.tokenValue == ",") { + token = unit->next_tok(); + } else if (token.tokenValue == ">") { + break; + } else { + CompileError e("Unknown token " + token.dump(), + token.source); + throw e; + } + } } token = unit->next_tok(); } - TypeAST *result = new TypeAST(unit, baseClass, genericTypes); + TypeAST *result = new TypeAST(unit, baseClass, genericTypes, inClass); + result->source = source; while (token.type == tok_syntax && token.tokenValue == "*") { result = new TypeAST(unit, result); token = unit->next_tok(); } return result; } + +std::string TypeAST::getName() +{ + TypeAST *realType = this; + if (inClass != nullptr) { + realType = inClass->getRealType(realType); + } + + std::string name = realType->baseClass; + if (realType->genericTypes.size() != 0) { + name += "<"; + for (unsigned int i = 0; i < realType->genericTypes.size() - 1; i++) { + name += realType->genericTypes[i]->getName() + ","; + } + name += realType->genericTypes[realType->genericTypes.size() - 1] + ->getName() + + ">"; + } + return name; +} + +std::string TypeAST::getMangleName() +{ + TypeAST *realType = this; + if (inClass != nullptr) { + realType = inClass->getRealType(realType); + } + std::stringstream ss; + if (realType->pointee == nullptr) { + ss << realType->baseClass.length() << realType->baseClass; + if (realType->genericTypes.size() != 0) { + for (unsigned int i = 0; i < realType->genericTypes.size(); i++) { + std::string name = realType->genericTypes[i]->getName(); + ss << name.length() << name; + } + } + ss << "e"; + return ss.str(); + } else { + ss << "P"; + ss << realType->pointee->getMangleName(); + return ss.str(); + } +} diff --git a/src/ast/TypeAST.h b/src/ast/TypeAST.h index ea0269ab6ed1d7cdd9b2342c9b4d3d75f4baaa06..3185c53b2e894f75402bcaf93701a4d0b472b9a4 100644 --- a/src/ast/TypeAST.h +++ b/src/ast/TypeAST.h @@ -14,18 +14,21 @@ class TypeAST : public BaseAST { public: TypeAST(CompileUnit *unit, std::string baseClass, - std::vector genericTypes = std::vector()); + std::vector genericTypes = std::vector(), + ClassAST * inClass = nullptr); TypeAST(CompileUnit *unit, TypeAST *pointee); virtual ~TypeAST(); - static TypeAST *ParseType(CompileUnit *unit); - void initName(); + static TypeAST *ParseType(CompileUnit *unit, ClassAST *inClass = nullptr); + + llvm::Type *Codegen(); + std::string getMangleName(); + std::string getName(); - llvm::Type * Codegen(); - std::string name; std::string baseClass; std::vector innerType; std::vector genericTypes; TypeAST * pointee; //指向的类型 + ClassAST * inClass; }; #endif /* SRC_AST_TYPEAST_H_ */ diff --git a/src/ast/UnaryExprAST.cpp b/src/ast/UnaryExprAST.cpp index 1aa70f976584d15fc2055a6dadb2b66b3f1e94c4..8285c43a9f70b570ce0c643ddcdcc1227e692803 100644 --- a/src/ast/UnaryExprAST.cpp +++ b/src/ast/UnaryExprAST.cpp @@ -33,71 +33,37 @@ UnaryExprAST::~UnaryExprAST() { // TODO Auto-generated destructor stub } +llvm::Value *UnaryExprAST::getAlloca(llvm::IRBuilder<> *builder) +{ + if (op == "*") { + type.clear(); + llvm::Value *ret = operand->Codegen(builder)[0]; + type.push_back(operand->type[0]->pointee); + return ret; + } else { + CompileError e("Operator " + op + " can not be used as assignment", + source); + throw e; + } +} std::vector UnaryExprAST::Codegen(llvm::IRBuilder<> *builder) { + type.clear(); std::vector result; if (op == "&") { - if (VariableExprAST *v = dynamic_cast(operand)) { - result.push_back(v->getAlloca()); - this->type.push_back(new TypeAST(unit, operand->type[0])); - } else if (MemberExprAST *v = dynamic_cast(operand)) { - llvm::Value * pointer; - std::vector chain; - ExprAST * curAST = operand; - while (true) { - chain.push_back(curAST); - if (MemberExprAST *v = dynamic_cast(curAST)) { - curAST = v->LHS; - } else if (VariableExprAST *v = - dynamic_cast(curAST)) { - break; - } else { - CompileError e("Unknown AST."); - throw e; - } - } - VariableExprAST *start = - dynamic_cast(chain[chain.size() - 1]); - pointer = start->getAlloca(); - std::vector idx; - std::string curType = start->type[0]->baseClass; - for (int i = chain.size() - 2; i >= 0; i--) { - MemberExprAST *v = dynamic_cast(chain[i]); - std::string member = v->member; - ClassAST * baseClass = unit->classes[curType]; - auto memberAST = baseClass->members.find(member); - if (memberAST == baseClass->members.end()) { - CompileError e("Member" + member + " not found."); - throw e; - } - unsigned int index = - std::distance(std::begin(baseClass->members), memberAST); - idx.push_back(index); - curType = baseClass->members[member]->variableType->name; - } - std::vector idxl; - llvm::IntegerType * itype = - llvm::IntegerType::get(*unit->context, 32); - - idxl.push_back(llvm::ConstantInt::get(itype, 0, true)); - for (unsigned int pid : idx) { - idxl.push_back(llvm::ConstantInt::get(itype, pid, true)); - } - if (idx.size() != 0) { - pointer = builder->CreateGEP(start->type[0]->Codegen(), pointer, - idxl); - } - result.push_back(pointer); - } else { - CompileError e("& can only be used with variable"); + llvm::Value *pointer = operand->getAlloca(builder); + if (pointer == nullptr) { + CompileError e("No memory allocaed", source); throw e; } + type.push_back(new TypeAST(unit, operand->type[0])); + result.push_back(pointer); } else { //值操作 std::vector Rs = operand->CodegenChain(builder); if (Rs.size() != 1) { - CompileError e("Unary Expr length != 1"); + CompileError e("Unary Expr length != 1", source); throw e; } @@ -106,13 +72,13 @@ std::vector UnaryExprAST::Codegen(llvm::IRBuilder<> *builder) result.push_back(builder->CreateXor(Rs[0], 1)); } else if (op == "*") { if (operand->type[0]->pointee == nullptr) { - CompileError e("operator * must be used on pointer"); + CompileError e("operator * must be used on pointer", source); throw e; } this->type.push_back(operand->type[0]->pointee); result.push_back(builder->CreateLoad(Rs[0])); } else { - CompileError e("一元运算符:" + op + "未实现"); + CompileError e("一元运算符:" + op + "未实现", source); throw e; } } diff --git a/src/ast/UnaryExprAST.h b/src/ast/UnaryExprAST.h index 7db1f325375782b300f9304ca7a2b8d7aa2403aa..6e4ad57f74e78bacacbdf4f67ef79c97d9991a46 100644 --- a/src/ast/UnaryExprAST.h +++ b/src/ast/UnaryExprAST.h @@ -16,6 +16,8 @@ class UnaryExprAST : public ExprAST UnaryExprAST(CompileUnit *unit, const std::string &op, ExprAST *operand, bool leftop); virtual ~UnaryExprAST(); + virtual llvm::Value *getAlloca(llvm::IRBuilder<> *builder); + std::vector Codegen(llvm::IRBuilder<> *builder); std::string op; ExprAST * operand; diff --git a/src/ast/VariableDefExprAST.cpp b/src/ast/VariableDefExprAST.cpp index f7c1c299284a4730dcd5b891f44cf1d92b88242a..dce4a5b015b96488fbd54107a4d51b2767b0c943 100644 --- a/src/ast/VariableDefExprAST.cpp +++ b/src/ast/VariableDefExprAST.cpp @@ -9,6 +9,7 @@ #include "../CompileError.hpp" #include "CodeBlockAST.h" +#include "FunctionAST.h" #include "IntExprAST.h" #include "TypeAST.h" #include @@ -40,7 +41,8 @@ static llvm::AllocaInst *CreateEntryBlockAlloca(CompileUnit * unit, { llvm::IRBuilder<> builder(&function->getEntryBlock(), function->getEntryBlock().begin()); - return builder.CreateAlloca(typeAST->Codegen(), 0, VarName.c_str()); + llvm::Type * varType = typeAST->Codegen(); + return builder.CreateAlloca(varType, 0, VarName.c_str()); } std::vector @@ -51,16 +53,16 @@ VariableDefExprAST::Codegen(llvm::IRBuilder<> *builder) *unit->module, variableType->Codegen(), false, llvm::GlobalValue::ExternalLinkage, nullptr, idName); // todo:初始填0 - if (variableType->name == "int") { + if (variableType->getName() == "int") { llvm::IntegerType *itype = llvm::IntegerType::get(*unit->context, 64); llvm::ConstantInt *res = llvm::ConstantInt::get(itype, 0, true); gVar->setInitializer(res); - } else if (variableType->name == "double") { + } else if (variableType->getName() == "double") { llvm::Type * ftype = llvm::Type::getDoubleTy(*unit->context); llvm::Constant *res = llvm::ConstantFP::get(ftype, 0); gVar->setInitializer(res); - } else if (variableType->name == "bool") { + } else if (variableType->getName() == "bool") { llvm::IntegerType *itype = llvm::IntegerType::get(*unit->context, 1); llvm::ConstantInt *res = llvm::ConstantInt::get(itype, 0, true); @@ -100,6 +102,9 @@ VariableDefExprAST *VariableDefExprAST::ParseVar(CompileUnit * unit, CodeBlockAST *codeblock) { TypeAST *typeAST = TypeAST::ParseType(unit); + if (codeblock != nullptr) { + typeAST->inClass = codeblock->baseFunction->parentClass; + } Token nexToken = *(unit->icurTok); std::string idName = nexToken.tokenValue; @@ -115,13 +120,13 @@ VariableDefExprAST *VariableDefExprAST::ParseVar(CompileUnit * unit, unit->next_tok(); initValue = ExprAST::ParseExpression(unit, codeblock, false); } else { - CompileError e("Unknown token:" + nexToken.dump(),nexToken.file,nexToken.lineno); + CompileError e("Unknown token:" + nexToken.dump(), nexToken.source); throw e; } } std::cout << std::left << std::setw(35) << "Variable definition found:" << idName - << " with type:" << typeAST->name << std::endl; + << " with type:" << typeAST->baseClass << std::endl; return new VariableDefExprAST(unit, codeblock, idName, typeAST, initValue); } diff --git a/src/ast/VariableExprAST.cpp b/src/ast/VariableExprAST.cpp index fbe3c5d0ae9a8810a30e61ab80e34cd84d32c3c6..3bdb2b896762a4f16c3cbea6d161c476a3c9d786 100644 --- a/src/ast/VariableExprAST.cpp +++ b/src/ast/VariableExprAST.cpp @@ -19,7 +19,6 @@ VariableExprAST::VariableExprAST(CompileUnit *unit, CodeBlockAST *codeblock, { this->idName = idName; this->codeblock = codeblock; - this->alloca = nullptr; } VariableExprAST::~VariableExprAST() @@ -27,11 +26,9 @@ VariableExprAST::~VariableExprAST() // TODO Auto-generated destructor stub } -llvm::Value *VariableExprAST::getAlloca() +llvm::Value *VariableExprAST::getAlloca(llvm::IRBuilder<> *builder) { - if (alloca != nullptr) { - return alloca; - } + type.clear(); //找局部变量 CodeBlockAST *curCodeBlock = codeblock; while (curCodeBlock != nullptr) { @@ -39,11 +36,8 @@ llvm::Value *VariableExprAST::getAlloca() if (varAST == curCodeBlock->namedValues.end()) { curCodeBlock = curCodeBlock->parent; } else { - alloca = varAST->second.second; + llvm::Value *alloca = varAST->second.second; type.push_back(varAST->second.first); - if (varAST->second.first->name == "") { - std::cout << "fuck" << std::endl; - } return alloca; } } @@ -54,14 +48,13 @@ llvm::Value *VariableExprAST::getAlloca() throw e; } else { type.push_back(gVar->second.first); - alloca = gVar->second.second; - return alloca; + return gVar->second.second; } } std::vector VariableExprAST::Codegen(llvm::IRBuilder<> *builder) { std::vector result; - result.push_back(builder->CreateLoad(getAlloca())); + result.push_back(builder->CreateLoad(getAlloca(builder))); return result; } diff --git a/src/ast/VariableExprAST.h b/src/ast/VariableExprAST.h index 5b4de5e6629f888db40a8302fb96e1a6ca262a9c..082db1ce45a096a23ec97fed5e017489a777a236 100644 --- a/src/ast/VariableExprAST.h +++ b/src/ast/VariableExprAST.h @@ -15,13 +15,10 @@ class VariableExprAST : public ExprAST VariableExprAST(CompileUnit *unit, CodeBlockAST *codeblock, const std::string &idName); virtual ~VariableExprAST(); - llvm::Value * getAlloca(); + virtual llvm::Value * getAlloca(llvm::IRBuilder<> *builder); std::vector Codegen(llvm::IRBuilder<> *builder); std::string idName; CodeBlockAST * codeblock; - - private: - llvm::Value *alloca; }; #endif /* COMPILER_AST_VARIABLEEXPRAST_H_ */ diff --git a/src/ast/WhileExprAST.cpp b/src/ast/WhileExprAST.cpp index 585ade162a9dd780a5b2e1fefc137e948ecaf3e5..263a22c885da46ef46eb5cb76d14008835e6d96a 100644 --- a/src/ast/WhileExprAST.cpp +++ b/src/ast/WhileExprAST.cpp @@ -39,7 +39,7 @@ std::vector WhileExprAST::Codegen(llvm::IRBuilder<> *builder) std::vector conditionValues = condition->CodegenChain(builder); if (conditionValues.size() != 1) { - CompileError e("Multi/Void type in condition found."); + CompileError e("Multi/Void type in condition found.", source); throw e; } builder->CreateCondBr(conditionValues[0], bodyBB, MergeBB); @@ -57,6 +57,7 @@ WhileExprAST *WhileExprAST::ParseWhileExpr(CompileUnit * unit, { unit->next_tok(); ExprAST * condition = ExprAST::ParseExpression(unit, parent, false); - CodeBlockAST *body = CodeBlockAST::ParseCodeBlock(unit, "", parent); + CodeBlockAST *body = + CodeBlockAST::ParseCodeBlock(unit, "", parent->baseFunction, parent); return new WhileExprAST(unit, parent, condition, body); } diff --git a/src/ipc_Stuff/genproto.cpp b/src/ipc_Stuff/genproto.cpp new file mode 100644 index 0000000000000000000000000000000000000000..98cbef734c773b5473d79f1038841e6446b5f06d --- /dev/null +++ b/src/ipc_Stuff/genproto.cpp @@ -0,0 +1,36 @@ +#include "genproto.h" +#include +#include + +std::map alot_to_protot{{"int", "int64"}, + {"double", "double"}, + {"char", "int32"}, + {"byte", "int32"}, + {"pointer", "uint64"}}; + +proto::proto() +{ + this->protostr = ""; + this->protostr += + R"(syntax = "proto3"; + )"; +} + +void proto::addType(std::string typenamestr, + std::vector membertype) +{ + std::string typeMsg = ""; + typeMsg += (boost::format("message %1%\n") % typenamestr).str(); + typeMsg += "{\n"; + int li = 1; + for (auto mbs : membertype) { + auto tn = alot_to_protot.find(mbs) != alot_to_protot.end() + ? alot_to_protot[mbs] + : mbs; + typeMsg += + (boost::format(" %1% %2%_%3% = %3%;\n") % tn % mbs % li).str(); + li++; + } + typeMsg += "}\n"; + this->protostr += typeMsg += "\n"; +} \ No newline at end of file diff --git a/src/ipc_Stuff/genproto.h b/src/ipc_Stuff/genproto.h new file mode 100644 index 0000000000000000000000000000000000000000..d6e9d5128989c6bf41e0e2e2e7bec1fa068f88ad --- /dev/null +++ b/src/ipc_Stuff/genproto.h @@ -0,0 +1,11 @@ +#include +#include + +class proto +{ + public: + std::string protostr; + void addType(std::string typenamestr, std::vector membertype); + inline std::string getProto() { return this->protostr; }; + proto(); +}; \ No newline at end of file diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 5b0163357e1d47acf62f7a588ca92947cb0e2cd2..cd41ffe437264e29c4aee050368e6f3fe531d307 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -1,8 +1,11 @@ AUTOMAKE_OPTIONS = foreign -lib_LIBRARIES = libalolangcore.a -libalolangcore_a_SOURCES = testPuts.c +lib_LTLIBRARIES = libalolangcore.la +libalolangcore_la_SOURCES = unsafe.c io.c types.c rand.c ucs4support.cpp time.c +libalolangcore_la_LDFLAGS = -version-info 0:0:0 +# libalolangcore_la_CFLAGS = -fPIC +# libalolangcore_la_CXXFLAGS = -fPIC -alolanglibdir=$(libdir) -alolanglib_PROGRAMS = libalolangcore.so -libalolangcore_so_SOURCES = testPuts.c -libalolangcore_so_LDFLAGS = -shared -fpic +# alolanglibdir=$(libdir) +# alolanglib_PROGRAMS = libalolangcore.so +# libalolangcore_so_SOURCES = unsafe.c testPuts.c types.c testrand.c ucs4support.cpp +# libalolangcore_so_LDFLAGS = -shared -fPIC -static diff --git a/src/lib/array.alo b/src/lib/array.alo new file mode 100644 index 0000000000000000000000000000000000000000..ffa9f48a478308013263cdc85f05cf830e32565f --- /dev/null +++ b/src/lib/array.alo @@ -0,0 +1,122 @@ +%ifndef _ARRAY_ +%def _ARRAY_ + + +%import unsafe.alo +%import types.alo + +class array +{ + UnsafePointer ptr; // start + int sz; // current size + int cap; // current capacity + func _Desired_size_to_capacity(int _size) -> int + { + int u = floor(_size / 16); + return (u + 1) * 16; + // This is to be replcaced by the code below + // since the binary operators are implemented: + // return (_size >> 4) + 1 << 4; + } + func init(int _sz) + { + this->sz = _sz; + this->cap = this->_Desired_size_to_capacity(_sz); + this->ptr.malloc(this->cap); + return; + } + func init() + { + this->sz = 0; + this->cap = 16; + this->ptr.malloc(this->cap); + return; + } + func destroy() + { + this->ptr.free(); + this->sz = 0; + this->cap = 0; + return; + } + func size() -> int + { + return this->sz; + } + func capacity() -> int + { + return this->cap; + } + func data() -> A* + { + return this->ptr.load(); + } + func udata() -> UnsafePointer + { + return this->ptr; + } + func _Reallocate(int _Newsz) + { + this->cap = this->_Desired_size_to_capacity(_Newsz); + UnsafePointer newptr; + newptr.malloc(this->cap); + memcpy(this->ptr.addr, newptr.addr, this->sz * sizeof(A)); + this->ptr.free(); + this->ptr = newptr; + return; + } + func concat(A* _ptr, int _sz) + { + int newsz = this->sz + _sz; + if(newsz > this->cap) this->_Reallocate(newsz); + UnsafePointer _ptr_wrapper; + _ptr_wrapper.toObj(_ptr); + memcpy(_ptr_wrapper.addr, this->ptr.addr + this->sz * sizeof(A), _sz * sizeof(A)); + this->sz = newsz; + return; + } + func append(A obj) + { + this->concat(&obj, 1); + return; + } + func push_back(A obj) + { + this->concat(&obj, 1); + return; + } + func get(int _Index) -> A* + { + UnsafePointer cur; + cur.addr=this->ptr.addr+_Index * sizeof(A); + return cur.load(); + } + func pop_back() -> A + { + // TODO: + // if(this->sz < 1) throw some error; + UnsafePointer p; + p.addr = this->ptr.addr; + p.addr = p.addr + this->sz * sizeof(A) - sizeof(A); + this->sz = this->sz - 1; + return *(p.load()); + } + func erase_back(int _Size_to_erase) + { + // array = [0, 1, 2, 3, 4, 5, 6] + // array.erase_back(3) + // array = [0, 1, 2, 3] + this->sz = this->sz - _Size_to_erase; + return; + } + func back() -> A + { + // if(this->sz < 1) throw some error; + UnsafePointer p; + p.addr = this->ptr.addr; + p.addr = p.addr + this->sz * sizeof(A) - sizeof(A); + return *(p.load()); + } +} + +%endif \ No newline at end of file diff --git a/src/lib/io.alo b/src/lib/io.alo new file mode 100644 index 0000000000000000000000000000000000000000..b1762223a858a0bd08918ccb05da81eb8d77d00c --- /dev/null +++ b/src/lib/io.alo @@ -0,0 +1,13 @@ +%ifndef _IO_ +%def _IO_ + +extern func print(int i); +extern func print(double f); +extern func print(bool b); +extern func print(string s); +extern func print(char c); + +extern "S" func testGetInt() -> int; +extern "S" func testGetDouble() -> double; + +%endif \ No newline at end of file diff --git a/src/lib/io.c b/src/lib/io.c new file mode 100644 index 0000000000000000000000000000000000000000..8692b056cd5334f4c23120b4991918dc9a4729db --- /dev/null +++ b/src/lib/io.c @@ -0,0 +1,49 @@ +#include "types/alostring.h" +#include "ucs4support.h" +#include + +// print(int) +extern void _alolang_5print3inte(long long a) { printf("%lld\n", a); } + +// print(double) +extern void _alolang_5print6doublee(double a) { printf("%lf\n", a); } + +// print(string) +extern void _alolang_5print6stringe(struct alostring str) +{ + char buff[str.data.size * 4 + 1]; + string2char((int *)str.data.pointer.addr, str.data.size, buff); + printf("%s\n", buff); +}; + +// print(bool) +extern void _alolang_5print4boole(int a) +{ + if (a) { + printf("true\n"); + } else { + printf("false\n"); + } +} + +// print(char) +extern void _alolang_5print4chare(int alochar) +{ + char a[5]; + string2char(&alochar, 1, a); + printf("%s\n", a); +} + +extern long long _alolang_10testGetInte() +{ + long long a; + scanf("%lld", &a); + return a; +} + +extern double _alolang_13testGetDoublee() +{ + double a; + scanf("%lf", &a); + return a; +} diff --git a/src/lib/ipc/ipc.proto b/src/lib/ipc/ipc.proto new file mode 100644 index 0000000000000000000000000000000000000000..ed47844d2635556f2e9db567fcf8dd8d5a78d4b3 --- /dev/null +++ b/src/lib/ipc/ipc.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +message msg +{ + int64 version = 1; + int64 length = 2; + int64 command = 3; + message Data + { + int64 id = 1; + bytes dat = 2; + } + repeated Data data = 4; +} \ No newline at end of file diff --git a/src/lib/ipc/ipcpy/ipc_pb2.py b/src/lib/ipc/ipcpy/ipc_pb2.py new file mode 100644 index 0000000000000000000000000000000000000000..d4155c56490be078c307d8e86259bfafcf46f4e7 --- /dev/null +++ b/src/lib/ipc/ipcpy/ipc_pb2.py @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: ipc.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='ipc.proto', + package='', + syntax='proto3', + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\tipc.proto\"q\n\x03msg\x12\x0f\n\x07version\x18\x01 \x01(\x03\x12\x0e\n\x06length\x18\x02 \x01(\x03\x12\x0f\n\x07\x63ommand\x18\x03 \x01(\x03\x12\x17\n\x04\x64\x61ta\x18\x04 \x03(\x0b\x32\t.msg.Data\x1a\x1f\n\x04\x44\x61ta\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0b\n\x03\x64\x61t\x18\x02 \x01(\x0c\x62\x06proto3' +) + + + + +_MSG_DATA = _descriptor.Descriptor( + name='Data', + full_name='msg.Data', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='id', full_name='msg.Data.id', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='dat', full_name='msg.Data.dat', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=95, + serialized_end=126, +) + +_MSG = _descriptor.Descriptor( + name='msg', + full_name='msg', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='version', full_name='msg.version', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='length', full_name='msg.length', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='command', full_name='msg.command', index=2, + number=3, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='data', full_name='msg.data', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_MSG_DATA, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=13, + serialized_end=126, +) + +_MSG_DATA.containing_type = _MSG +_MSG.fields_by_name['data'].message_type = _MSG_DATA +DESCRIPTOR.message_types_by_name['msg'] = _MSG +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +msg = _reflection.GeneratedProtocolMessageType('msg', (_message.Message,), { + + 'Data' : _reflection.GeneratedProtocolMessageType('Data', (_message.Message,), { + 'DESCRIPTOR' : _MSG_DATA, + '__module__' : 'ipc_pb2' + # @@protoc_insertion_point(class_scope:msg.Data) + }) + , + 'DESCRIPTOR' : _MSG, + '__module__' : 'ipc_pb2' + # @@protoc_insertion_point(class_scope:msg) + }) +_sym_db.RegisterMessage(msg) +_sym_db.RegisterMessage(msg.Data) + + +# @@protoc_insertion_point(module_scope) diff --git a/src/lib/ipc/ipcpy/listen.py b/src/lib/ipc/ipcpy/listen.py new file mode 100644 index 0000000000000000000000000000000000000000..cbb4c8ef35337758dcc79da534cdcc4caa10e7a8 --- /dev/null +++ b/src/lib/ipc/ipcpy/listen.py @@ -0,0 +1,27 @@ +import os +import time + +def listen(pipename): + try: + rd = os.open(pipename, os.O_RDONLY) + except IOError: + print("不存在指定管道") + else: + fl = 0 + a='' + while True: + s = os.read(rd, 128) + if (len(s) == 0): + fl+=1 + time.sleep(1) + else: + fl == 0 + a += s + if (fl == 3): + os.close(rd) + return a + + + + + \ No newline at end of file diff --git a/src/lib/rand.alo b/src/lib/rand.alo new file mode 100644 index 0000000000000000000000000000000000000000..e23e7fe4d32c590408eaae5656ba1895845e630f --- /dev/null +++ b/src/lib/rand.alo @@ -0,0 +1,6 @@ +%ifndef _RAND_ +%def _RAND_ + +extern "S" func rand() -> int; + +%endif \ No newline at end of file diff --git a/src/lib/rand.c b/src/lib/rand.c new file mode 100644 index 0000000000000000000000000000000000000000..8947b1d32f67df0c41bcba85f162245c116491d7 --- /dev/null +++ b/src/lib/rand.c @@ -0,0 +1,2 @@ +#include +extern long long _alolang_4rand(void) { return rand(); } diff --git a/src/lib/string.alo b/src/lib/string.alo new file mode 100644 index 0000000000000000000000000000000000000000..fa4048418b621e7680e29345ac60611b8f86acb5 --- /dev/null +++ b/src/lib/string.alo @@ -0,0 +1,20 @@ +%ifndef _STRING_ +%def _STRING_ + +%import array.alo + +class string +{ + //private: + array data; + func length()->int + { + return this->data.size(); + } + func charAt(int index)->char + { + return *this->data.get(index); + } +} + +%endif \ No newline at end of file diff --git a/src/lib/testPuts.c b/src/lib/testPuts.c deleted file mode 100644 index 2fab4eec8ab5527d0c1a9571b9ad39ec9c9f4b85..0000000000000000000000000000000000000000 --- a/src/lib/testPuts.c +++ /dev/null @@ -1,28 +0,0 @@ -#include - -extern void _alolang_8testPuts(void) { puts("AloLang Test Function"); } - -extern void _alolang_12testPrintInt3int(long long a) { printf("%lld\n", a); } -extern void _alolang_15testPrintDouble6double(double a) { printf("%lf\n", a); } -extern void _alolang_13testPrintBool4bool(int a) -{ - if (a) { - printf("true\n"); - } else { - printf("false\n"); - } -} - -extern int _alolang_10testGetInt() -{ - int a; - scanf("%d", &a); - return a; -} - -extern double _alolang_13testGetDouble() -{ - double a; - scanf("%lf", &a); - return a; -} \ No newline at end of file diff --git a/src/lib/time.alo b/src/lib/time.alo new file mode 100644 index 0000000000000000000000000000000000000000..136b2cdf3aad664ba97666e3690f45f54e47ec7b --- /dev/null +++ b/src/lib/time.alo @@ -0,0 +1,6 @@ +%ifndef _TIME_ +%def _TIME_ + +extern "S" func time() -> int; + +%endif \ No newline at end of file diff --git a/src/lib/time.c b/src/lib/time.c new file mode 100644 index 0000000000000000000000000000000000000000..22b4c9510b19cbcf31141edef4fa825f941b63fc --- /dev/null +++ b/src/lib/time.c @@ -0,0 +1,22 @@ +/* + * time.c + * + * Created on: Mar 18, 2021 + * Author: zbc + */ + +#include +#include +#include +#include + +int64_t currentTimeMillis() +{ + struct timeval time; + gettimeofday(&time, NULL); + int64_t s1 = (int64_t)(time.tv_sec) * 1000; + int64_t s2 = (time.tv_usec / 1000); + return s1 + s2; +} + +extern long long _alolang_4time(void) { return currentTimeMillis(); } diff --git a/src/lib/types.alo b/src/lib/types.alo new file mode 100644 index 0000000000000000000000000000000000000000..f109ddbc2915ff6aa70cfeddea2793960d34bf98 --- /dev/null +++ b/src/lib/types.alo @@ -0,0 +1,19 @@ +%ifndef _TYPES_ +%def _TYPES_ + +extern "S" func _cdouble2int(double v)->int; + +//返回一个小于传入参数的最大整数 +func floor(double v)->int{ + double v1=0.0; + if(v % 1.0 >= 0.0) + { + v1=v%1.0; + }else{ + v1=1.0 + v % 1.0; + } + double t= v - v1; + return _cdouble2int(t); +} + +%endif \ No newline at end of file diff --git a/src/lib/types.c b/src/lib/types.c new file mode 100644 index 0000000000000000000000000000000000000000..780ca50092d342a88be2069786596f8c7d26f76b --- /dev/null +++ b/src/lib/types.c @@ -0,0 +1,8 @@ +/* + * types.c + * + * Created on: Mar 8, 2021 + * Author: zbc + */ + +extern long long _alolang_12_cdouble2int6doublee(double v) { return (int)v; } diff --git a/src/lib/types/alostring.h b/src/lib/types/alostring.h new file mode 100644 index 0000000000000000000000000000000000000000..5de2cbc768370dd132af80da3a908fd48d0d7dbb --- /dev/null +++ b/src/lib/types/alostring.h @@ -0,0 +1,22 @@ +/* + * alostring.h + * + * Created on: Mar 18, 2021 + * Author: zbc + */ + +#ifndef SRC_LIB_TYPES_ALOSTRING_H_ +#define SRC_LIB_TYPES_ALOSTRING_H_ + +struct aloptr { + long long addr; +}; +struct aloarray_char { + struct aloptr pointer; + long long size; +}; +struct alostring { + struct aloarray_char data; +}; + +#endif /* SRC_LIB_TYPES_ALOSTRING_H_ */ diff --git a/src/lib/ucs4support.cpp b/src/lib/ucs4support.cpp new file mode 100644 index 0000000000000000000000000000000000000000..599d3b94d9ee91a66a4d463b4dee3b4aa22ecb2f --- /dev/null +++ b/src/lib/ucs4support.cpp @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include +#include +#include +// #include + +typedef int mfchar_t; // 无符号的4字节,用于容纳UCS-4的一个字符 +typedef std::u32string mfstring; // 自定义的UCS-4字符串 + +// 把utf-8编码的字符串转换成UCS-4编码的字符串 +unsigned int UTF8ToUCS4(const std::string &src, mfchar_t *dest) +{ + mfchar_t w = 0; + mfchar_t err = '?'; // 表转码错误 + int bytes = 0; // 表剩余要处理的字节数 + unsigned int curIndex = 0; + + for (size_t i = 0; i < src.length(); i++) { + unsigned char c = (unsigned char)src[i]; + + if (c <= 0x7f) // <= 0x0111 1111(即127)的说明是ascii码 + { + // 若bytes不为0,说明出错,因为ascii码的utf-8编码只占一个字节 + if (bytes) { + dest[curIndex++] = err; + bytes = 0; + } + + // 将字符压入队列 + dest[curIndex++] = c; + } else if (c <= 0xbf) // <= 0x1011 + // 1111,说明是多字节的utf-8编码的第2,3,4,5,6字节 + { + // 既然是2,3,4,5,6字节,bytes必不为0,否则出错 + if (bytes) { + // 取出c的后六位,将w左移6位,做或预算,赋值给w,这样w就融合了c的后6位 + w = ((w << 6) | (c & 0x3f)); + + // 字节数减1,因为本字节已经融合完毕 + bytes--; + + // 若后面没有字节数了,说明字节数融合完毕,成为一个完整的ucs-4的字符了,压入队列 + if (bytes == 0) { + dest[curIndex++] = w; + } + } else { + dest[curIndex++] = err; // 出错 + } + } else if (c <= + 0xdf) // <= 0x1101 1111,说明是2字节的utf-8编码的第一个字节 + { + bytes = 1; // 标记后面还有1个字节,下面类似 + w = c & + 0x1f; // 取出后5位,注意是赋值操作,所以w的高位都将赋值为0。然后将 + // w 与后面字节的后六位融合即可,下面类似 + } else if (c <= + 0xef) // <= 0x1110 1111,说明是3字节的utf-8编码的第一个字节 + { + bytes = 2; + w = c & 0x0f; // 取出后4位 + } else if (c <= + 0xf7) // <= 0x1111 0111,说明是4字节的utf-8编码的第一个字节 + { + bytes = 3; + w = c & 0x07; // 取出后3位 + } else if (c <= + 0xfb) // <= 0x1111 1011,说明是5字节的utf-8编码的第一个字节 + { + bytes = 4; + w = c & 0x03; // 取出后2位 + } else if (c <= + 0xfd) // <= 0x1111 1101,说明是6字节的utf-8编码的第一个字节 + { + bytes = 5; + w = c & 0x01; // 取出后1位 + } else // > 0x1111 1101的是出错,因utf-8最多6个字节 + { + dest[curIndex++] = err; + bytes = 0; + } + } + + if (bytes) { + dest[curIndex++] = err; + } + return curIndex; +} + +std::string UCS4ToUTF8(const std::u32string &s) +{ + std::wstring_convert, char32_t> conv; + return conv.to_bytes(s); +} + +// TODO: Support for other chatsets + +extern "C" void string2char(int *data, long long length, char *dst) +{ + std::u32string src; + for (long long i = 0; i < length; i++) { + src.push_back(data[i]); + } + std::string result = UCS4ToUTF8(src); + std::strncpy(dst, result.c_str(), result.length() + 1); +} + +extern "C" long long char2string(char *str, int *dest) +{ + return UTF8ToUCS4(std::string(str), dest); +} + +// for alolang + +extern "C" long long __alolang_inner_load_string(char *str, long long addr) +{ + return char2string(str, (int *)addr); +} diff --git a/src/lib/ucs4support.h b/src/lib/ucs4support.h new file mode 100644 index 0000000000000000000000000000000000000000..563ee05cad79beb969f68958b071110e51a62425 --- /dev/null +++ b/src/lib/ucs4support.h @@ -0,0 +1,14 @@ +/* + * ucs4support.h + * + * Created on: Mar 18, 2021 + * Author: zbc + */ + +#ifndef SRC_LIB_UCS4SUPPORT_H_ +#define SRC_LIB_UCS4SUPPORT_H_ + +extern long long char2string(char *str, int *dest); +extern void string2char(int *data, long long length, char *dst); + +#endif /* SRC_LIB_UCS4SUPPORT_H_ */ diff --git a/src/lib/unsafe.alo b/src/lib/unsafe.alo new file mode 100644 index 0000000000000000000000000000000000000000..0a940c05e464608d44cab57171e2c4e44b1308f8 --- /dev/null +++ b/src/lib/unsafe.alo @@ -0,0 +1,50 @@ +%ifndef _UNSAFE_ +%def _UNSAFE_ + + +extern func __cfree(int addr); +extern func __cmalloc(int size)->int; +extern func __cmemcpy(int src,int dst,int size); + +func memcpy(int src,int dst,int size) +{ + __cmemcpy(src,dst,size); + return; +} + +class UnsafePointer +{ + int addr; + func __alolang_inner_load()->A* + { + //编译器实现 + } + /*func __alolang_inner_set(A data){ + //编译器实现 + }*/ + func __alolang_inner_toObj(A* pointer) + { + //编译器实现 + } + func load()->A* + { + return this->__alolang_inner_load(); + } + func toObj(A* pointer) + { + this->__alolang_inner_toObj(pointer); + return; + } + func malloc(int count) + { + this->addr=__cmalloc(count*sizeof(A)); + return; + } + func free() + { + __cfree(this->addr); + return; + } +} + +%endif \ No newline at end of file diff --git a/src/lib/unsafe.c b/src/lib/unsafe.c new file mode 100644 index 0000000000000000000000000000000000000000..018dde40795e0ca716a4f99446df63be46b8f81d --- /dev/null +++ b/src/lib/unsafe.c @@ -0,0 +1,27 @@ +/* + * unsafe.c + * + * Created on: Mar 7, 2021 + * Author: zbc + */ +#include +#include + +extern void _alolang_9__cmemcpy3inte3inte3inte(long long src, long long dst, + long long size) +{ + memcpy((void *)dst, (void *)src, size); +} + +extern void _alolang_7__cfree3inte(long long addr) { free((void *)addr); } + +struct addr { + long long addr; +}; + +extern struct addr _alolang_9__cmalloc3inte(long long size) +{ + struct addr retValue; + retValue.addr = (long long)malloc(size); + return retValue; +} diff --git a/src/preprocessor.cpp b/src/preprocessor.cpp index 2e5be87785def17314480878f09845248b17ad1a..ec2f99fcd9a37c6af90009c246db5fd8f89e4538 100644 --- a/src/preprocessor.cpp +++ b/src/preprocessor.cpp @@ -1,7 +1,9 @@ #include "preprocessor.h" +#include "boost/filesystem.hpp" #include "utils.h" #include #include + std::ifstream t_fin__; std::map variable; @@ -32,20 +34,25 @@ std::pair genFactor(const std::string &line) } } -std::vector processPreInstruction(const std::string &line, int cnt, int lineno) +std::vector processPreInstruction(const std::string &line, int cnt, + int lineno, const std::string &FN) { + boost::filesystem::path curFile(FN); std::pair instruction = genFactor(line); //解析后的预编译指令 if (instruction.first == "import") { - t_fin__.open(instruction.second); + std::string realPath = + curFile.parent_path().string() + "/" + instruction.second; + t_fin__.open(realPath); if (!t_fin__.is_open()) { - CompileError e("import file " + instruction.second + " not found"); + CompileError e("import file " + realPath + " not found", + TokenSource(FN, lineno)); throw e; } std::string importFileContent; std::getline(t_fin__, importFileContent, char(EOF)); t_fin__.close(); - return preProcess(importFileContent, cnt + 1, instruction.second); + return preProcess(importFileContent, cnt + 1, realPath); } else if (instruction.first == "def") { //解析宏定义 std::string var, data; @@ -68,7 +75,7 @@ std::vector processPreInstruction(const std::string &line, int cnt, int l data = instruction.second.substr(i + 1, len - i - 1); } variable[var] = data; - return std::vector{Tline(std::pair("",lineno),"")}; + return std::vector{Tline(TokenSource("", lineno), "")}; } else if (instruction.first == "rmdef") { if (instruction.second.length() == 0) { CompileError e("no second instruction"); @@ -80,7 +87,7 @@ std::vector processPreInstruction(const std::string &line, int cnt, int l throw e; //找不到宏定义 } - return std::vector{Tline(std::pair("",lineno),"")}; + return std::vector{Tline(TokenSource("", lineno), "")}; } else if (instruction.first == "ifdef") { if (instruction.second.length() == 0) { CompileError e("no second instruction"); @@ -93,7 +100,7 @@ std::vector processPreInstruction(const std::string &line, int cnt, int l closeifstack++; } currentifstack++; - return std::vector{Tline(std::pair("",lineno),"")}; + return std::vector{Tline(TokenSource("", lineno), "")}; } else if (instruction.first == "ifndef") { if (instruction.second.length() == 0) { CompileError e("no second instruction"); @@ -106,7 +113,7 @@ std::vector processPreInstruction(const std::string &line, int cnt, int l closeifstack++; } currentifstack++; - return std::vector{Tline(std::pair("",lineno),"")}; + return std::vector{Tline(TokenSource("", lineno), "")}; } else if (instruction.first == "endif") { if (currentifstack == 0) { CompileError e("no second instruction"); @@ -116,9 +123,10 @@ std::vector processPreInstruction(const std::string &line, int cnt, int l closeifstack--; } currentifstack--; - return std::vector{Tline(std::pair("",lineno),"")}; + return std::vector{Tline(TokenSource("", lineno), "")}; } else { - CompileError e("Unrecognized preprocessor command"); + CompileError e("Unrecognized preprocessor command " + + instruction.first); throw e; } } @@ -169,7 +177,7 @@ std::vector preProcess(const std::string &code, int cnt, std::string FN) std::vector processedLines; std::string temp; bool isCommented = false; - int lineno = 0; + int lineno = 0; while (std::getline(buft_fin__, temp)) { lineno++; if (closeifstack > 0 && temp.substr(0, 6) != "%endif" && @@ -178,9 +186,11 @@ std::vector preProcess(const std::string &code, int cnt, std::string FN) } if (temp[0] == '%') { auto processedPreInstruction = - processPreInstruction(temp, cnt, lineno); + processPreInstruction(temp, cnt, lineno, FN); if (processedPreInstruction.size() > 0) - std::move(processedPreInstruction.begin(), processedPreInstruction.end(), std::back_inserter(processedLines)); + std::move(processedPreInstruction.begin(), + processedPreInstruction.end(), + std::back_inserter(processedLines)); } else { std::string replaced = doReplace(temp); //处理块注释 @@ -219,7 +229,8 @@ std::vector preProcess(const std::string &code, int cnt, std::string FN) } int plen = result.length(); if (plen > 0) { - processedLines.push_back(Tline(std::pair(FN,lineno),result)); + processedLines.push_back( + Tline(TokenSource(FN, lineno), result)); } } temp.erase(); diff --git a/src/preprocessor.h b/src/preprocessor.h index 6d56b80744c2a2fb799db53f12e2a97eb449fc6a..2e6fcdbfe2d10a3be5a37fda858096a87c047ca7 100644 --- a/src/preprocessor.h +++ b/src/preprocessor.h @@ -1,17 +1,17 @@ #ifndef _PREPROCESSOR_ #define _PREPROCESSOR_ +#include "TokenSource.h" #include #include #include -#include -#include #include #include +#include +#include -typedef std::pair,std::string> Tline; +typedef std::pair Tline; std::vector preProcess(const std::string &code, int cnt, std::string FN); - #endif diff --git a/src/utils.cpp b/src/utils.cpp index 65a81c796d57a6ea0b1ff3f08d744e6a0eaede9d..2067389a2f1b11b6558c0d679921aaf4867308c2 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -15,13 +15,18 @@ char syntax[] = {'!', '%', '^', '&', '*', '(', ')', '+', '=', '{', ',', '<', '>', '?', '.', '/', '#', ' '}; std::string demangle(const std::string & fnName, - const std::vector &argTypes) + const std::vector &argTypes, + const std::string & className) { std::stringstream ss; ss << "_alolang_"; + if (className != "") { + ss << className; + } ss << fnName.length() << fnName; for (TypeAST *word : argTypes) { - ss << word->name.length() << word->name; //得到类型 + std::string mangleName = word->getMangleName(); + ss << mangleName; //得到类型 } return ss.str(); } diff --git a/src/utils.h b/src/utils.h index 2532903573307d1c0ddd2994c9ba375f56f2627c..789b988281745299c685937405f44a720ddb47c3 100644 --- a/src/utils.h +++ b/src/utils.h @@ -13,14 +13,11 @@ #include std::string demangle(const std::string & fnName, - const std::vector &argTypes); + const std::vector &argTypes, + const std::string & className = ""); bool isSyntax(char c); void skipSpace(const std::vector &words, long unsigned int &i); void skipSpace(std::istream &in); -template inline bool instanceof (const T *) -{ - return std::is_base_of::value; -} #endif /* COMPILER_UTILS_H_ */ diff --git a/src/yacc_stuff/tokenizer.lpp b/src/yacc_stuff/tokenizer.lpp index f2f0d44d564babde562b98c94b73231d291362c0..b12145b25d453f0fdd02e3a11fbc04d42e868efe 100644 --- a/src/yacc_stuff/tokenizer.lpp +++ b/src/yacc_stuff/tokenizer.lpp @@ -27,6 +27,7 @@ foreach token = tok_key_foreach; return token goto token = tok_key_goto; return token; if token = tok_key_if; return token; while token = tok_key_while; return token; +sizeof token = tok_key_sizeof; return token; case|switch token = tok_key_switch; return token; @@ -37,6 +38,7 @@ func token = tok_fun; return token extern token = tok_extern; return token; return token = tok_return; return token; [a-zA-Z_][a-zA-Z_0-9]* token = tok_identifier; return token; +0\.[0-9]+ token = tok_number; return token; 0b[01]+ token = tok_number; return token; 0x[1-9a-fA-F][0-9a-fA-F]* token = tok_number; return token; 0B[01]+ token = tok_number; return token; @@ -46,6 +48,8 @@ return token = tok_return; return token 0 token = tok_number; return token; -> token = tok_syntax; return token; +\<\< token = tok_syntax; return token; +>> token = tok_syntax; return token; == token = tok_syntax; return token; != token = tok_syntax; return token; \>= token = tok_syntax; return token; diff --git a/test/classanytype.alo b/test/classanytype.alo index 92f0abc934229c7b34b5dcad12ec38a39f33e181..c384ddeb208fe923fe6dd52fb0c34060ee5ffa16 100644 --- a/test/classanytype.alo +++ b/test/classanytype.alo @@ -27,6 +27,10 @@ func main() { testPrintInt((*(test1.pred)).data); testPrintInt(*testint1); + node> test4; + test4.data = test1; + testPrintInt(test4.data.data); + if (true) testPrintInt(114514); diff --git a/test/perfcheck/demo.py b/test/perfcheck/demo.py old mode 100755 new mode 100644 index 05a458900412dae123b2d62ce6f179795859ce7c..819afe870ba813fb362edc5f4e27c6b213910b0b --- a/test/perfcheck/demo.py +++ b/test/perfcheck/demo.py @@ -1,6 +1,6 @@ -#!/usr/bin/python - -a = 0 -while a < 100000000: - a = a + 1 +#!/usr/bin/python + +a = 0 +while a < 100000000: + a = a + 1 print(a) \ No newline at end of file diff --git a/test/unsafetest.alo b/test/unsafetest.alo new file mode 100644 index 0000000000000000000000000000000000000000..6e5d4ef7876a65c4267b2128e08adfc10f0a9966 --- /dev/null +++ b/test/unsafetest.alo @@ -0,0 +1,50 @@ +%import ../src/lib/testio.alo +%import ../src/lib/unsafe.alo + +class node { + UnsafePointer> pred; + UnsafePointer> succ; + A data; +} + +func main() { + int i = 0; + UnsafePointer> init; + init.malloc(1); + init.load()->data = 0; + UnsafePointer> curs; + curs = init; + while (i < 20){ + i = i + 1; + UnsafePointer> next; + next.malloc(1); + next.load()->data = i; + curs.load()->succ = next; + next.load()->pred = curs; + curs = next; + } + + curs = init; + i = 0; + while (i < 20){ + testPrintInt(curs.load()->data); + curs = curs.load()->succ; + i = i + 1; + } + + while (i > 0){ + testPrintInt(curs.load()->data); + curs = curs.load()->pred; + i = i - 1; + } + + curs = init.load()->succ; + i = 0; + + while (i < 20){ + testPrintInt(i); + curs.load()->pred.free(); + curs = curs.load()->succ; + i = i + 1; + } +} \ No newline at end of file diff --git a/tools/demangle b/tools/demangle old mode 100755 new mode 100644 index 8a6a8ce9de531187bdfae7913f40c6b8754ed464..5aea898bd347d8654a8b2d4f090d43910f68e995 Binary files a/tools/demangle and b/tools/demangle differ