/* CrossLang is a dynamically-typed scripting language built on TessesFramework, named in honor of Jesus's sacrifice. Copyright (C) 2026 Mike Nolan SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "CrossLang.hpp" #include "TessesFramework/Serialization/BitConverter.hpp" #include "TessesFramework/Streams/ByteReader.hpp" #include "TessesFramework/Uuid.hpp" #include #include #include #include #include #include #include namespace Tesses::CrossLang { std::string ToString(std::shared_ptr gc, TObject o) { if (std::holds_alternative(o)) { return std::get(o).ToString(); } if (std::holds_alternative(o)) { return std::get(o); } if (std::holds_alternative(o)) { return std::get(o).ToString(); } if (std::holds_alternative(o)) { return std::to_string(std::get(o)); } if (std::holds_alternative(o)) { return std::to_string(std::get(o)); } if (std::holds_alternative(o)) { return std::string{std::get(o)}; } if (IsNull(o)) { return "null"; } if (std::holds_alternative(o)) { return "undefined"; } if (std::holds_alternative(o)) { return std::get(o) ? "true" : "false"; } if (std::holds_alternative< std::shared_ptr>(o)) { return std::get>(o) ->ToString(); } if (std::holds_alternative< std::shared_ptr>(o)) { return std::get>(o) ->ToString(false); } if (std::holds_alternative(o)) { return std::get(o).ToString( Framework::UuidStringifyConfig::LowercaseNoCurly); } if (std::holds_alternative(o)) { auto obj = std::get(o); auto dict = dynamic_cast(obj); auto list = dynamic_cast(obj); auto bArray = dynamic_cast(obj); auto natObj = dynamic_cast(obj); auto cls = dynamic_cast(obj); auto aArray = dynamic_cast(obj); if (aArray != nullptr) { std::string str = {}; gc->BarrierBegin(); bool first = true; for (auto item : aArray->items) { if (!first) str.push_back('\n'); first = false; str.push_back('['); str.append(Json_Encode(item.first)); str.append("] = "); str.append(Json_Encode(item.second)); str.append(";"); } gc->BarrierEnd(); return str; } if (cls != nullptr) { auto res = cls->GetValue("", "ToString"); TCallable *call; GCList ls(gc); if (GetObjectHeap(res, call)) return ToString(gc, call->Call(ls, {})); return cls->TypeName(); } if (natObj != nullptr) { GCList ls(gc); TObject o = natObj->CallMethod(ls, "ToString", {}); return ToString(gc, o); } if (dict != nullptr) { GCList ls(gc); if (dict->MethodExists(ls, "ToString")) return ToString(gc, dict->CallMethod(ls, "ToString", {})); else { return Json_Encode(dict); } } else if (bArray != nullptr) { return std::string(bArray->data.begin(), bArray->data.end()); } else if (list != nullptr) { return Json_Encode(list); } } return ""; } } // namespace Tesses::CrossLang