Support for length unary operator
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2019-09-12 18:19:06 +02:00
parent bd9eac9056
commit 73142afa8a
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
18 changed files with 95 additions and 10 deletions

View File

@ -599,8 +599,15 @@ namespace Porygon::Binder {
expression->GetStartPosition(), expression->GetLength());
}
break;
default:
case UnaryOperatorKind::Count:
if (operandType->IsCountable()){
return new BoundUnaryExpression(operand, BoundUnaryOperation::Count,
NumericScriptType::AwareInt,
expression->GetStartPosition(), expression->GetLength());
}
break;
default:
throw Exception("Unknown unary operator was called.");
}
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::NoUnaryOperationFound,
expression->GetStartPosition(),

View File

@ -23,6 +23,7 @@ namespace Porygon::Binder {
enum class BoundUnaryOperation {
Negation,
Count,
LogicalNegation,
};
}

View File

@ -1,5 +1,6 @@
#include "NumericalTableEvalValue.hpp"
#include "../Iterator/NumericalKeyIterator.hpp"
#include "../../Utilities/Random.hpp"
inline Porygon::Evaluation::Iterator *Porygon::Evaluation::NumericalTableEvalValue::GetKeyIterator() const {
return new NumericalKeyIterator(this);
@ -7,6 +8,14 @@ inline Porygon::Evaluation::Iterator *Porygon::Evaluation::NumericalTableEvalVal
Porygon::Evaluation::NumericalTableEvalValue::NumericalTableEvalValue(shared_ptr<vector<EvalValuePointer>> table) :
_table(std::move(table)),
_hash(rand())
_hash(Utilities::Random::Get())
{
}
Porygon::Evaluation::EvalValue *
Porygon::Evaluation::NumericalTableEvalValue::UnaryOperation(Porygon::Binder::BoundUnaryOperation operation) const {
if (operation == Porygon::Binder::BoundUnaryOperation::Count){
return new NumericEvalValue(static_cast<int64_t>(this->_table->size()));
}
return EvalValue::UnaryOperation(operation);
}

View File

@ -69,7 +69,9 @@ namespace Porygon::Evaluation {
[[nodiscard]]
inline shared_ptr<vector<EvalValuePointer>> GetTable() const{
return _table;
};
}
EvalValue *UnaryOperation(Binder::BoundUnaryOperation operation) const override;;
};
}

View File

@ -4,6 +4,7 @@
#include <string>
#include "EvalValue.hpp"
#include "NumericEvalValue.hpp"
#include "../../Utilities/HashedString.hpp"
using namespace std;
@ -68,6 +69,13 @@ namespace Porygon::Evaluation {
auto str = stringStream.str();
return new StringEvalValue(str);
}
[[nodiscard]] EvalValue *UnaryOperation(Binder::BoundUnaryOperation operation) const override {
if (operation == Binder::BoundUnaryOperation ::Count){
return new NumericEvalValue(static_cast<int64_t >(_value->size()));
}
return EvalValue::UnaryOperation(operation);
}
};
}

View File

@ -1,6 +1,15 @@
#include "TableEvalValue.hpp"
#include "../Iterator/SimpleKeyIterator.hpp"
#include "NumericEvalValue.hpp"
inline Porygon::Evaluation::Iterator * Porygon::Evaluation::TableEvalValue::GetKeyIterator() const {
return new TableKeyIterator(this);
}
Porygon::Evaluation::EvalValue *
Porygon::Evaluation::TableEvalValue::UnaryOperation(Porygon::Binder::BoundUnaryOperation operation) const {
if (operation == Porygon::Binder::BoundUnaryOperation::Count){
return new NumericEvalValue(static_cast<int64_t>(this->_table->size()));
}
return EvalValue::UnaryOperation(operation);
}

View File

@ -83,7 +83,9 @@ namespace Porygon::Evaluation {
[[nodiscard]]
inline _Rb_tree_const_iterator<pair<const Utilities::HashedString, EvalValuePointer>> GetTableIteratorEnd() const{
return _table->cend();
};
}
EvalValue *UnaryOperation(Binder::BoundUnaryOperation operation) const override;;
};
}

View File

@ -103,6 +103,8 @@ namespace Porygon::Parser {
}
this->ScriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::UnexpectedCharacter, this->_position - 1, 1);
return new SimpleToken(TokenKind::BadToken, this->_position - 1, 1);
case '#':
return new SimpleToken(TokenKind::HashToken, this->_position - 1, 1);
case '0':
case '1':
case '2':

View File

@ -362,6 +362,7 @@ namespace Porygon::Parser {
switch (kind) {
case TokenKind::PlusToken:
case TokenKind::MinusToken:
case TokenKind::HashToken:
case TokenKind::NotKeyword:
return OperatorPrecedence::Unary;
default:
@ -375,6 +376,8 @@ namespace Porygon::Parser {
return UnaryOperatorKind::Identity;
case TokenKind::MinusToken:
return UnaryOperatorKind::Negation;
case TokenKind::HashToken :
return UnaryOperatorKind::Count;
case TokenKind::NotKeyword:
return UnaryOperatorKind::LogicalNegation;
default: // This should never trigger, so throw.

View File

@ -19,6 +19,7 @@ namespace Porygon::Parser {
LessEquals,
Greater,
GreaterEquals,
HashToken,
OpenParenthesis,
CloseParenthesis,

View File

@ -6,6 +6,7 @@ namespace Porygon::Parser {
enum class UnaryOperatorKind {
Identity,
Negation,
Count,
LogicalNegation,
};
}

View File

@ -1,5 +1,7 @@
#include "../Script.hpp"
#include "../UserData/UserDataFunctionType.hpp"
#include "ScriptType.hpp"
namespace Porygon{
inline bool ScriptType::CanBeIndexedWith(const ScriptType *) const{
@ -76,6 +78,14 @@ namespace Porygon{
return ToString(this->_class);
}
bool ScriptType::IsCountable() const {
return false;
}
bool StringScriptType::IsCountable() const {
return true;
}
extern "C"{
ScriptType* CreateScriptType(Porygon::TypeClass t){
return new ScriptType(t);

View File

@ -51,6 +51,8 @@ namespace Porygon{
[[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;
};
@ -145,6 +147,8 @@ namespace Porygon{
inline uint32_t GetHashValue() const{
return _hashValue;
}
bool IsCountable() const override;
};
class NumericalTableScriptType : public ScriptType{

View File

@ -65,6 +65,10 @@ namespace Porygon{
shared_ptr<const ScriptType> GetIteratorKeyType() const final {
return make_shared<ScriptType>(TypeClass::Any);
}
bool IsCountable() const override {
return true;
}
};
}

View File

@ -20,7 +20,8 @@ namespace Porygon::UserData {
_iterable(iterable)
{}
static shared_ptr<UserDataCollectionType> CreateIndexable(const shared_ptr<const ScriptType>& keyType, const shared_ptr<const ScriptType>& valueType){
static shared_ptr<UserDataCollectionType> CreateIndexable(const shared_ptr<const ScriptType>& keyType,
const shared_ptr<const ScriptType>& valueType){
return make_shared<UserDataCollectionType>(keyType, valueType, true, true);
}
@ -65,6 +66,10 @@ namespace Porygon::UserData {
return _valueType;
}
}
[[nodiscard]] bool IsCountable() const override {
return true;
}
};
}

View File

@ -8,8 +8,9 @@ UserDataCollectionType* CreateCollectionType(const ScriptType* keyType, const Sc
UserDataCollectionValue* CreateCollectionValue(UserDataCollectionType* type, void* obj,
const EvalValue* (*get)(void*, const EvalValue*),
void (*set)(void*, const EvalValue*, const EvalValue*),
Iterator* (*getIterator)(void*)){
return new UserDataCollectionValue(shared_ptr<UserDataCollectionType>(type), new UserDataCollectionHelper(obj, get, set, getIterator));
Iterator* (*getIterator)(void*), size_t (getSize)(void*)){
return new UserDataCollectionValue(shared_ptr<UserDataCollectionType>(type),
new UserDataCollectionHelper(obj, get, set, getIterator, getSize));
}
}
}

View File

@ -6,6 +6,7 @@
#include "UserDataCollectionType.hpp"
#include "../../Evaluator/EvalValues/EvalValue.hpp"
#include "../../Utilities/Random.hpp"
#include "../../Evaluator/EvalValues/NumericEvalValue.hpp"
using namespace Porygon::Evaluation;
@ -15,12 +16,14 @@ namespace Porygon::UserData {
const EvalValue* (*_get)(void*, const EvalValue*);
void (*_set)(void*, const EvalValue* , const EvalValue*);
Iterator* (*_getIterator)(void*);
size_t (*_getLength)(void*);
public:
UserDataCollectionHelper(void* parentObject,
const EvalValue* (*get)(void*, const EvalValue*),
void (*set)(void*, const EvalValue*, const EvalValue*),
Iterator* (*getIterator)(void*))
: _parentObject(parentObject), _get(get), _set(set), _getIterator(getIterator){}
Iterator* (*getIterator)(void*), size_t (*getLength)(void*))
: _parentObject(parentObject), _get(get), _set(set), _getIterator(getIterator),
_getLength(getLength){}
const EvalValue* Get(const EvalValue* key) const{
return _get(_parentObject, key);
@ -33,6 +36,10 @@ namespace Porygon::UserData {
[[nodiscard]] Iterator* GetIterator() const{
return _getIterator(_parentObject);
}
[[nodiscard]] size_t GetLength() const{
return _getLength(_parentObject);
}
};
class UserDataCollectionValue : public Evaluation::EvalValue{
@ -46,7 +53,7 @@ namespace Porygon::UserData {
}
public:
UserDataCollectionValue(shared_ptr<const ScriptType> type, const UserDataCollectionHelper* helper)
UserDataCollectionValue(const shared_ptr<const ScriptType>& type, const UserDataCollectionHelper* helper)
: _type(dynamic_pointer_cast<const UserDataCollectionType>(type)), _helper(helper), _hash(Utilities::Random::Get())
{
}
@ -85,6 +92,13 @@ namespace Porygon::UserData {
_helper->Set(key, value);
delete value;
}
[[nodiscard]] EvalValue *UnaryOperation(Binder::BoundUnaryOperation operation) const override {
if (operation == Binder::BoundUnaryOperation::Count){
return new NumericEvalValue(static_cast<int64_t>(_helper->GetLength()));
}
return EvalValue::UnaryOperation(operation);
}
};
}

View File

@ -96,6 +96,8 @@ Porygon::Utilities::HashedString* Convert(const char* k){
auto val = ((T_USERDATA*)obj)->fieldName; \
auto size = val.size(); \
return new Porygon::UserData::UserDataCollectionRangeIterator(0, size); \
}, [](void* obj) -> size_t{ \
return ((T_USERDATA*)obj)->fieldName.size(); \
} \
) \
) \