PorygonLang/src/ScriptTypes/FunctionScriptType.hpp

146 lines
5.3 KiB
C++

#ifndef PORYGONLANG_FUNCTIONSCRIPTTYPE_HPP
#define PORYGONLANG_FUNCTIONSCRIPTTYPE_HPP
#include <utility>
#include "ScriptType.hpp"
#include "../Binder/BoundExpressions/BoundExpression.hpp"
#include "../Diagnostics/DiagnosticsHolder.hpp"
namespace Porygon {
class GenericFunctionOption{
shared_ptr<const ScriptType> _returnType;
vector<shared_ptr<const ScriptType>> _parameterTypes;
size_t _option = 0;
public:
GenericFunctionOption(shared_ptr<const ScriptType> returnType, vector<shared_ptr<const ScriptType>> parameterTypes)
: _returnType(std::move(returnType)), _parameterTypes(std::move(parameterTypes)){
}
virtual ~GenericFunctionOption() = default;
[[nodiscard]] inline shared_ptr<const ScriptType> GetReturnType() const {
return _returnType;
}
inline void SetOption(size_t v){
_option = v;
}
inline void SetReturnType(const shared_ptr<const ScriptType>& t) {
_returnType = t;
}
[[nodiscard]] inline vector<shared_ptr<const ScriptType>> GetParameterTypes() const {
return _parameterTypes;
}
bool IsValid(const shared_ptr<Diagnostics::DiagnosticsHolder>& diagnostics,
vector<Binder::BoundExpression *>* parameters){
if (parameters->size() != _parameterTypes.size()){
return false;
}
for (size_t i = 0; i < parameters->size(); i++){
if (_parameterTypes[i]->GetClass() == TypeClass::Any)
continue;
auto parameter = parameters->at(i);
const auto& parameterType = parameter->GetType();
if (parameterType->operator!=(_parameterTypes[i])){
auto castResult = parameterType->CastableTo(_parameterTypes[i], false);
if (castResult == CastResult::InvalidCast){
return false;
}
else{
if (castResult == CastResult::DataLoss){
diagnostics->LogWarning(Diagnostics::DiagnosticCode::DataLossOnCast, parameter->GetStartPosition(),
parameter->GetLength());
}
parameters->at(i) = new Binder::BoundCastExpression(parameter, _parameterTypes[i]);
}
}
}
return true;
}
[[nodiscard]] inline size_t GetOptionId() const{
return _option;
}
[[nodiscard]] virtual bool IsScriptFunction() const = 0;
};
class GenericFunctionScriptType : public Porygon::ScriptType {
vector<GenericFunctionOption *>* _options = new vector<GenericFunctionOption *>;
public:
GenericFunctionScriptType()
: ScriptType(Porygon::TypeClass::Function){};
explicit GenericFunctionScriptType(GenericFunctionOption * option)
: ScriptType(Porygon::TypeClass::Function){
this -> RegisterFunctionOption(option);
};
explicit GenericFunctionScriptType(const vector<GenericFunctionOption*>& options)
: ScriptType(Porygon::TypeClass::Function){
for (auto option: options){
this -> RegisterFunctionOption(option);
}
};
~GenericFunctionScriptType() final{
for (auto o: *_options){
delete o;
}
delete _options;
}
const GenericFunctionScriptType* RegisterFunctionOption (GenericFunctionOption * opt) const{
opt->SetOption(_options->size());
_options->push_back(opt);
return this;
}
const GenericFunctionScriptType* RegisterFunctionOption (size_t index, GenericFunctionOption * opt) const{
opt->SetOption(index);
_options->push_back(opt);
return this;
}
[[nodiscard]]
GenericFunctionOption* GetFunctionOption(const shared_ptr<Diagnostics::DiagnosticsHolder>& diagnostics,
vector<Binder::BoundExpression *>* parameters) const{
for (auto o: *_options){
if (o->IsValid(diagnostics, parameters)){
return o;
}
}
return nullptr;
}
[[nodiscard]] inline GenericFunctionOption* GetFirstOption() const{
return _options->at(0);
}
};
class ScriptFunctionOption : public GenericFunctionOption {
vector<shared_ptr<const Porygon::Binder::BoundVariableKey>> _parameterKeys;
public:
ScriptFunctionOption(shared_ptr<const ScriptType> returnType, vector<shared_ptr<const ScriptType>> parameterTypes,
vector<shared_ptr<const Porygon::Binder::BoundVariableKey>> parameterKeys)
: GenericFunctionOption(move(returnType), std::move(parameterTypes)), _parameterKeys(move(parameterKeys)) {
}
[[nodiscard]] inline vector<shared_ptr<const Porygon::Binder::BoundVariableKey>> GetParameterKeys() const {
return _parameterKeys;
}
[[nodiscard]] inline bool IsScriptFunction() const final {
return true;
}
};
}
#include "ScriptType.hpp"
#endif //PORYGONLANG_FUNCTIONSCRIPTTYPE_HPP