From 18e04d2fce3d15bcd87378afc2bdb7eb3f202921 Mon Sep 17 00:00:00 2001 From: chloro <13125187405@163.com> Date: Sat, 15 Jun 2024 05:01:02 +0800 Subject: [PATCH] support to_string(enum) --- BUILD | 18 +++++++++--------- TODO.md | 4 ++-- example/register_cpp_function.cc | 3 ++- include/wamon/builtin_functions.h | 7 +++++-- include/wamon/type_checker.h | 2 ++ src/builtin_functions.cc | 26 ++++++++++++++++++++------ src/package_unit.cc | 5 +++-- src/type_checker.cc | 4 ++-- test/builtin_function_test.cc | 25 +++++++++++++++++++++++++ test/interpreter_test.cc | 3 ++- 10 files changed, 72 insertions(+), 25 deletions(-) diff --git a/BUILD b/BUILD index 8cd50e6..ee91e31 100644 --- a/BUILD +++ b/BUILD @@ -26,15 +26,15 @@ cc_test( ], ) -#cc_binary( -# name = "catch2_test", -# srcs = glob(["catch2_test/*.cc"]), -# copts = WAMON_COPTS, -# deps = [ -# "@catch2//:catch2_main", -# ":wamon", -# ], -#) +cc_binary( + name = "catch2_test", + srcs = glob(["catch2_test/*.cc"]), + copts = WAMON_COPTS, + deps = [ + "@catch2//:catch2_main", + ":wamon", + ], +) cc_binary( name = "hello_world", diff --git a/TODO.md b/TODO.md index f01b3eb..69ac48e 100644 --- a/TODO.md +++ b/TODO.md @@ -39,5 +39,5 @@ * 返回类型为void时的return语句优化 * [done] 支持析构函数 * 支持内置函数assert -* 支持 enum to string -* 内置函数放置在wamon包名称中 +* [done] 支持 enum to string +* [done] 内置函数放置在wamon包名称中 diff --git a/example/register_cpp_function.cc b/example/register_cpp_function.cc index 624fbb2..dcee100 100644 --- a/example/register_cpp_function.cc +++ b/example/register_cpp_function.cc @@ -7,7 +7,8 @@ #include "wamon/type_checker.h" #include "wamon/variable.h" -auto my_cpp_func_check(const std::vector>& params_type) -> std::unique_ptr { +auto my_cpp_func_check(const wamon::PackageUnit&, const std::vector>& params_type) + -> std::unique_ptr { if (params_type.size() != 1) { throw wamon::WamonException("invalid params count {}", params_type.size()); } diff --git a/include/wamon/builtin_functions.h b/include/wamon/builtin_functions.h index 38514bf..b4e2d58 100644 --- a/include/wamon/builtin_functions.h +++ b/include/wamon/builtin_functions.h @@ -17,6 +17,7 @@ class Type; class FuncCallExpr; class TypeChecker; class Interpreter; +class PackageUnit; namespace detail { @@ -35,7 +36,8 @@ void MergeMap(std::unordered_map& map, std::unordered_map(Interpreter&, std::vector>&&)>; - using CheckType = std::function(const std::vector>& params_type)>; + using CheckType = + std::function(const PackageUnit&, const std::vector>& params_type)>; BuiltinFunctions(); @@ -45,7 +47,8 @@ class BuiltinFunctions { BuiltinFunctions& operator=(BuiltinFunctions&&) = default; - std::unique_ptr TypeCheck(const std::string& name, const std::vector>& params_type) const; + std::unique_ptr TypeCheck(const std::string& name, const PackageUnit& pu, + const std::vector>& params_type) const; bool Find(const std::string& name) const { return builtin_handles_.find(name) != builtin_handles_.end(); } diff --git a/include/wamon/type_checker.h b/include/wamon/type_checker.h index 4a6bdaf..f1b217d 100644 --- a/include/wamon/type_checker.h +++ b/include/wamon/type_checker.h @@ -35,6 +35,8 @@ class TypeChecker { friend std::unique_ptr CheckAndGetTypeForNewExpr(TypeChecker& tc, NewExpr* new_expr); friend std::unique_ptr CheckAndGetTypeForAllocExpr(TypeChecker& tc, AllocExpr* alloc_expr); friend std::unique_ptr CheckAndGetTypeForDeallocExpr(TypeChecker& tc, DeallocExpr* dealloc_expr); + friend std::unique_ptr CheckParamTypeAndGetResultTypeForFunction(const TypeChecker& tc, + FuncCallExpr* call_expr); friend class BuiltinFunctions; diff --git a/src/builtin_functions.cc b/src/builtin_functions.cc index 313322f..25d1a9c 100644 --- a/src/builtin_functions.cc +++ b/src/builtin_functions.cc @@ -7,6 +7,7 @@ #include "wamon/ast.h" #include "wamon/exception.h" #include "wamon/interpreter.h" +#include "wamon/package_unit.h" #include "wamon/type_checker.h" #include "wamon/variable.h" @@ -48,8 +49,13 @@ static auto _to_string(Interpreter& ip, std::vector>&& result = std::to_string(AsDoubleVariable(v)->GetValue()); } else if (IsBoolType(v->GetType())) { result = AsBoolVariable(v)->GetValue() == true ? "true" : "false"; - } else { + } else if (IsByteType(v->GetType())) { result.push_back(static_cast(AsByteVariable(v)->GetValue())); + } else { + auto enum_def = ip.GetPackageUnit().FindEnum(v->GetTypeInfo()); + assert(enum_def != nullptr); + const auto& enum_item = AsEnumVariable(v)->GetEnumItem(); + result = enum_def->GetEnumName() + ":" + enum_item; } return std::make_shared(result, wamon::Variable::ValueCategory::RValue, ""); } @@ -61,18 +67,21 @@ static void register_builtin_handles(const std::string& prefix, handles[prefix + "context_stack"] = _context_stack; } -static auto _print_check(const std::vector>& params_type) -> std::unique_ptr { +static auto _print_check(const PackageUnit& pu, const std::vector>& params_type) + -> std::unique_ptr { return TypeFactory::Get(); } -static auto _context_stack_check(const std::vector>& params_type) -> std::unique_ptr { +static auto _context_stack_check(const PackageUnit& pu, const std::vector>& params_type) + -> std::unique_ptr { if (params_type.size() != 0) { throw WamonException("context_stack type_check error, params_type.size() == {}", params_type.size()); } return TypeFactory>::Get(); } -static auto _to_string_check(const std::vector>& params_type) -> std::unique_ptr { +static auto _to_string_check(const PackageUnit& pu, const std::vector>& params_type) + -> std::unique_ptr { if (params_type.size() != 1) { throw WamonException("to_string type_check error ,params_type.size() == {}", params_type.size()); } @@ -80,6 +89,11 @@ static auto _to_string_check(const std::vector>& params_ty if (IsIntType(type) || IsDoubleType(type) || IsBoolType(type) || IsByteType(type)) { return TypeFactory::Get(); } + if (pu.FindEnum(type->GetTypeInfo()) == nullptr) { + throw WamonException("to_string type_check error, invalid type {}", type->GetTypeInfo()); + } else { + return TypeFactory::Get(); + } throw WamonException("to_string type_check error, type {} cant not be to_string", type->GetTypeInfo()); } @@ -97,13 +111,13 @@ void BuiltinFunctions::RegisterWamonBuiltinFunction(BuiltinFunctions& obj) { register_builtin_handles("wamon$", obj.builtin_handles_); } -std::unique_ptr BuiltinFunctions::TypeCheck(const std::string& name, +std::unique_ptr BuiltinFunctions::TypeCheck(const std::string& name, const PackageUnit& pu, const std::vector>& params_type) const { auto check = builtin_checks_.find(name); if (check == builtin_checks_.end()) { throw WamonException("BuiltinFunctions::TypeCheck error, not implemented {} now", name); } - return check->second(params_type); + return check->second(pu, params_type); } } // namespace wamon diff --git a/src/package_unit.cc b/src/package_unit.cc index cec8346..4cea152 100644 --- a/src/package_unit.cc +++ b/src/package_unit.cc @@ -54,8 +54,9 @@ void PackageUnit::RegisterCppFunctions(const std::string& name, std::unique_ptr< } auto ftype = func_type->Clone(); MoveWrapper mw(std::move(ftype)); - auto check_f = [name = name, - mw = mw](const std::vector>& params_type) mutable -> std::unique_ptr { + auto check_f = [name = name, mw = mw]( + const PackageUnit&, + const std::vector>& params_type) mutable -> std::unique_ptr { auto func_type = std::move(mw).Get(); auto par_type = GetParamType(func_type); size_t param_size = par_type.size(); diff --git a/src/type_checker.cc b/src/type_checker.cc index 4df57aa..f5e9f34 100644 --- a/src/type_checker.cc +++ b/src/type_checker.cc @@ -569,8 +569,8 @@ std::unique_ptr CheckParamTypeAndGetResultTypeForFunction(const TypeChecke for (auto& each : call_expr->parameters_) { param_types.push_back(tc.GetExpressionType(each.get())); } - return tc.GetStaticAnalyzer().GetPackageUnit().GetBuiltinFunctions().TypeCheck(id_expr->GenerateIdent(), - param_types); + return tc.GetStaticAnalyzer().GetPackageUnit().GetBuiltinFunctions().TypeCheck( + id_expr->GenerateIdent(), tc.GetStaticAnalyzer().GetPackageUnit(), param_types); } // would calcualte id_expr.type_ std::unique_ptr find_type = tc.GetExpressionType(call_expr->caller_.get()); diff --git a/test/builtin_function_test.cc b/test/builtin_function_test.cc index 1a81a38..b54d974 100644 --- a/test/builtin_function_test.cc +++ b/test/builtin_function_test.cc @@ -61,4 +61,29 @@ TEST(builtin_function, context_stack) { std::string dump_info = R"_(["__lambda_0main","main$func3","main$func2","main$ms::func_method","main$func1","global"])_"; EXPECT_EQ(v->Print().dump(), dump_info); +} + +TEST(builtin_function, to_string) { + using namespace wamon; + std::string script = R"( + package main; + + enum Color { + Red; + Blue; + } + )"; + Scanner scan; + auto tokens = scan.Scan(script); + auto pu = Parse(tokens); + pu = MergePackageUnits(std::move(pu)); + + TypeChecker tc(pu); + std::string reason; + EXPECT_EQ(tc.CheckAll(reason), true) << reason; + + Interpreter ip(pu); + auto v = ip.ExecExpression(tc, "main", "call wamon::to_string:(enum Color:Red)"); + EXPECT_EQ(v->GetTypeInfo(), "string"); + EXPECT_EQ(AsStringVariable(v)->GetValue(), "main$Color:Red"); } \ No newline at end of file diff --git a/test/interpreter_test.cc b/test/interpreter_test.cc index 60f4947..a60f877 100644 --- a/test/interpreter_test.cc +++ b/test/interpreter_test.cc @@ -710,7 +710,8 @@ TEST(interpreter, register_cpp_function) { pu.RegisterCppFunctions( "func111", - [](const std::vector>& params_type) -> std::unique_ptr { + [](const wamon::PackageUnit&, + const std::vector>& params_type) -> std::unique_ptr { if (params_type.size() != 1) { throw wamon::WamonException("invalid params count {}", params_type.size()); }