190 lines
6.2 KiB
C++
190 lines
6.2 KiB
C++
#ifndef PORYGONLANG_SCRIPTTYPE_HPP
|
|
#define PORYGONLANG_SCRIPTTYPE_HPP
|
|
|
|
#include <utility>
|
|
#include <vector>
|
|
#include <memory>
|
|
#include "../Utilities/HashedString.hpp"
|
|
#include "CastResult.hpp"
|
|
|
|
using namespace std;
|
|
|
|
namespace Porygon{
|
|
enum class TypeClass{
|
|
Error,
|
|
Nil,
|
|
Number,
|
|
Bool,
|
|
String,
|
|
Function,
|
|
UserData,
|
|
Table,
|
|
Any,
|
|
};
|
|
|
|
class ScriptType{
|
|
TypeClass _class;
|
|
public:
|
|
static shared_ptr<const ScriptType> BoolType;
|
|
static shared_ptr<const ScriptType> NilType;
|
|
static shared_ptr<const ScriptType> AnyType;
|
|
|
|
explicit ScriptType(TypeClass c){
|
|
_class = c;
|
|
}
|
|
virtual ~ScriptType() = default;
|
|
|
|
[[nodiscard]] inline TypeClass GetClass() const{
|
|
return _class;
|
|
}
|
|
|
|
virtual bool operator ==(const shared_ptr<const ScriptType>& b) const;
|
|
virtual bool operator !=(const shared_ptr<const ScriptType>& b) const;
|
|
|
|
virtual bool CanBeIndexedWith(const ScriptType* indexer) const;
|
|
[[nodiscard]] virtual bool CanBeIndexedWithIdentifier(uint32_t hash) const;
|
|
[[nodiscard]] virtual shared_ptr<const ScriptType> GetIndexedType(const ScriptType* indexer) const;
|
|
[[nodiscard]] virtual shared_ptr<const ScriptType> GetIndexedType(uint32_t hash) const;
|
|
|
|
[[nodiscard]] virtual bool CanBeIterated() const;
|
|
[[nodiscard]] virtual shared_ptr<const ScriptType> GetIteratorKeyType() const;
|
|
|
|
[[nodiscard]] virtual CastResult CastableTo(const shared_ptr<const ScriptType>& castType, bool explicitCast) const;
|
|
|
|
[[nodiscard]] virtual bool IsCountable() const;
|
|
|
|
static std::string ToString(TypeClass c);
|
|
[[nodiscard]] virtual std::string ToString() const;
|
|
};
|
|
|
|
class NumericScriptType : public ScriptType{
|
|
// Are we aware of whether this is a float or not?
|
|
bool _awareOfFloat;
|
|
// Is this value a float?
|
|
bool _isFloat;
|
|
|
|
public:
|
|
static shared_ptr<const NumericScriptType> AwareInt;
|
|
static shared_ptr<const NumericScriptType> AwareFloat;
|
|
static shared_ptr<const NumericScriptType> Unaware;
|
|
|
|
static shared_ptr<const NumericScriptType> ResolveType(bool isAware, bool isFloat){
|
|
if (isAware){
|
|
if (isFloat) return AwareFloat;
|
|
return AwareInt;
|
|
}
|
|
return Unaware;
|
|
}
|
|
|
|
explicit NumericScriptType(bool floatAware, bool isFloat) : ScriptType(TypeClass::Number){
|
|
_awareOfFloat = floatAware;
|
|
_isFloat = isFloat;
|
|
}
|
|
|
|
[[nodiscard]] inline bool IsAwareOfFloat() const{
|
|
return _awareOfFloat;
|
|
}
|
|
|
|
[[nodiscard]] inline bool IsFloat() const{
|
|
return _isFloat;
|
|
}
|
|
|
|
bool operator ==(const shared_ptr<const ScriptType>& b) const final{
|
|
if (b->GetClass() != TypeClass::Number)
|
|
return false;
|
|
auto bNum = dynamic_pointer_cast<const NumericScriptType>(b);
|
|
if (bNum->IsAwareOfFloat() && IsAwareOfFloat()){
|
|
return bNum->IsFloat() == IsFloat();
|
|
}
|
|
return true;
|
|
};
|
|
|
|
bool operator !=(const shared_ptr<const ScriptType>& b) const final{
|
|
return ! (operator==(b));
|
|
}
|
|
|
|
[[nodiscard]] CastResult CastableTo(const shared_ptr<const ScriptType>& castType, bool explicitCast) const final{
|
|
if (!explicitCast){
|
|
if (castType->GetClass() != TypeClass::Number )
|
|
return CastResult::InvalidCast;
|
|
auto bNum = dynamic_pointer_cast<const NumericScriptType>(castType);
|
|
if (bNum->IsFloat() && !IsFloat()) return CastResult::ValidCast;
|
|
if (!bNum->IsFloat() && IsFloat()) return CastResult::DataLoss;
|
|
}
|
|
return ScriptType::CastableTo(castType, explicitCast);
|
|
}
|
|
};
|
|
|
|
class StringScriptType : public ScriptType{
|
|
bool _isKnownAtBind;
|
|
uint32_t _hashValue;
|
|
public:
|
|
explicit StringScriptType(bool knownAtBind, uint32_t hashValue): ScriptType(TypeClass::String){
|
|
_isKnownAtBind = knownAtBind;
|
|
_hashValue = hashValue;
|
|
}
|
|
|
|
static shared_ptr<const StringScriptType> Dynamic;
|
|
|
|
[[nodiscard]]
|
|
bool CanBeIndexedWith(const ScriptType* indexer) const final{
|
|
if (indexer -> GetClass() != TypeClass::Number)
|
|
return false;
|
|
auto num = dynamic_cast<const NumericScriptType*>(indexer);
|
|
return !(num->IsAwareOfFloat() && num->IsFloat());
|
|
}
|
|
|
|
inline shared_ptr<const ScriptType> GetIndexedType(const ScriptType* indexer) const final{
|
|
return StringScriptType::Dynamic;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
inline bool IsKnownAtBind() const{
|
|
return _isKnownAtBind;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
inline uint32_t GetHashValue() const{
|
|
return _hashValue;
|
|
}
|
|
|
|
bool IsCountable() const override;
|
|
};
|
|
|
|
class NumericalTableScriptType : public ScriptType{
|
|
shared_ptr<const ScriptType> _valueType;
|
|
// Consider adding a check whether the table actually contains a type if every key is static.
|
|
public:
|
|
explicit NumericalTableScriptType(shared_ptr<const ScriptType> valueType)
|
|
: ScriptType(TypeClass::Table), _valueType(std::move(valueType)){
|
|
}
|
|
|
|
bool CanBeIndexedWith(const ScriptType* indexer) const final{
|
|
if (indexer -> GetClass() != TypeClass::Number)
|
|
return false;
|
|
auto num = dynamic_cast<const NumericScriptType*>(indexer);
|
|
return !(num->IsAwareOfFloat() && num->IsFloat());
|
|
}
|
|
|
|
inline shared_ptr<const ScriptType> GetIndexedType(const ScriptType* indexer) const final{
|
|
return _valueType;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
inline bool CanBeIterated() const final{
|
|
return true;
|
|
}
|
|
[[nodiscard]]
|
|
inline shared_ptr<const ScriptType> GetIteratorKeyType() const final{
|
|
return NumericScriptType::AwareInt;
|
|
}
|
|
|
|
[[nodiscard]] bool IsCountable() const override {
|
|
return true;
|
|
}
|
|
};
|
|
}
|
|
|
|
|
|
#endif //PORYGONLANG_SCRIPTTYPE_HPP
|