#ifndef PORYGONLANG_SCRIPTTYPE_HPP #define PORYGONLANG_SCRIPTTYPE_HPP #include #include #include #include "Binder/BoundVariables/BoundVariableKey.hpp" #include "Utilities/HashedString.hpp" using namespace std; namespace Porygon{ enum class TypeClass{ Error, Nil, Number, Bool, String, Function, UserData, Table, }; class ScriptType{ TypeClass _class; public: explicit ScriptType(TypeClass c){ _class = c; } virtual ~ScriptType() = default; const TypeClass GetClass() const{ return _class; } virtual bool operator ==(const ScriptType& b) const{ return _class == b._class; }; virtual bool operator ==(ScriptType* b) const{ return _class == b->_class; }; virtual bool operator !=(const ScriptType& b) const{ return ! (operator==(b)); } virtual bool operator !=(ScriptType* b) const{ return ! (operator==(b)); } virtual const bool CanBeIndexedWith(ScriptType* indexer) const; virtual const bool CanBeIndexedWithIdentifier(uint32_t hash) const{ return false; } virtual const shared_ptr GetIndexedType(ScriptType* indexer) const; virtual const shared_ptr GetIndexedType(uint32_t hash) const{ throw "This type told the binder it can be indexed, but it does not implement the resulting type."; } virtual const bool CanBeIterated() const{ return false; } virtual shared_ptr GetIteratorKeyType() const{ throw "This type told the binder it can be iterated, but it does not implement the resulting type."; } }; 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: explicit NumericScriptType(bool floatAware, bool isFloat) : ScriptType(TypeClass::Number){ _awareOfFloat = floatAware; _isFloat = isFloat; } const bool IsAwareOfFloat() const{ return _awareOfFloat; } const bool IsFloat() const{ return _isFloat; } }; class StringScriptType : public ScriptType{ bool _isKnownAtBind; uint32_t _hashValue; public: explicit StringScriptType(bool knownAtBind, uint32_t hashValue): ScriptType(TypeClass::String){ _isKnownAtBind = knownAtBind; _hashValue = hashValue; } const bool IsKnownAtBind() const{ return _isKnownAtBind; } const uint32_t GetHashValue() const{ return _hashValue; } }; class NumericalTableScriptType : public ScriptType{ shared_ptr _valueType; // Consider adding a check whether the table actually contains a type if every key is static. public: explicit NumericalTableScriptType(shared_ptr valueType) : ScriptType(TypeClass::Table){ _valueType = std::move(valueType); } const bool CanBeIndexedWith(ScriptType* indexer) const final{ if (indexer -> GetClass() != TypeClass::Number) return false; auto num =(NumericScriptType*)indexer; return !(num->IsAwareOfFloat() && num->IsFloat()); } const shared_ptr GetIndexedType(ScriptType* indexer) const final{ return _valueType; } const bool CanBeIterated() const final{ return true; } shared_ptr GetIteratorKeyType() const final{ return make_shared(true, false); } }; } #endif //PORYGONLANG_SCRIPTTYPE_HPP