diff --git a/libs/interpreter/include/pslang/interpreter/context.hpp b/libs/interpreter/include/pslang/interpreter/context.hpp index 3405129..ae7c03d 100644 --- a/libs/interpreter/include/pslang/interpreter/context.hpp +++ b/libs/interpreter/include/pslang/interpreter/context.hpp @@ -54,4 +54,6 @@ namespace pslang::interpreter void dump(std::ostream & out, context const & context); + value zero_value(context & context, types::type const & type); + } diff --git a/libs/interpreter/source/context.cpp b/libs/interpreter/source/context.cpp index 0a94b76..c2caac4 100644 --- a/libs/interpreter/source/context.cpp +++ b/libs/interpreter/source/context.cpp @@ -1,9 +1,54 @@ #include +#include #include namespace pslang::interpreter { + namespace + { + + struct zero_value_visitor + { + interpreter::context & context; + + value operator()(types::unit_type const &) + { + return unit_value{}; + } + + template + value operator()(types::primitive_type_base const &) + { + return primitive_value{primitive_value_base{.value = {}}}; + } + + value operator()(types::array_type const & array_type) + { + array_value result{.element_type = array_type.element_type}; + for (std::uint64_t i = 0; i < array_type.size; ++i) + result.elements.push_back(std::make_unique(types::apply(*this, *array_type.element_type))); + return std::move(result); + } + + value operator()(types::function_type const &) + { + throw std::runtime_error("Cannot zero-initialize a function type"); + } + + value operator()(types::named_type const & named_type) + { + auto const & struct_data = context.scope_stack.at(named_type.level).structs.at(named_type.name); + + struct_value result{.struct_type = std::make_unique(named_type)}; + for (auto const & field : struct_data.fields) + result.fields[field.name] = std::make_unique(types::apply(*this, *field.type)); + return std::move(result); + } + }; + + } + context empty_context() { context result; @@ -27,4 +72,9 @@ namespace pslang::interpreter std::cout << std::flush; } + value zero_value(context & context, types::type const & type) + { + return types::apply(zero_value_visitor{context}, type); + } + } diff --git a/libs/interpreter/source/eval.cpp b/libs/interpreter/source/eval.cpp index 39a52a8..d23e751 100644 --- a/libs/interpreter/source/eval.cpp +++ b/libs/interpreter/source/eval.cpp @@ -514,6 +514,9 @@ namespace pslang::interpreter { if (auto jt = it->structs.find(identifier->name); jt != it->structs.end()) { + if (function_call.arguments.empty()) + return zero_value(context, types::named_type{.name = identifier->name, .level = identifier->level}); + if (jt->second.fields.size() != function_call.arguments.size()) { std::ostringstream os; diff --git a/libs/types/include/pslang/types/type_visitor.hpp b/libs/types/include/pslang/types/type_visitor.hpp index 31008e2..1a9bdea 100644 --- a/libs/types/include/pslang/types/type_visitor.hpp +++ b/libs/types/include/pslang/types/type_visitor.hpp @@ -14,19 +14,19 @@ namespace pslang::types Visitor & visitor; template - void operator()(Type const & type) + auto operator()(Type const & type) { - visitor(type); + return visitor(type); } - void operator()(types::primitive_type const & type) + auto operator()(types::primitive_type const & type) { - std::visit(*this, type); + return std::visit(*this, type); } - void operator()(types::type const & type) + auto operator()(types::type const & type) { - std::visit(*this, type); + return std::visit(*this, type); } }; @@ -36,36 +36,36 @@ namespace pslang::types Visitor & visitor; template - void operator()(Type & type) + auto operator()(Type & type) { - visitor(type); + return visitor(type); } - void operator()(types::primitive_type & type) + auto operator()(types::primitive_type & type) { - std::visit(*this, type); + return std::visit(*this, type); } - void operator()(types::type & type) + auto operator()(types::type & type) { - std::visit(*this, type); + return std::visit(*this, type); } }; } template - void apply(Visitor && visitor, type const & type) + auto apply(Visitor && visitor, type const & type) { detail::const_visitor_helper helper{visitor}; - helper(type); + return helper(type); } template - void apply(Visitor && visitor, type & type) + auto apply(Visitor && visitor, type & type) { detail::visitor_helper helper{visitor}; - helper(type); + return helper(type); } }