146 lines
5.3 KiB
C++
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
|