PorygonLang/src/ScriptTypes/ScriptType.hpp

182 lines
6.0 KiB
C++
Raw Normal View History

#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,
2019-05-28 16:50:23 +00:00
};
class ScriptType{
TypeClass _class;
public:
2019-09-07 09:16:12 +00:00
static shared_ptr<const ScriptType> BoolType;
static shared_ptr<const ScriptType> NilType;
static shared_ptr<const ScriptType> AnyType;
2019-09-07 09:16:12 +00:00
explicit ScriptType(TypeClass c){
_class = c;
}
virtual ~ScriptType() = default;
[[nodiscard]] inline TypeClass GetClass() const{
return _class;
}
2019-09-07 09:16:12 +00:00
virtual bool operator ==(const shared_ptr<const ScriptType>& b) const;
virtual bool operator !=(const shared_ptr<const ScriptType>& b) const;
2019-07-25 15:23:54 +00:00
virtual bool CanBeIndexedWith(const ScriptType* indexer) const;
2019-09-07 09:16:12 +00:00
[[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;
2019-09-07 09:16:12 +00:00
[[nodiscard]] virtual bool CanBeIterated() const;
[[nodiscard]] virtual shared_ptr<const ScriptType> GetIteratorKeyType() const;
2019-09-07 09:16:12 +00:00
[[nodiscard]] virtual CastResult CastableTo(const shared_ptr<const ScriptType>& castType, bool explicitCast) const;
2019-09-07 09:16:12 +00:00
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;
}
2019-07-25 15:23:54 +00:00
[[nodiscard]] inline bool IsAwareOfFloat() const{
return _awareOfFloat;
}
2019-07-25 15:23:54 +00:00
[[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 )
2019-08-18 12:32:14 +00:00
return CastResult::InvalidCast;
auto bNum = dynamic_pointer_cast<const NumericScriptType>(castType);
2019-08-18 12:32:14 +00:00
if (bNum->IsFloat() && !IsFloat()) return CastResult::ValidCast;
if (!bNum->IsFloat() && IsFloat()) return CastResult::DataLoss;
}
2019-08-18 12:32:14 +00:00
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;
2019-07-25 15:23:54 +00:00
[[nodiscard]]
bool CanBeIndexedWith(const ScriptType* indexer) const final{
2019-07-04 16:24:49 +00:00
if (indexer -> GetClass() != TypeClass::Number)
return false;
2019-07-25 15:23:54 +00:00
auto num = dynamic_cast<const NumericScriptType*>(indexer);
2019-07-04 16:24:49 +00:00
return !(num->IsAwareOfFloat() && num->IsFloat());
}
2019-07-25 15:23:54 +00:00
inline shared_ptr<const ScriptType> GetIndexedType(const ScriptType* indexer) const final{
return StringScriptType::Dynamic;
2019-07-04 16:24:49 +00:00
}
2019-07-25 15:23:54 +00:00
[[nodiscard]]
inline bool IsKnownAtBind() const{
return _isKnownAtBind;
}
2019-07-25 15:23:54 +00:00
[[nodiscard]]
inline uint32_t GetHashValue() const{
return _hashValue;
}
};
class NumericalTableScriptType : public ScriptType{
2019-07-25 15:23:54 +00:00
shared_ptr<const ScriptType> _valueType;
// Consider adding a check whether the table actually contains a type if every key is static.
public:
2019-07-25 15:23:54 +00:00
explicit NumericalTableScriptType(shared_ptr<const ScriptType> valueType)
2019-07-04 16:24:49 +00:00
: ScriptType(TypeClass::Table), _valueType(std::move(valueType)){
}
2019-07-25 15:23:54 +00:00
bool CanBeIndexedWith(const ScriptType* indexer) const final{
2019-06-26 14:19:34 +00:00
if (indexer -> GetClass() != TypeClass::Number)
return false;
2019-07-25 15:23:54 +00:00
auto num = dynamic_cast<const NumericScriptType*>(indexer);
2019-06-26 14:19:34 +00:00
return !(num->IsAwareOfFloat() && num->IsFloat());
}
2019-07-25 15:23:54 +00:00
inline shared_ptr<const ScriptType> GetIndexedType(const ScriptType* indexer) const final{
return _valueType;
}
2019-06-26 14:19:34 +00:00
2019-07-25 15:23:54 +00:00
[[nodiscard]]
inline bool CanBeIterated() const final{
2019-06-26 14:19:34 +00:00
return true;
}
2019-07-25 15:23:54 +00:00
[[nodiscard]]
inline shared_ptr<const ScriptType> GetIteratorKeyType() const final{
return NumericScriptType::AwareInt;
2019-06-26 14:19:34 +00:00
}
};
}
2019-06-09 18:15:09 +00:00
2019-06-12 13:19:28 +00:00
#endif //PORYGONLANG_SCRIPTTYPE_HPP