/*
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 {
bool InterperterThread::Add(std::shared_ptr gc) {
std::vector &cse = this->call_stack_entries;
GCList ls(gc);
auto right = cse.back()->Pop(ls);
auto left = cse.back()->Pop(ls);
if (std::holds_alternative(left) &&
std::holds_alternative(right)) {
cse.back()->Push(
gc, std::get(left) +
std::get(right));
} else if (std::holds_alternative(left) &&
std::holds_alternative(right)) {
cse.back()->Push(gc,
(char)(std::get(left) + std::get(right)));
} else if (std::holds_alternative(left) &&
std::holds_alternative(right)) {
cse.back()->Push(
gc, (char)(std::get(left) + std::get(right)));
} else if (std::holds_alternative(left) &&
std::holds_alternative(right)) {
cse.back()->Push(
gc, (char)(std::get(left) + std::get(right)));
} else if (std::holds_alternative(
left) &&
std::holds_alternative(right)) {
cse.back()->Push(
gc, std::get(left) +
std::get(right));
}
else if (std::holds_alternative(
left) &&
std::holds_alternative(
right)) {
cse.back()->Push(
gc, std::get(left) +
std::get(right));
}
else if (std::holds_alternative(left) &&
std::holds_alternative(right)) {
cse.back()->Push(gc,
std::get(left) + std::get(right));
}
else if (std::holds_alternative(left) &&
std::holds_alternative(right)) {
cse.back()->Push(gc, std::get(left) + std::get(right));
} else if (std::holds_alternative(left) &&
std::holds_alternative(right)) {
cse.back()->Push(gc, std::get(left) + std::get(right));
} else if (std::holds_alternative(left) &&
std::holds_alternative(right)) {
cse.back()->Push(gc, std::get(left) + std::get(right));
} else if (std::holds_alternative<
std::shared_ptr>(left) &&
std::holds_alternative<
std::shared_ptr>(right)) {
auto &l =
std::get>(left);
auto &r =
std::get>(right);
cse.back()->Push(
gc,
std::make_shared((*l) + (*r)));
} else if (std::holds_alternative<
std::shared_ptr>(left) &&
std::holds_alternative<
std::shared_ptr>(right)) {
auto &l =
std::get>(left);
auto &r =
std::get>(right);
cse.back()->Push(
gc,
std::make_shared((*l) + (*r)));
} else if (std::holds_alternative<
std::shared_ptr>(left) &&
std::holds_alternative<
std::shared_ptr>(right)) {
auto &l =
std::get>(left);
auto &r =
std::get>(right);
cse.back()->Push(
gc,
std::make_shared((*l) + (*r)));
} else if (std::holds_alternative(left) &&
std::holds_alternative(right)) {
std::string str = {};
str.append(std::get(left));
str.append(std::get(right));
cse.back()->Push(gc, str);
} else if (std::holds_alternative(left) &&
std::holds_alternative(right)) {
std::string str = {};
str.push_back(std::get(left));
str.append(std::get(right));
cse.back()->Push(gc, str);
} else if (std::holds_alternative(left) &&
std::holds_alternative(right)) {
std::string str = {};
str.append(std::get(left));
str.push_back(std::get(right));
cse.back()->Push(gc, str);
} else if (std::holds_alternative(left)) {
auto obj = std::get(left);
auto dict = dynamic_cast(obj);
auto dynDict = dynamic_cast(obj);
auto natObj = dynamic_cast(obj);
auto cls = dynamic_cast(obj);
if (cls != nullptr) {
gc->BarrierBegin();
auto obj =
cls->GetValue(cse.back()->callable->className, "operator+");
gc->BarrierEnd();
TClosure *clos;
TCallable *callable;
if (GetObjectHeap(obj, clos)) {
this->AddCallStackEntry(ls, clos, {right});
return true;
} else if (GetObjectHeap(obj, callable)) {
cse.back()->Push(gc, callable->Call(ls, {right}));
return false;
}
cse.back()->Push(gc, Undefined());
return false;
} else if (natObj != nullptr) {
cse.back()->Push(gc, natObj->CallMethod(ls, "operator+", {right}));
return false;
} else if (dict != nullptr) {
gc->BarrierBegin();
TObject fn = dict->GetValue("operator+");
gc->BarrierEnd();
return InvokeTwo(ls, fn, left, right);
} else if (dynDict != nullptr) {
cse.back()->Push(gc, dynDict->CallMethod(ls, "operator+", {right}));
return false;
} else {
cse.back()->Push(gc, Undefined());
}
} else {
cse.back()->Push(gc, Undefined());
}
return false;
}
} // namespace Tesses::CrossLang