diff --git a/example/merge_sort.cc b/example/merge_sort.cc index 6fe018f..0d0850e 100644 --- a/example/merge_sort.cc +++ b/example/merge_sort.cc @@ -6,6 +6,7 @@ #include "wamon/scanner.h" #include "wamon/type_checker.h" #include "wamon/variable.h" +#include "wamon/variable_list.h" int main() { std::string script = R"( diff --git a/include/wamon/inner_type_method.h b/include/wamon/inner_type_method.h index ba25576..d2a0e77 100644 --- a/include/wamon/inner_type_method.h +++ b/include/wamon/inner_type_method.h @@ -10,7 +10,7 @@ namespace wamon { -class PackageUnit; +class Interpreter; class InnerTypeMethod { public: @@ -21,8 +21,8 @@ class InnerTypeMethod { using CheckType = std::function(const std::unique_ptr& builtin_type, const std::vector>& params_type)>; - using HandleType = std::function( - std::shared_ptr& obj, std::vector>&&, const PackageUnit&)>; + using HandleType = std::function(std::shared_ptr& obj, + std::vector>&&, Interpreter&)>; std::string GetHandleId(const std::unique_ptr& builtintype, const std::string& method_name) const { std::string handle_id; diff --git a/include/wamon/interpreter.h b/include/wamon/interpreter.h index 2297353..2233b61 100644 --- a/include/wamon/interpreter.h +++ b/include/wamon/interpreter.h @@ -223,7 +223,7 @@ class Interpreter { std::vector>&& params) { auto method = InnerTypeMethod::Instance().Get(obj, method_name); EnterContext(obj->GetTypeInfo() + "::" + method_name); - auto ret = method(obj, std::move(params), pu_); + auto ret = method(obj, std::move(params), *this); LeaveContext(); return ret->IsRValue() ? std::move(ret) : ret->Clone(); } diff --git a/include/wamon/variable.h b/include/wamon/variable.h index 8f9c2f2..abcbf7c 100644 --- a/include/wamon/variable.h +++ b/include/wamon/variable.h @@ -223,124 +223,6 @@ inline PointerVariable* AsPointerVariable(const std::shared_ptr& v) { return static_cast(v.get()); } -class ListVariable : public CompoundVariable { - public: - ListVariable(std::unique_ptr&& element_type, ValueCategory vc, Interpreter& ip, const std::string& name) - : CompoundVariable(std::make_unique(element_type->Clone()), vc, name), - element_type_(std::move(element_type)), - ip_(ip) {} - - void PushBack(std::shared_ptr element); - - void PopBack(); - - size_t Size() const { return elements_.size(); } - - void Resize(size_t new_size) { - size_t old_size = Size(); - if (new_size == old_size) { - return; - } else if (new_size < old_size) { - elements_.resize(new_size); - } else { - for (size_t i = 0; i < (new_size - old_size); ++i) { - auto v = VariableFactory(element_type_, vc_, "", ip_); - v->DefaultConstruct(); - elements_.push_back(std::move(v)); - } - } - } - - void Clear() { elements_.clear(); } - - void Erase(size_t index) { - if (index >= elements_.size()) { - throw WamonException("List.Erase error, index out of range : {} >= {}", index, elements_.size()); - } - auto it = elements_.begin(); - std::advance(it, index); - elements_.erase(it); - } - - void Insert(size_t index, std::shared_ptr v) { - if (index > Size()) { - throw WamonException("List.Insert error, index = {}, size = {}", index, Size()); - } - - std::shared_ptr tmp; - if (v->IsRValue()) { - tmp = v; - } else { - tmp = v->Clone(); - } - tmp->ChangeTo(vc_); - auto it = elements_.begin(); - std::advance(it, index); - elements_.insert(it, std::move(tmp)); - } - - std::shared_ptr at(size_t i) { - if (i >= Size()) { - throw WamonException("ListVariable.at error, index {} out of range", i); - } - return elements_[i]; - } - - std::string get_string_only_for_byte_list(); - - void ConstructByFields(const std::vector>& fields) override; - - void DefaultConstruct() override; - - std::shared_ptr Clone() override; - - bool Compare(const std::shared_ptr& other) override { - check_compare_type_match(other); - ListVariable* list_v = static_cast(other.get()); - if (elements_.size() != list_v->elements_.size()) { - return false; - } - for (size_t i = 0; i < elements_.size(); ++i) { - if (elements_[i]->Compare((list_v->elements_)[i]) == false) { - return false; - } - } - return true; - } - - void Assign(const std::shared_ptr& other) override { - check_compare_type_match(other); - ListVariable* list_v = static_cast(other.get()); - elements_.clear(); - for (size_t i = 0; i < list_v->elements_.size(); ++i) { - // PushBack函数会处理值型别 - PushBack(list_v->elements_[i]); - } - } - - void ChangeTo(ValueCategory vc) override { - vc_ = vc; - for (auto& each : elements_) { - each->ChangeTo(vc); - } - } - - nlohmann::json Print() override { - nlohmann::json list; - for (size_t i = 0; i < elements_.size(); ++i) { - list.push_back(elements_[i]->Print()); - } - return list; - } - - private: - std::unique_ptr element_type_; - std::vector> elements_; - Interpreter& ip_; -}; - -inline ListVariable* AsListVariable(const std::shared_ptr& v) { return static_cast(v.get()); } - class FunctionVariable : public CompoundVariable { public: struct capture_item { diff --git a/include/wamon/variable_list.h b/include/wamon/variable_list.h new file mode 100644 index 0000000..8d984d3 --- /dev/null +++ b/include/wamon/variable_list.h @@ -0,0 +1,124 @@ +#pragma once + +#include "wamon/interpreter.h" +#include "wamon/variable.h" + +namespace wamon { + +class ListVariable : public CompoundVariable { + public: + ListVariable(std::unique_ptr&& element_type, ValueCategory vc, const std::string& name) + : CompoundVariable(std::make_unique(element_type->Clone()), vc, name), + element_type_(std::move(element_type)) {} + + void PushBack(std::shared_ptr element); + + void PopBack(); + + size_t Size() const { return elements_.size(); } + + void Resize(size_t new_size, Interpreter& ip) { + size_t old_size = Size(); + if (new_size == old_size) { + return; + } else if (new_size < old_size) { + elements_.resize(new_size); + } else { + for (size_t i = 0; i < (new_size - old_size); ++i) { + auto v = VariableFactory(element_type_, vc_, "", ip); + v->DefaultConstruct(); + elements_.push_back(std::move(v)); + } + } + } + + void Clear() { elements_.clear(); } + + void Erase(size_t index) { + if (index >= elements_.size()) { + throw WamonException("List.Erase error, index out of range : {} >= {}", index, elements_.size()); + } + auto it = elements_.begin(); + std::advance(it, index); + elements_.erase(it); + } + + void Insert(size_t index, std::shared_ptr v) { + if (index > Size()) { + throw WamonException("List.Insert error, index = {}, size = {}", index, Size()); + } + + std::shared_ptr tmp; + if (v->IsRValue()) { + tmp = v; + } else { + tmp = v->Clone(); + } + tmp->ChangeTo(vc_); + auto it = elements_.begin(); + std::advance(it, index); + elements_.insert(it, std::move(tmp)); + } + + std::shared_ptr at(size_t i) { + if (i >= Size()) { + throw WamonException("ListVariable.at error, index {} out of range", i); + } + return elements_[i]; + } + + std::string get_string_only_for_byte_list(); + + void ConstructByFields(const std::vector>& fields) override; + + void DefaultConstruct() override; + + std::shared_ptr Clone() override; + + bool Compare(const std::shared_ptr& other) override { + check_compare_type_match(other); + ListVariable* list_v = static_cast(other.get()); + if (elements_.size() != list_v->elements_.size()) { + return false; + } + for (size_t i = 0; i < elements_.size(); ++i) { + if (elements_[i]->Compare((list_v->elements_)[i]) == false) { + return false; + } + } + return true; + } + + void Assign(const std::shared_ptr& other) override { + check_compare_type_match(other); + ListVariable* list_v = static_cast(other.get()); + elements_.clear(); + for (size_t i = 0; i < list_v->elements_.size(); ++i) { + // PushBack函数会处理值型别 + PushBack(list_v->elements_[i]); + } + } + + void ChangeTo(ValueCategory vc) override { + vc_ = vc; + for (auto& each : elements_) { + each->ChangeTo(vc); + } + } + + nlohmann::json Print() override { + nlohmann::json list; + for (size_t i = 0; i < elements_.size(); ++i) { + list.push_back(elements_[i]->Print()); + } + return list; + } + + private: + std::unique_ptr element_type_; + std::vector> elements_; +}; + +inline ListVariable* AsListVariable(const std::shared_ptr& v) { return static_cast(v.get()); } + +} // namespace wamon \ No newline at end of file diff --git a/src/builtin_functions.cc b/src/builtin_functions.cc index 1f3cd01..a1f2d28 100644 --- a/src/builtin_functions.cc +++ b/src/builtin_functions.cc @@ -3,13 +3,13 @@ #include #include -#include "nlohmann/json.hpp" #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" +#include "wamon/variable_list.h" namespace wamon { diff --git a/src/inner_type_method.cc b/src/inner_type_method.cc index b86fcc3..f008d86 100644 --- a/src/inner_type_method.cc +++ b/src/inner_type_method.cc @@ -1,7 +1,10 @@ #include "wamon/inner_type_method.h" +#include + #include "wamon/exception.h" #include "wamon/package_unit.h" +#include "wamon/variable_list.h" namespace wamon { @@ -140,14 +143,14 @@ static void register_builtin_type_method_check(std::unordered_map& handles) { handles[concat("string", "len")] = [](std::shared_ptr& obj, std::vector>&& params, - const PackageUnit& pu) -> std::shared_ptr { + Interpreter& ip) -> std::shared_ptr { assert(params.empty()); int ret = AsStringVariable(obj)->GetValue().size(); return std::make_shared(ret, Variable::ValueCategory::RValue, ""); }; handles[concat("string", "at")] = [](std::shared_ptr& obj, std::vector>&& params, - const PackageUnit& pu) -> std::shared_ptr { + Interpreter& ip) -> std::shared_ptr { assert(params.size() == 1); const std::string& v = AsStringVariable(obj)->GetValue(); int index = AsIntVariable(params[0])->GetValue(); @@ -159,7 +162,7 @@ static void register_builtin_type_method_handle(std::unordered_map& obj, std::vector>&& params, - const PackageUnit& pu) -> std::shared_ptr { + Interpreter& ip) -> std::shared_ptr { assert(params.size() == 1); std::string& v = AsStringVariable(obj)->GetValue(); if (IsStringType(params[0]->GetType())) { @@ -173,14 +176,14 @@ static void register_builtin_type_method_handle(std::unordered_map& obj, std::vector>&& params, - const PackageUnit& pu) -> std::shared_ptr { + Interpreter& ip) -> std::shared_ptr { assert(params.empty()); int ret = AsListVariable(obj)->Size(); return std::make_shared(ret, Variable::ValueCategory::RValue, ""); }; handles[concat("list", "at")] = [](std::shared_ptr& obj, std::vector>&& params, - const PackageUnit& pu) -> std::shared_ptr { + Interpreter& ip) -> std::shared_ptr { assert(params.size() == 1); int index = AsIntVariable(params[0])->GetValue(); return AsListVariable(obj)->at(index); @@ -188,7 +191,7 @@ static void register_builtin_type_method_handle(std::unordered_map& obj, std::vector>&& params, - const PackageUnit& pu) -> std::shared_ptr { + Interpreter& ip) -> std::shared_ptr { assert(params.size() == 2); int index = AsIntVariable(params[0])->GetValue(); AsListVariable(obj)->Insert(index, params[1]); @@ -197,7 +200,7 @@ static void register_builtin_type_method_handle(std::unordered_map& obj, std::vector>&& params, - const PackageUnit& pu) -> std::shared_ptr { + Interpreter& ip) -> std::shared_ptr { assert(params.size() == 1); AsListVariable(obj)->PushBack(params[0]); return GetVoidVariable(); @@ -205,7 +208,7 @@ static void register_builtin_type_method_handle(std::unordered_map& obj, std::vector>&& params, - const PackageUnit& pu) -> std::shared_ptr { + Interpreter& ip) -> std::shared_ptr { assert(params.size() == 0); AsListVariable(obj)->PopBack(); return GetVoidVariable(); @@ -213,28 +216,28 @@ static void register_builtin_type_method_handle(std::unordered_map& obj, std::vector>&& params, - const PackageUnit& pu) -> std::shared_ptr { + Interpreter& ip) -> std::shared_ptr { assert(params.size() == 1); - AsListVariable(obj)->Resize(AsIntVariable(params[0])->GetValue()); + AsListVariable(obj)->Resize(AsIntVariable(params[0])->GetValue(), ip); return GetVoidVariable(); }; handles[concat("list", "erase")] = [](std::shared_ptr& obj, std::vector>&& params, - const PackageUnit& pu) -> std::shared_ptr { + Interpreter& ip) -> std::shared_ptr { assert(params.size() == 1); AsListVariable(obj)->Erase(AsIntVariable(params[0])->GetValue()); return GetVoidVariable(); }; handles[concat("list", "clear")] = [](std::shared_ptr& obj, std::vector>&& params, - const PackageUnit& pu) -> std::shared_ptr { + Interpreter& ip) -> std::shared_ptr { assert(params.size() == 0); AsListVariable(obj)->Clear(); return GetVoidVariable(); }; handles[concat("list", "empty")] = [](std::shared_ptr& obj, std::vector>&& params, - const PackageUnit& pu) -> std::shared_ptr { + Interpreter& ip) -> std::shared_ptr { assert(params.size() == 0); bool empty = AsListVariable(obj)->Size() == 0; return std::make_shared(empty, Variable::ValueCategory::RValue, ""); diff --git a/src/operator.cc b/src/operator.cc index 38fda11..688bee6 100644 --- a/src/operator.cc +++ b/src/operator.cc @@ -2,6 +2,7 @@ #include "wamon/interpreter.h" #include "wamon/operator_def.h" +#include "wamon/variable_list.h" namespace wamon { diff --git a/src/variable.cc b/src/variable.cc index 8beba77..7c49b98 100644 --- a/src/variable.cc +++ b/src/variable.cc @@ -1,5 +1,7 @@ #include "wamon/variable.h" +#include + #include #include "wamon/enum_def.h" @@ -9,6 +11,7 @@ #include "wamon/variable_byte.h" #include "wamon/variable_double.h" #include "wamon/variable_int.h" +#include "wamon/variable_list.h" #include "wamon/variable_string.h" #include "wamon/variable_void.h" @@ -56,7 +59,7 @@ std::shared_ptr VariableFactory(const std::unique_ptr& type, Var return std::make_unique(GetHoldType(type), vc, name); } if (IsListType(type)) { - return std::make_unique(GetElementType(type), vc, *ip, name); + return std::make_unique(GetElementType(type), vc, name); } if (IsFuncType(type)) { return std::make_unique(GetParamType(type), GetReturnType(type), vc, name); @@ -329,64 +332,6 @@ std::shared_ptr PointerVariable::Clone() { return ret; } -void ListVariable::PushBack(std::shared_ptr element) { - if (element->IsRValue()) { - elements_.push_back(std::move(element)); - } else { - elements_.push_back(element->Clone()); - } - elements_.back()->ChangeTo(vc_); -} - -void ListVariable::PopBack() { - if (elements_.empty()) { - throw WamonException("List pop back error, empty list"); - } - elements_.pop_back(); -} - -std::string ListVariable::get_string_only_for_byte_list() { - if (!IsByteType(element_type_)) { - throw WamonException("ListVariable.get_string_only_for_byte_list can only be called by List(byte) type"); - } - std::string ret; - for (auto& each : elements_) { - ret.push_back(char(AsByteVariable(each)->GetValue())); - } - return ret; -} - -void ListVariable::ConstructByFields(const std::vector>& fields) { - for (auto& each : fields) { - if (each->GetTypeInfo() != element_type_->GetTypeInfo()) { - throw WamonException("ListVariable::ConstructByFields error, type dismatch : {} != {}", each->GetTypeInfo(), - element_type_->GetTypeInfo()); - } - if (each->IsRValue()) { - elements_.push_back(std::move(each)); - } else { - elements_.push_back(each->Clone()); - } - elements_.back()->ChangeTo(vc_); - } -} - -void ListVariable::DefaultConstruct() { elements_.clear(); } - -std::shared_ptr ListVariable::Clone() { - std::vector> elements; - for (auto& each : elements_) { - if (each->IsRValue()) { - elements.push_back(std::move(each)); - } else { - elements.push_back(each->Clone()); - } - } - auto ret = std::make_shared(element_type_->Clone(), ValueCategory::RValue, ip_, ""); - ret->elements_ = std::move(elements); - return ret; -} - void FunctionVariable::ConstructByFields(const std::vector>& fields) { if (fields.size() != 1) { throw WamonException("FunctionVariable's ConstructByFields method error : fields.size() == {}", fields.size()); diff --git a/src/variable_list.cc b/src/variable_list.cc new file mode 100644 index 0000000..d23168d --- /dev/null +++ b/src/variable_list.cc @@ -0,0 +1,63 @@ +#include "wamon/variable_list.h" + +namespace wamon { + +void ListVariable::PushBack(std::shared_ptr element) { + if (element->IsRValue()) { + elements_.push_back(std::move(element)); + } else { + elements_.push_back(element->Clone()); + } + elements_.back()->ChangeTo(vc_); +} + +void ListVariable::PopBack() { + if (elements_.empty()) { + throw WamonException("List pop back error, empty list"); + } + elements_.pop_back(); +} + +std::string ListVariable::get_string_only_for_byte_list() { + if (!IsByteType(element_type_)) { + throw WamonException("ListVariable.get_string_only_for_byte_list can only be called by List(byte) type"); + } + std::string ret; + for (auto& each : elements_) { + ret.push_back(char(AsByteVariable(each)->GetValue())); + } + return ret; +} + +void ListVariable::ConstructByFields(const std::vector>& fields) { + for (auto& each : fields) { + if (each->GetTypeInfo() != element_type_->GetTypeInfo()) { + throw WamonException("ListVariable::ConstructByFields error, type dismatch : {} != {}", each->GetTypeInfo(), + element_type_->GetTypeInfo()); + } + if (each->IsRValue()) { + elements_.push_back(std::move(each)); + } else { + elements_.push_back(each->Clone()); + } + elements_.back()->ChangeTo(vc_); + } +} + +void ListVariable::DefaultConstruct() { elements_.clear(); } + +std::shared_ptr ListVariable::Clone() { + std::vector> elements; + for (auto& each : elements_) { + if (each->IsRValue()) { + elements.push_back(std::move(each)); + } else { + elements.push_back(each->Clone()); + } + } + auto ret = std::make_shared(element_type_->Clone(), ValueCategory::RValue, ""); + ret->elements_ = std::move(elements); + return ret; +} + +} // namespace wamon \ No newline at end of file diff --git a/test/interpreter_test.cc b/test/interpreter_test.cc index 51618a8..43a8183 100644 --- a/test/interpreter_test.cc +++ b/test/interpreter_test.cc @@ -7,6 +7,7 @@ #include "wamon/type_checker.h" #include "wamon/var_as.h" #include "wamon/variable.h" +#include "wamon/variable_list.h" TEST(interpreter, callfunction) { wamon::Scanner scan; diff --git a/test/variable_test.cc b/test/variable_test.cc index f472bf0..caf9bc4 100644 --- a/test/variable_test.cc +++ b/test/variable_test.cc @@ -9,6 +9,7 @@ #include "wamon/to_var.h" #include "wamon/type_checker.h" #include "wamon/var_as.h" +#include "wamon/variable_list.h" TEST(variable, list) { wamon::Scanner scan;