#ifndef PORYGONLANG_FUNCTIONSCRIPTTYPE_HPP #define PORYGONLANG_FUNCTIONSCRIPTTYPE_HPP #include #include "ScriptType.hpp" #include "../Binder/BoundExpressions/BoundExpression.hpp" #include "../Diagnostics/DiagnosticsHolder.hpp" namespace Porygon { class GenericFunctionOption{ shared_ptr _returnType; vector> _parameterTypes; size_t _option = 0; public: GenericFunctionOption(shared_ptr returnType, vector> parameterTypes) : _returnType(std::move(returnType)), _parameterTypes(std::move(parameterTypes)){ } virtual ~GenericFunctionOption() = default; [[nodiscard]] inline shared_ptr GetReturnType() const { return _returnType; } inline void SetOption(size_t v){ _option = v; } inline void SetReturnType(const shared_ptr& t) { _returnType = t; } [[nodiscard]] inline vector> GetParameterTypes() const { return _parameterTypes; } bool IsValid(const shared_ptr& diagnostics, vector* 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* _options = new vector; public: GenericFunctionScriptType() : ScriptType(Porygon::TypeClass::Function){}; explicit GenericFunctionScriptType(GenericFunctionOption * option) : ScriptType(Porygon::TypeClass::Function){ this -> RegisterFunctionOption(option); }; explicit GenericFunctionScriptType(const vector& 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, vector* 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> _parameterKeys; public: ScriptFunctionOption(shared_ptr returnType, vector> parameterTypes, vector> parameterKeys) : GenericFunctionOption(move(returnType), std::move(parameterTypes)), _parameterKeys(move(parameterKeys)) { } [[nodiscard]] inline vector> GetParameterKeys() const { return _parameterKeys; } [[nodiscard]] inline bool IsScriptFunction() const final { return true; } }; } #include "ScriptType.hpp" #endif //PORYGONLANG_FUNCTIONSCRIPTTYPE_HPP