diff --git a/src/Binder/Binder.cpp b/src/Binder/Binder.cpp index d98bebf..54aa58b 100644 --- a/src/Binder/Binder.cpp +++ b/src/Binder/Binder.cpp @@ -6,521 +6,581 @@ #include "../UserData/UserDataScriptType.hpp" #include -BoundScriptStatement *Binder::Bind(Script* script, const ParsedScriptStatement *s, BoundScope* scriptScope) { - auto binder = Binder(); - binder._scriptData = script; +using namespace Porygon::Parser; - binder._scope = scriptScope; - auto statements = s->GetStatements(); - vector boundStatements (statements->size()); - for (int i = 0; i < statements->size(); i++){ - boundStatements[i] = binder.BindStatement(statements->at(i)); +namespace Porygon::Binder { + BoundScriptStatement *Binder::Bind(Script *script, const ParsedScriptStatement *s, BoundScope *scriptScope) { + auto binder = Binder(); + binder._scriptData = script; + + binder._scope = scriptScope; + auto statements = s->GetStatements(); + vector boundStatements(statements->size()); + for (int i = 0; i < statements->size(); i++) { + boundStatements[i] = binder.BindStatement(statements->at(i)); + } + return new BoundScriptStatement(boundStatements, scriptScope->GetLocalVariableCount()); } - return new BoundScriptStatement(boundStatements, scriptScope->GetLocalVariableCount()); -} -Binder::~Binder() { - delete _scope; -} - -BoundStatement* Binder::BindStatement(const ParsedStatement* statement){ - switch (statement -> GetKind()) { - case ParsedStatementKind ::Script: throw; // This shouldn't happen. - case ParsedStatementKind ::Block: return this -> BindBlockStatement(statement); - case ParsedStatementKind ::Expression: return this -> BindExpressionStatement(statement); - case ParsedStatementKind::Assignment: return this -> BindAssignmentStatement(statement); - case ParsedStatementKind::IndexAssignment: return this -> BindIndexAssignmentStatement(statement); - case ParsedStatementKind ::FunctionDeclaration: return this->BindFunctionDeclarationStatement(statement); - case ParsedStatementKind::Return: return this -> BindReturnStatement(statement); - case ParsedStatementKind::Conditional: return this -> BindConditionalStatement(statement); - - case ParsedStatementKind::Bad: return new BoundBadStatement(); + Binder::~Binder() { + delete _scope; } -} -BoundStatement *Binder::BindBlockStatement(const ParsedStatement *statement) { - auto statements = ((ParsedBlockStatement*)statement)->GetStatements(); - vector boundStatements (statements->size()); - this->_scope->GoInnerScope(); - for (int i = 0; i < statements->size(); i++){ - boundStatements[i] = this -> BindStatement(statements->at(i)); + BoundStatement *Binder::BindStatement(const ParsedStatement *statement) { + switch (statement->GetKind()) { + case ParsedStatementKind::Script: + throw; // This shouldn't happen. + case ParsedStatementKind::Block: + return this->BindBlockStatement(statement); + case ParsedStatementKind::Expression: + return this->BindExpressionStatement(statement); + case ParsedStatementKind::Assignment: + return this->BindAssignmentStatement(statement); + case ParsedStatementKind::IndexAssignment: + return this->BindIndexAssignmentStatement(statement); + case ParsedStatementKind::FunctionDeclaration: + return this->BindFunctionDeclarationStatement(statement); + case ParsedStatementKind::Return: + return this->BindReturnStatement(statement); + case ParsedStatementKind::Conditional: + return this->BindConditionalStatement(statement); + + case ParsedStatementKind::Bad: + return new BoundBadStatement(); + } } - this->_scope->GoOuterScope(); - return new BoundBlockStatement(boundStatements); -} -BoundStatement *Binder::BindExpressionStatement(const ParsedStatement *statement) { - auto exp = ((ParsedExpressionStatement*)statement)->GetExpression(); - return new BoundExpressionStatement(this -> BindExpression(exp)); -} + BoundStatement *Binder::BindBlockStatement(const ParsedStatement *statement) { + auto statements = ((ParsedBlockStatement *) statement)->GetStatements(); + vector boundStatements(statements->size()); + this->_scope->GoInnerScope(); + for (int i = 0; i < statements->size(); i++) { + boundStatements[i] = this->BindStatement(statements->at(i)); + } + this->_scope->GoOuterScope(); + return new BoundBlockStatement(boundStatements); + } -BoundStatement* Binder::BindAssignmentStatement(const ParsedStatement *statement){ - auto s = (ParsedAssignmentStatement*) statement; - auto boundExpression = this->BindExpression(s->GetExpression()); - VariableAssignment assignment = - s->IsLocal() ? + BoundStatement *Binder::BindExpressionStatement(const ParsedStatement *statement) { + auto exp = ((ParsedExpressionStatement *) statement)->GetExpression(); + return new BoundExpressionStatement(this->BindExpression(exp)); + } + + BoundStatement *Binder::BindAssignmentStatement(const ParsedStatement *statement) { + auto s = (ParsedAssignmentStatement *) statement; + auto boundExpression = this->BindExpression(s->GetExpression()); + VariableAssignment assignment = + s->IsLocal() ? this->_scope->CreateExplicitLocal(s->GetIdentifier().GetHash(), boundExpression->GetType()) - : this->_scope->AssignVariable(s->GetIdentifier().GetHash(), boundExpression->GetType()); - if (assignment.GetResult() == VariableAssignmentResult::Ok){ - auto key = assignment.GetKey(); - return new BoundAssignmentStatement(key, boundExpression); - } - else{ - this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::CantAssignVariable, statement->GetStartPosition(), statement->GetLength()); - return new BoundBadStatement(); - } -} - -BoundStatement *Binder::BindIndexAssignmentStatement(const ParsedStatement *statement) { - auto s = (ParsedIndexAssignmentStatement*) statement; - auto indexExp = s -> GetIndexExpression(); - const BoundExpression* indexable; - if (indexExp->GetKind() == ParsedExpressionKind::Indexer){ - indexable = this -> BindIndexExpression((IndexExpression*)indexExp, true); - } else{ - indexable = this -> BindPeriodIndexExpression((PeriodIndexExpression*)indexExp, true); - } - auto valueExpression = this -> BindExpression(s->GetValueExpression()); - auto boundIndexType = indexable -> GetType(); - if (boundIndexType ->GetClass() != TypeClass ::Error && boundIndexType->operator!=(valueExpression->GetType().get())){ - this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidTableValueType, statement->GetStartPosition(), statement->GetLength()); - return new BoundBadStatement(); - } - - return new BoundIndexAssignmentStatement(indexable, valueExpression); -} - -std::shared_ptr ParseTypeIdentifier(HashedString s){ - auto hash = s.GetHash(); - switch (hash){ - case HashedString::ConstHash("number"): return std::make_shared(false, false); - case HashedString::ConstHash("bool"): return std::make_shared(TypeClass::Bool); - case HashedString::ConstHash("string"): return std::make_shared(false, 0); - default: - if (!UserDataStorage::HasUserDataType(hash)){ - return nullptr; - } - return std::make_shared(hash); - } -} - -BoundStatement *Binder::BindFunctionDeclarationStatement(const ParsedStatement *statement) { - auto functionStatement = (ParsedFunctionDeclarationStatement*) statement; - auto parameters = functionStatement->GetParameters(); - auto parameterTypes = vector>(parameters->size()); - auto parameterKeys = vector>(parameters->size()); - - auto scopeIndex = this->_scope->GetCurrentScope(); - this->_scope->GoInnerScope(); - for (int i = 0; i < parameters->size(); i++){ - auto var = parameters -> at(i); - auto parsedType = ParseTypeIdentifier(var->GetType()); - if (parsedType == nullptr){ - this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidTypeName, statement->GetStartPosition(), statement->GetLength()); + : this->_scope->AssignVariable(s->GetIdentifier().GetHash(), boundExpression->GetType()); + if (assignment.GetResult() == VariableAssignmentResult::Ok) { + auto key = assignment.GetKey(); + return new BoundAssignmentStatement(key, boundExpression); + } else { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::CantAssignVariable, statement->GetStartPosition(), + statement->GetLength()); return new BoundBadStatement(); } - parameterTypes.at(i) = parsedType; - auto parameterAssignment = this->_scope->CreateExplicitLocal(var->GetIdentifier().GetHash(), parsedType); - if (parameterAssignment.GetResult() == VariableAssignmentResult::Ok){ - parameterKeys.at(i) = std::shared_ptr(parameterAssignment.GetKey()); + } + + BoundStatement *Binder::BindIndexAssignmentStatement(const ParsedStatement *statement) { + auto s = (ParsedIndexAssignmentStatement *) statement; + auto indexExp = s->GetIndexExpression(); + const BoundExpression *indexable; + if (indexExp->GetKind() == ParsedExpressionKind::Indexer) { + indexable = this->BindIndexExpression((IndexExpression *) indexExp, true); + } else { + indexable = this->BindPeriodIndexExpression((PeriodIndexExpression *) indexExp, true); } - else{ - //TODO: log error - continue; + auto valueExpression = this->BindExpression(s->GetValueExpression()); + auto boundIndexType = indexable->GetType(); + if (boundIndexType->GetClass() != TypeClass::Error && + boundIndexType->operator!=(valueExpression->GetType().get())) { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::InvalidTableValueType, + statement->GetStartPosition(), statement->GetLength()); + return new BoundBadStatement(); + } + + return new BoundIndexAssignmentStatement(indexable, valueExpression); + } + + std::shared_ptr ParseTypeIdentifier(HashedString s) { + auto hash = s.GetHash(); + switch (hash) { + case HashedString::ConstHash("number"): + return std::make_shared(false, false); + case HashedString::ConstHash("bool"): + return std::make_shared(TypeClass::Bool); + case HashedString::ConstHash("string"): + return std::make_shared(false, 0); + default: + if (!UserData::UserDataStorage::HasUserDataType(hash)) { + return nullptr; + } + return std::make_shared(hash); } } - auto identifier = functionStatement->GetIdentifier(); - auto returnType = make_shared(TypeClass::Nil); - auto type = make_shared(returnType, parameterTypes, parameterKeys, scopeIndex); - this->_currentFunction = type; + BoundStatement *Binder::BindFunctionDeclarationStatement(const ParsedStatement *statement) { + auto functionStatement = (ParsedFunctionDeclarationStatement *) statement; + auto parameters = functionStatement->GetParameters(); + auto parameterTypes = vector>(parameters->size()); + auto parameterKeys = vector>(parameters->size()); - auto assignment = this->_scope->AssignVariable(identifier.GetHash(), type); - if (assignment.GetResult() != VariableAssignmentResult::Ok){ - this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::CantAssignVariable, statement->GetStartPosition(), statement->GetLength()); - return new BoundBadStatement(); - } - auto boundBlock = this -> BindBlockStatement(functionStatement->GetBlock()); - this->_scope->GoOuterScope(); - this->_currentFunction = nullptr; - return new BoundFunctionDeclarationStatement(type, assignment.GetKey(), (BoundBlockStatement*)boundBlock); -} + auto scopeIndex = this->_scope->GetCurrentScope(); + this->_scope->GoInnerScope(); + for (int i = 0; i < parameters->size(); i++) { + auto var = parameters->at(i); + auto parsedType = ParseTypeIdentifier(var->GetType()); + if (parsedType == nullptr) { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::InvalidTypeName, statement->GetStartPosition(), + statement->GetLength()); + return new BoundBadStatement(); + } + parameterTypes.at(i) = parsedType; + auto parameterAssignment = this->_scope->CreateExplicitLocal(var->GetIdentifier().GetHash(), parsedType); + if (parameterAssignment.GetResult() == VariableAssignmentResult::Ok) { + parameterKeys.at(i) = std::shared_ptr(parameterAssignment.GetKey()); + } else { + //TODO: log error + continue; + } + } -BoundStatement *Binder::BindReturnStatement(const ParsedStatement* statement){ - auto expression = ((ParsedReturnStatement*)statement)->GetExpression(); - shared_ptr currentReturnType; - if (this->_currentFunction == nullptr){ - currentReturnType = this->_scriptData->GetReturnType(); - } else{ - currentReturnType = this->_currentFunction->GetReturnType(); + auto identifier = functionStatement->GetIdentifier(); + auto returnType = make_shared(TypeClass::Nil); + auto type = make_shared(returnType, parameterTypes, parameterKeys, scopeIndex); + this->_currentFunction = type; + + auto assignment = this->_scope->AssignVariable(identifier.GetHash(), type); + if (assignment.GetResult() != VariableAssignmentResult::Ok) { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::CantAssignVariable, statement->GetStartPosition(), + statement->GetLength()); + return new BoundBadStatement(); + } + auto boundBlock = this->BindBlockStatement(functionStatement->GetBlock()); + this->_scope->GoOuterScope(); + this->_currentFunction = nullptr; + return new BoundFunctionDeclarationStatement(type, assignment.GetKey(), (BoundBlockStatement *) boundBlock); } - if (expression == nullptr && currentReturnType != nullptr){ - this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidReturnType, statement->GetStartPosition(), statement->GetLength()); - return new BoundBadStatement(); - } - auto boundExpression = this->BindExpression(expression); - auto expresionType = boundExpression->GetType(); - if (currentReturnType == nullptr || currentReturnType->GetClass() == TypeClass::Nil){ - if (this->_currentFunction == nullptr){ - this->_scriptData->SetReturnType(expresionType); - } else{ - this->_currentFunction->SetReturnType(expresionType); + + BoundStatement *Binder::BindReturnStatement(const ParsedStatement *statement) { + auto expression = ((ParsedReturnStatement *) statement)->GetExpression(); + shared_ptr currentReturnType; + if (this->_currentFunction == nullptr) { + currentReturnType = this->_scriptData->GetReturnType(); + } else { + currentReturnType = this->_currentFunction->GetReturnType(); + } + if (expression == nullptr && currentReturnType != nullptr) { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::InvalidReturnType, statement->GetStartPosition(), + statement->GetLength()); + return new BoundBadStatement(); + } + auto boundExpression = this->BindExpression(expression); + auto expresionType = boundExpression->GetType(); + if (currentReturnType == nullptr || currentReturnType->GetClass() == TypeClass::Nil) { + if (this->_currentFunction == nullptr) { + this->_scriptData->SetReturnType(expresionType); + } else { + this->_currentFunction->SetReturnType(expresionType); + } + return new BoundReturnStatement(boundExpression); + } + if (currentReturnType.get()->operator!=(expresionType.get())) { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::InvalidReturnType, statement->GetStartPosition(), + statement->GetLength()); + return new BoundBadStatement(); } return new BoundReturnStatement(boundExpression); } - if (currentReturnType.get()->operator!=(expresionType.get())){ - this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidReturnType, statement->GetStartPosition(), statement->GetLength()); - return new BoundBadStatement(); + + BoundStatement *Binder::BindConditionalStatement(const ParsedStatement *statement) { + auto conditionalStatement = (ParsedConditionalStatement *) statement; + auto boundCondition = this->BindExpression(conditionalStatement->GetCondition()); + if (boundCondition->GetType()->GetClass() != TypeClass::Bool) { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::ConditionNotABool, statement->GetStartPosition(), + statement->GetLength()); + return new BoundBadStatement(); + } + auto boundBlock = this->BindStatement(conditionalStatement->GetBlock()); + BoundStatement *elseStatement = nullptr; + if (conditionalStatement->GetElseStatement() != nullptr) { + elseStatement = this->BindStatement(conditionalStatement->GetElseStatement()); + } + return new BoundConditionalStatement(boundCondition, boundBlock, elseStatement); } - return new BoundReturnStatement(boundExpression); -} -BoundStatement *Binder::BindConditionalStatement(const ParsedStatement* statement) { - auto conditionalStatement = (ParsedConditionalStatement*)statement; - auto boundCondition = this -> BindExpression(conditionalStatement -> GetCondition()); - if (boundCondition->GetType() -> GetClass() != TypeClass::Bool){ - this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::ConditionNotABool, statement->GetStartPosition(), statement->GetLength()); - return new BoundBadStatement(); + BoundExpression *Binder::BindExpression(const ParsedExpression *expression) { + switch (expression->GetKind()) { + case ParsedExpressionKind::LiteralInteger: + return new BoundLiteralIntegerExpression(((LiteralIntegerExpression *) expression)->GetValue(), + expression->GetStartPosition(), expression->GetLength()); + case ParsedExpressionKind::LiteralFloat: + return new BoundLiteralFloatExpression(((LiteralFloatExpression *) expression)->GetValue(), + expression->GetStartPosition(), expression->GetLength()); + case ParsedExpressionKind::LiteralString: + return new BoundLiteralStringExpression(((LiteralStringExpression *) expression)->GetValue(), + expression->GetStartPosition(), expression->GetLength()); + case ParsedExpressionKind::LiteralBool: + return new BoundLiteralBoolExpression(((LiteralBoolExpression *) expression)->GetValue(), + expression->GetStartPosition(), expression->GetLength()); + case ParsedExpressionKind::Variable: + return this->BindVariableExpression((VariableExpression *) expression); + + case ParsedExpressionKind::Binary: + return this->BindBinaryOperator((BinaryExpression *) expression); + case ParsedExpressionKind::Unary: + return this->BindUnaryOperator((UnaryExpression *) expression); + + case ParsedExpressionKind::Parenthesized: + return BindExpression(((ParenthesizedExpression *) expression)->GetInnerExpression()); + case ParsedExpressionKind::FunctionCall: + return this->BindFunctionCall((FunctionCallExpression *) expression); + + case ParsedExpressionKind::Indexer: + return this->BindIndexExpression((IndexExpression *) expression, false); + case ParsedExpressionKind::PeriodIndexer: + return this->BindPeriodIndexExpression((PeriodIndexExpression *) expression, false); + case ParsedExpressionKind::NumericalTable: + return this->BindNumericalTableExpression((ParsedNumericalTableExpression *) expression); + case ParsedExpressionKind::Table: + return this->BindTableExpression((ParsedTableExpression *) expression); + + case ParsedExpressionKind::Bad: + return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); + } } - auto boundBlock = this -> BindStatement(conditionalStatement->GetBlock()); - BoundStatement* elseStatement = nullptr; - if (conditionalStatement->GetElseStatement() != nullptr){ - elseStatement = this -> BindStatement(conditionalStatement->GetElseStatement()); - } - return new BoundConditionalStatement(boundCondition, boundBlock, elseStatement); -} -BoundExpression* Binder::BindExpression(const ParsedExpression* expression){ - switch (expression -> GetKind()){ - case ParsedExpressionKind ::LiteralInteger: - return new BoundLiteralIntegerExpression(((LiteralIntegerExpression*)expression)->GetValue(), expression->GetStartPosition(), expression->GetLength()); - case ParsedExpressionKind ::LiteralFloat: - return new BoundLiteralFloatExpression(((LiteralFloatExpression*)expression)->GetValue(), expression->GetStartPosition(), expression->GetLength()); - case ParsedExpressionKind ::LiteralString: - return new BoundLiteralStringExpression(((LiteralStringExpression*)expression)->GetValue(), expression->GetStartPosition(), expression->GetLength()); - case ParsedExpressionKind ::LiteralBool: - return new BoundLiteralBoolExpression(((LiteralBoolExpression*)expression)->GetValue(), expression->GetStartPosition(), expression->GetLength()); - case ParsedExpressionKind ::Variable: - return this -> BindVariableExpression((VariableExpression*)expression); - - case ParsedExpressionKind ::Binary: - return this -> BindBinaryOperator((BinaryExpression*)expression); - case ParsedExpressionKind ::Unary: - return this -> BindUnaryOperator((UnaryExpression*)expression); - - case ParsedExpressionKind ::Parenthesized: - return BindExpression(((ParenthesizedExpression*)expression)->GetInnerExpression()); - case ParsedExpressionKind ::FunctionCall: - return this->BindFunctionCall((FunctionCallExpression*)expression); - - case ParsedExpressionKind ::Indexer: - return this->BindIndexExpression((IndexExpression*)expression, false); - case ParsedExpressionKind::PeriodIndexer: - return this -> BindPeriodIndexExpression((PeriodIndexExpression*)expression, false); - case ParsedExpressionKind::NumericalTable: - return this -> BindNumericalTableExpression((ParsedNumericalTableExpression*)expression); - case ParsedExpressionKind ::Table: - return this -> BindTableExpression((ParsedTableExpression*)expression); - - case ParsedExpressionKind ::Bad: - return new BoundBadExpression(expression->GetStartPosition(), expression-> GetLength()); - } -} - -BoundExpression* Binder::BindVariableExpression(const VariableExpression* expression){ - auto key = expression->GetValue(); - auto scope = this->_scope->Exists(key.GetHash()); - if (scope == -1){ - this -> _scriptData -> Diagnostics->LogError(DiagnosticCode::VariableNotFound, expression->GetStartPosition(), expression->GetLength()); - return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); - } - auto var = this->_scope->GetVariable(scope, key.GetHash()); - auto type = var->GetType(); - return new BoundVariableExpression(new BoundVariableKey(key.GetHash(), scope, false), type, expression->GetStartPosition(), expression->GetLength()); -} - -BoundExpression* Binder::BindBinaryOperator(const BinaryExpression* expression){ - auto boundLeft = this -> BindExpression(expression->GetLeft()); - auto boundRight = this -> BindExpression(expression->GetRight()); - - auto boundLeftType = boundLeft->GetType(); - auto boundRightType = boundRight->GetType(); - - switch (expression->GetOperatorKind()){ - case BinaryOperatorKind ::Addition: - if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number){ - auto leftNumeric = std::dynamic_pointer_cast(boundLeftType); - auto rightNumeric = std::dynamic_pointer_cast(boundRightType); - if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ - return new BoundBinaryExpression(boundLeft, boundRight, - BoundBinaryOperation::Addition, - std::make_shared(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()), - expression->GetStartPosition(), expression->GetLength()); - } - else{ - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Addition, - std::make_shared(false, false), - expression->GetStartPosition(), expression->GetLength()); - } - } else if (boundLeftType->GetClass() == TypeClass::String){ - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Concatenation, std::make_shared(false, - 0), - expression->GetStartPosition(), expression->GetLength()); - } - break; - case BinaryOperatorKind ::Subtraction: - if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number){ - auto leftNumeric = std::dynamic_pointer_cast(boundLeftType); - auto rightNumeric = std::dynamic_pointer_cast(boundRightType); - if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ - return new BoundBinaryExpression(boundLeft, boundRight, - BoundBinaryOperation::Subtraction, - std::make_shared(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()), - expression->GetStartPosition(), expression->GetLength()); - } - else{ - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Subtraction, - std::make_shared(false, false), - expression->GetStartPosition(), expression->GetLength()); - } - } - break; - case BinaryOperatorKind ::Multiplication: - if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number){ - auto leftNumeric = std::dynamic_pointer_cast(boundLeftType); - auto rightNumeric = std::dynamic_pointer_cast(boundRightType); - if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ - return new BoundBinaryExpression(boundLeft, boundRight, - BoundBinaryOperation::Multiplication, - std::make_shared(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()), - expression->GetStartPosition(), expression->GetLength()); - } - else{ - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Multiplication, - std::make_shared(false, false), - expression->GetStartPosition(), expression->GetLength()); - } - } - break; - case BinaryOperatorKind ::Division: - if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number){ - auto leftNumeric = std::dynamic_pointer_cast(boundLeftType); - auto rightNumeric = std::dynamic_pointer_cast(boundRightType); - if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ - return new BoundBinaryExpression(boundLeft, boundRight, - BoundBinaryOperation::Division, - std::make_shared(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()), - expression->GetStartPosition(), expression->GetLength()); - } - else{ - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Division, - std::make_shared(false, false), - expression->GetStartPosition(), expression->GetLength()); - } - } - break; - case BinaryOperatorKind ::Equality: - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Equality, std::make_shared(TypeClass::Bool), - expression->GetStartPosition(), expression->GetLength()); - case BinaryOperatorKind ::Inequality: - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Inequality, std::make_shared(TypeClass::Bool), - expression->GetStartPosition(), expression->GetLength()); - case BinaryOperatorKind ::Less: - if (boundLeft->GetType()->GetClass() == TypeClass::Number && boundRight->GetType()->GetClass() == TypeClass::Number){ - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LessThan, std::make_shared(TypeClass::Bool), - expression->GetStartPosition(), expression->GetLength()); - } - case BinaryOperatorKind ::LessOrEquals: - if (boundLeft->GetType()->GetClass() == TypeClass::Number && boundRight->GetType()->GetClass() == TypeClass::Number){ - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LessThanEquals, std::make_shared(TypeClass::Bool), - expression->GetStartPosition(), expression->GetLength()); - } - case BinaryOperatorKind ::Greater: - if (boundLeft->GetType()->GetClass() == TypeClass::Number && boundRight->GetType()->GetClass() == TypeClass::Number){ - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::GreaterThan, std::make_shared(TypeClass::Bool), - expression->GetStartPosition(), expression->GetLength()); - } - case BinaryOperatorKind ::GreaterOrEquals: - if (boundLeft->GetType()->GetClass() == TypeClass::Number && boundRight->GetType()->GetClass() == TypeClass::Number){ - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::GreaterThanEquals, std::make_shared(TypeClass::Bool), - expression->GetStartPosition(), expression->GetLength()); - } - case BinaryOperatorKind ::LogicalAnd: - if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool) - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LogicalAnd, std::make_shared(TypeClass::Bool), - expression->GetStartPosition(), expression->GetLength()); - break; - case BinaryOperatorKind ::LogicalOr: - if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool) - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LogicalOr, std::make_shared(TypeClass::Bool), - expression->GetStartPosition(), expression->GetLength()); - break; - } - this -> _scriptData -> Diagnostics->LogError(DiagnosticCode::NoBinaryOperationFound, expression->GetStartPosition(), expression->GetLength()); - return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); -} - -BoundExpression* Binder::BindUnaryOperator(const UnaryExpression* expression){ - auto operand = this -> BindExpression(expression->GetOperand()); - auto operandType = operand -> GetType(); - switch (expression->GetOperatorKind()){ - case UnaryOperatorKind ::Identity: - if (operandType->GetClass() == TypeClass::Number){ - // Identity won't change anything during evaluation, so just return the inner operand. - return operand; - } - break; - case UnaryOperatorKind ::Negation: - if (operandType->GetClass() == TypeClass::Number){ - auto innerType = std::dynamic_pointer_cast(operandType); - return new BoundUnaryExpression(operand, BoundUnaryOperation::Negation, - std::make_shared(innerType.get()->IsAwareOfFloat(), innerType.get()->IsFloat()), - expression->GetStartPosition(), expression->GetLength()); - } - break; - case UnaryOperatorKind ::LogicalNegation: - if (operandType->GetClass() == TypeClass::Bool){ - return new BoundUnaryExpression(operand, BoundUnaryOperation::LogicalNegation, - std::make_shared(TypeClass::Bool), - expression->GetStartPosition(), expression->GetLength()); - } - break; - default: - break; - } - this -> _scriptData -> Diagnostics->LogError(DiagnosticCode::NoUnaryOperationFound, expression->GetStartPosition(), expression->GetLength()); - return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); - -} - -BoundExpression* Binder::BindFunctionCall(const FunctionCallExpression* expression){ - auto functionExpression = BindExpression(expression->GetFunction()); - auto type = functionExpression->GetType(); - if (type->GetClass() != TypeClass::Function){ - this->_scriptData->Diagnostics->LogError(DiagnosticCode::ExpressionIsNotAFunction, expression->GetStartPosition(), - expression->GetLength()); - return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); - } - auto functionType = std::dynamic_pointer_cast(type); - auto parameterTypes = functionType->GetParameterTypes(); - auto givenParameters = expression->GetParameters(); - if (parameterTypes.size() != givenParameters->size()){ - this->_scriptData->Diagnostics->LogError(DiagnosticCode::ParameterCountMismatch, expression->GetStartPosition(), - expression->GetLength()); - return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); - } - vector boundParameters = vector(givenParameters->size()); - for (int i = 0; i < givenParameters->size(); i++){ - auto parameter = givenParameters -> at(i); - auto boundParameter = this -> BindExpression(parameter); - if (boundParameter->GetType().get()->operator!=(parameterTypes.at(i).get())){ - this->_scriptData->Diagnostics->LogError(DiagnosticCode::ParameterTypeMismatch, parameter->GetStartPosition(), - parameter->GetLength()); + BoundExpression *Binder::BindVariableExpression(const VariableExpression *expression) { + auto key = expression->GetValue(); + auto scope = this->_scope->Exists(key.GetHash()); + if (scope == -1) { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::VariableNotFound, expression->GetStartPosition(), + expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); } - boundParameters[i] = boundParameter; + auto var = this->_scope->GetVariable(scope, key.GetHash()); + auto type = var->GetType(); + return new BoundVariableExpression(new BoundVariableKey(key.GetHash(), scope, false), type, + expression->GetStartPosition(), expression->GetLength()); } - return new BoundFunctionCallExpression(functionExpression, boundParameters, functionType.get()->GetReturnType(), - expression->GetStartPosition(), expression->GetLength()); -} + BoundExpression *Binder::BindBinaryOperator(const BinaryExpression *expression) { + auto boundLeft = this->BindExpression(expression->GetLeft()); + auto boundRight = this->BindExpression(expression->GetRight()); -BoundExpression *Binder::BindIndexExpression(const IndexExpression *expression, bool setter) { - auto indexer = this->BindExpression(expression->GetIndexer()); - auto index = this->BindExpression(expression->GetIndex()); + auto boundLeftType = boundLeft->GetType(); + auto boundRightType = boundRight->GetType(); - auto indexerType = indexer -> GetType(); - if (!indexerType->CanBeIndexedWith(index->GetType().get())){ - this->_scriptData->Diagnostics->LogError(DiagnosticCode::CantIndex, index->GetStartPosition(), - index->GetLength()); - return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); - } - if (indexerType -> GetClass() == TypeClass::UserData){ - auto stringKey = dynamic_pointer_cast(index -> GetType()); - auto field = dynamic_pointer_cast(indexerType) -> GetField(stringKey->GetHashValue()); - if (!setter){ - if (!field->HasGetter()){ - this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoGetter, index->GetStartPosition(), - index->GetLength()); - return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); - } - } else{ - if (!field->HasSetter()){ - this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoSetter, index->GetStartPosition(), - index->GetLength()); - return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); - } + switch (expression->GetOperatorKind()) { + case BinaryOperatorKind::Addition: + if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number) { + auto leftNumeric = std::dynamic_pointer_cast(boundLeftType); + auto rightNumeric = std::dynamic_pointer_cast(boundRightType); + if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()) { + return new BoundBinaryExpression(boundLeft, boundRight, + BoundBinaryOperation::Addition, + std::make_shared(true, + leftNumeric->IsFloat() || + rightNumeric->IsFloat()), + expression->GetStartPosition(), expression->GetLength()); + } else { + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Addition, + std::make_shared(false, false), + expression->GetStartPosition(), expression->GetLength()); + } + } else if (boundLeftType->GetClass() == TypeClass::String) { + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Concatenation, + std::make_shared(false, + 0), + expression->GetStartPosition(), expression->GetLength()); + } + break; + case BinaryOperatorKind::Subtraction: + if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number) { + auto leftNumeric = std::dynamic_pointer_cast(boundLeftType); + auto rightNumeric = std::dynamic_pointer_cast(boundRightType); + if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()) { + return new BoundBinaryExpression(boundLeft, boundRight, + BoundBinaryOperation::Subtraction, + std::make_shared(true, + leftNumeric->IsFloat() || + rightNumeric->IsFloat()), + expression->GetStartPosition(), expression->GetLength()); + } else { + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Subtraction, + std::make_shared(false, false), + expression->GetStartPosition(), expression->GetLength()); + } + } + break; + case BinaryOperatorKind::Multiplication: + if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number) { + auto leftNumeric = std::dynamic_pointer_cast(boundLeftType); + auto rightNumeric = std::dynamic_pointer_cast(boundRightType); + if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()) { + return new BoundBinaryExpression(boundLeft, boundRight, + BoundBinaryOperation::Multiplication, + std::make_shared(true, + leftNumeric->IsFloat() || + rightNumeric->IsFloat()), + expression->GetStartPosition(), expression->GetLength()); + } else { + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Multiplication, + std::make_shared(false, false), + expression->GetStartPosition(), expression->GetLength()); + } + } + break; + case BinaryOperatorKind::Division: + if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number) { + auto leftNumeric = std::dynamic_pointer_cast(boundLeftType); + auto rightNumeric = std::dynamic_pointer_cast(boundRightType); + if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()) { + return new BoundBinaryExpression(boundLeft, boundRight, + BoundBinaryOperation::Division, + std::make_shared(true, + leftNumeric->IsFloat() || + rightNumeric->IsFloat()), + expression->GetStartPosition(), expression->GetLength()); + } else { + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Division, + std::make_shared(false, false), + expression->GetStartPosition(), expression->GetLength()); + } + } + break; + case BinaryOperatorKind::Equality: + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Equality, + std::make_shared(TypeClass::Bool), + expression->GetStartPosition(), expression->GetLength()); + case BinaryOperatorKind::Inequality: + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Inequality, + std::make_shared(TypeClass::Bool), + expression->GetStartPosition(), expression->GetLength()); + case BinaryOperatorKind::Less: + if (boundLeft->GetType()->GetClass() == TypeClass::Number && + boundRight->GetType()->GetClass() == TypeClass::Number) { + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LessThan, + std::make_shared(TypeClass::Bool), + expression->GetStartPosition(), expression->GetLength()); + } + case BinaryOperatorKind::LessOrEquals: + if (boundLeft->GetType()->GetClass() == TypeClass::Number && + boundRight->GetType()->GetClass() == TypeClass::Number) { + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LessThanEquals, + std::make_shared(TypeClass::Bool), + expression->GetStartPosition(), expression->GetLength()); + } + case BinaryOperatorKind::Greater: + if (boundLeft->GetType()->GetClass() == TypeClass::Number && + boundRight->GetType()->GetClass() == TypeClass::Number) { + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::GreaterThan, + std::make_shared(TypeClass::Bool), + expression->GetStartPosition(), expression->GetLength()); + } + case BinaryOperatorKind::GreaterOrEquals: + if (boundLeft->GetType()->GetClass() == TypeClass::Number && + boundRight->GetType()->GetClass() == TypeClass::Number) { + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::GreaterThanEquals, + std::make_shared(TypeClass::Bool), + expression->GetStartPosition(), expression->GetLength()); + } + case BinaryOperatorKind::LogicalAnd: + if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool) + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LogicalAnd, + std::make_shared(TypeClass::Bool), + expression->GetStartPosition(), expression->GetLength()); + break; + case BinaryOperatorKind::LogicalOr: + if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool) + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LogicalOr, + std::make_shared(TypeClass::Bool), + expression->GetStartPosition(), expression->GetLength()); + break; } - } - - auto resultType = indexer->GetType()->GetIndexedType(index->GetType().get()); - return new BoundIndexExpression(indexer, index, resultType, expression->GetStartPosition(), expression->GetLength()); -} - -BoundExpression* Binder::BindPeriodIndexExpression(const PeriodIndexExpression* expression, bool setter){ - auto indexer = this->BindExpression(expression->GetIndexer()); - const auto& identifier = expression->GetIndex(); - const auto& indexerType = indexer -> GetType(); - if (!indexerType -> CanBeIndexedWithIdentifier(identifier.GetHash())){ - this->_scriptData->Diagnostics->LogError(DiagnosticCode::CantIndex, expression->GetStartPosition(), + this->_scriptData->Diagnostics->LogError(DiagnosticCode::NoBinaryOperationFound, expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); } - if (indexerType -> GetClass() == TypeClass::UserData){ - auto field = dynamic_pointer_cast(indexerType) -> GetField(identifier . GetHash()); - if (!setter){ - if (!field->HasGetter()){ - this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoGetter, expression->GetStartPosition(), - expression->GetLength()); + + BoundExpression *Binder::BindUnaryOperator(const UnaryExpression *expression) { + auto operand = this->BindExpression(expression->GetOperand()); + auto operandType = operand->GetType(); + switch (expression->GetOperatorKind()) { + case UnaryOperatorKind::Identity: + if (operandType->GetClass() == TypeClass::Number) { + // Identity won't change anything during evaluation, so just return the inner operand. + return operand; + } + break; + case UnaryOperatorKind::Negation: + if (operandType->GetClass() == TypeClass::Number) { + auto innerType = std::dynamic_pointer_cast(operandType); + return new BoundUnaryExpression(operand, BoundUnaryOperation::Negation, + std::make_shared( + innerType.get()->IsAwareOfFloat(), + innerType.get()->IsFloat()), + expression->GetStartPosition(), expression->GetLength()); + } + break; + case UnaryOperatorKind::LogicalNegation: + if (operandType->GetClass() == TypeClass::Bool) { + return new BoundUnaryExpression(operand, BoundUnaryOperation::LogicalNegation, + std::make_shared(TypeClass::Bool), + expression->GetStartPosition(), expression->GetLength()); + } + break; + default: + break; + } + this->_scriptData->Diagnostics->LogError(DiagnosticCode::NoUnaryOperationFound, expression->GetStartPosition(), + expression->GetLength()); + return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); + + } + + BoundExpression *Binder::BindFunctionCall(const FunctionCallExpression *expression) { + auto functionExpression = BindExpression(expression->GetFunction()); + auto type = functionExpression->GetType(); + if (type->GetClass() != TypeClass::Function) { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::ExpressionIsNotAFunction, + expression->GetStartPosition(), + expression->GetLength()); + return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); + } + auto functionType = std::dynamic_pointer_cast(type); + auto parameterTypes = functionType->GetParameterTypes(); + auto givenParameters = expression->GetParameters(); + if (parameterTypes.size() != givenParameters->size()) { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::ParameterCountMismatch, + expression->GetStartPosition(), + expression->GetLength()); + return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); + } + vector boundParameters = vector(givenParameters->size()); + for (int i = 0; i < givenParameters->size(); i++) { + auto parameter = givenParameters->at(i); + auto boundParameter = this->BindExpression(parameter); + if (boundParameter->GetType().get()->operator!=(parameterTypes.at(i).get())) { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::ParameterTypeMismatch, + parameter->GetStartPosition(), + parameter->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); } - } else{ - if (!field->HasSetter()){ - this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoSetter, expression->GetStartPosition(), - expression->GetLength()); - return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); + boundParameters[i] = boundParameter; + } + + return new BoundFunctionCallExpression(functionExpression, boundParameters, functionType.get()->GetReturnType(), + expression->GetStartPosition(), expression->GetLength()); + } + + BoundExpression *Binder::BindIndexExpression(const IndexExpression *expression, bool setter) { + auto indexer = this->BindExpression(expression->GetIndexer()); + auto index = this->BindExpression(expression->GetIndex()); + + auto indexerType = indexer->GetType(); + if (!indexerType->CanBeIndexedWith(index->GetType().get())) { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::CantIndex, index->GetStartPosition(), + index->GetLength()); + return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); + } + if (indexerType->GetClass() == TypeClass::UserData) { + auto stringKey = dynamic_pointer_cast(index->GetType()); + auto field = dynamic_pointer_cast(indexerType)->GetField(stringKey->GetHashValue()); + if (!setter) { + if (!field->HasGetter()) { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoGetter, + index->GetStartPosition(), + index->GetLength()); + return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); + } + } else { + if (!field->HasSetter()) { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoSetter, + index->GetStartPosition(), + index->GetLength()); + return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); + } } } + + auto resultType = indexer->GetType()->GetIndexedType(index->GetType().get()); + return new BoundIndexExpression(indexer, index, resultType, expression->GetStartPosition(), + expression->GetLength()); } - auto resultType = indexer->GetType()->GetIndexedType(identifier . GetHash()); - return new BoundPeriodIndexExpression(indexer, identifier, resultType, expression->GetStartPosition(), expression->GetLength()); - -} - -BoundExpression* Binder::BindNumericalTableExpression(const ParsedNumericalTableExpression* expression){ - auto expressions = expression->GetExpressions(); - auto boundExpressions = vector(expressions-> size()); - shared_ptr valueType = nullptr; - if (!boundExpressions.empty()){ - boundExpressions[0] = this -> BindExpression(expressions -> at(0)); - valueType = boundExpressions[0] -> GetType(); - for (int i = 1; i < expressions->size(); i++){ - boundExpressions[i] = this -> BindExpression(expressions -> at(i)); - if (boundExpressions[i] -> GetType().get()->operator!=(valueType.get())){ - this->_scriptData->Diagnostics->LogError(DiagnosticCode::InvalidTableValueType, boundExpressions[i]->GetStartPosition(), - boundExpressions[i]->GetLength()); + BoundExpression *Binder::BindPeriodIndexExpression(const PeriodIndexExpression *expression, bool setter) { + auto indexer = this->BindExpression(expression->GetIndexer()); + const auto &identifier = expression->GetIndex(); + const auto &indexerType = indexer->GetType(); + if (!indexerType->CanBeIndexedWithIdentifier(identifier.GetHash())) { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::CantIndex, expression->GetStartPosition(), + expression->GetLength()); + return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); + } + if (indexerType->GetClass() == TypeClass::UserData) { + auto field = dynamic_pointer_cast(indexerType)->GetField(identifier.GetHash()); + if (!setter) { + if (!field->HasGetter()) { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoGetter, + expression->GetStartPosition(), + expression->GetLength()); + return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); + } + } else { + if (!field->HasSetter()) { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoSetter, + expression->GetStartPosition(), + expression->GetLength()); + return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); + } } } + + auto resultType = indexer->GetType()->GetIndexedType(identifier.GetHash()); + return new BoundPeriodIndexExpression(indexer, identifier, resultType, expression->GetStartPosition(), + expression->GetLength()); + } - if (valueType == nullptr){ - valueType = std::make_shared(TypeClass::Nil); + + BoundExpression *Binder::BindNumericalTableExpression(const ParsedNumericalTableExpression *expression) { + auto expressions = expression->GetExpressions(); + auto boundExpressions = vector(expressions->size()); + shared_ptr valueType = nullptr; + if (!boundExpressions.empty()) { + boundExpressions[0] = this->BindExpression(expressions->at(0)); + valueType = boundExpressions[0]->GetType(); + for (int i = 1; i < expressions->size(); i++) { + boundExpressions[i] = this->BindExpression(expressions->at(i)); + if (boundExpressions[i]->GetType().get()->operator!=(valueType.get())) { + this->_scriptData->Diagnostics->LogError(DiagnosticCode::InvalidTableValueType, + boundExpressions[i]->GetStartPosition(), + boundExpressions[i]->GetLength()); + } + } + } + if (valueType == nullptr) { + valueType = std::make_shared(TypeClass::Nil); + } + auto tableType = std::make_shared(valueType); + return new BoundNumericalTableExpression(boundExpressions, tableType, expression->GetStartPosition(), + expression->GetLength()); + } + + BoundExpression *Binder::BindTableExpression(const ParsedTableExpression *expression) { + auto tableScope = new unordered_map(); + auto innerScope = new BoundScope(tableScope); + auto currentScope = this->_scope; + this->_scope = innerScope; + auto block = this->BindBlockStatement(expression->GetBlock()); + this->_scope = currentScope; + + auto tableType = std::make_shared(tableScope, innerScope->GetLocalVariableCount()); + delete innerScope; + + return new BoundTableExpression((BoundBlockStatement *) block, tableType, expression->GetStartPosition(), + expression->GetLength()); } - auto tableType = std::make_shared(valueType); - return new BoundNumericalTableExpression(boundExpressions, tableType, expression->GetStartPosition(), expression->GetLength()); } - -BoundExpression *Binder::BindTableExpression(const ParsedTableExpression *expression) { - auto tableScope = new unordered_map(); - auto innerScope = new BoundScope(tableScope); - auto currentScope = this -> _scope; - this -> _scope = innerScope; - auto block = this -> BindBlockStatement(expression -> GetBlock()); - this -> _scope = currentScope; - - auto tableType = std::make_shared(tableScope, innerScope->GetLocalVariableCount()); - delete innerScope; - - return new BoundTableExpression((BoundBlockStatement*)block, tableType, expression->GetStartPosition(), expression->GetLength()); -} - diff --git a/src/Binder/Binder.hpp b/src/Binder/Binder.hpp index baf13d7..945f26b 100644 --- a/src/Binder/Binder.hpp +++ b/src/Binder/Binder.hpp @@ -8,36 +8,54 @@ #include "../Parser/ParsedExpressions/ParsedTableExpression.hpp" using namespace std; +using namespace Porygon::Parser; -class Binder { - Script* _scriptData; - BoundScope* _scope; - shared_ptr _currentFunction; +namespace Porygon::Binder { + class Binder { + Porygon::Script *_scriptData; + BoundScope *_scope; + shared_ptr _currentFunction; - ~Binder(); + ~Binder(); - BoundStatement *BindStatement(const ParsedStatement *statement); - BoundStatement *BindBlockStatement(const ParsedStatement *statement); - BoundStatement *BindExpressionStatement(const ParsedStatement *statement); - BoundStatement *BindAssignmentStatement(const ParsedStatement *statement); - BoundStatement *BindIndexAssignmentStatement(const ParsedStatement *statement); - BoundStatement *BindFunctionDeclarationStatement(const ParsedStatement * statement); - BoundStatement *BindReturnStatement(const ParsedStatement *statement); - BoundStatement *BindConditionalStatement(const ParsedStatement *statement); + BoundStatement *BindStatement(const ParsedStatement *statement); - BoundExpression *BindExpression(const ParsedExpression *expression); - BoundExpression *BindVariableExpression(const VariableExpression *expression); - BoundExpression *BindBinaryOperator(const BinaryExpression *expression); - BoundExpression *BindUnaryOperator(const UnaryExpression *expression); - BoundExpression *BindFunctionCall(const FunctionCallExpression *expression); - BoundExpression *BindIndexExpression(const IndexExpression *expression, bool setter); - BoundExpression *BindNumericalTableExpression(const ParsedNumericalTableExpression *expression); - BoundExpression *BindTableExpression(const ParsedTableExpression * expression); -public: - static BoundScriptStatement* Bind(Script* script, const ParsedScriptStatement* s, BoundScope* scriptScope); + BoundStatement *BindBlockStatement(const ParsedStatement *statement); - BoundExpression *BindPeriodIndexExpression(const PeriodIndexExpression *expression, bool setter); -}; + BoundStatement *BindExpressionStatement(const ParsedStatement *statement); + BoundStatement *BindAssignmentStatement(const ParsedStatement *statement); + + BoundStatement *BindIndexAssignmentStatement(const ParsedStatement *statement); + + BoundStatement *BindFunctionDeclarationStatement(const ParsedStatement *statement); + + BoundStatement *BindReturnStatement(const ParsedStatement *statement); + + BoundStatement *BindConditionalStatement(const ParsedStatement *statement); + + BoundExpression *BindExpression(const ParsedExpression *expression); + + BoundExpression *BindVariableExpression(const VariableExpression *expression); + + BoundExpression *BindBinaryOperator(const BinaryExpression *expression); + + BoundExpression *BindUnaryOperator(const UnaryExpression *expression); + + BoundExpression *BindFunctionCall(const FunctionCallExpression *expression); + + BoundExpression *BindIndexExpression(const IndexExpression *expression, bool setter); + + BoundExpression *BindNumericalTableExpression(const ParsedNumericalTableExpression *expression); + + BoundExpression *BindTableExpression(const ParsedTableExpression *expression); + + public: + static BoundScriptStatement * + Bind(Porygon::Script *script, const ParsedScriptStatement *s, BoundScope *scriptScope); + + BoundExpression *BindPeriodIndexExpression(const PeriodIndexExpression *expression, bool setter); + }; +} #endif //PORYGONLANG_BINDER_HPP diff --git a/src/Binder/BoundExpressions/BoundExpression.hpp b/src/Binder/BoundExpressions/BoundExpression.hpp index 16c10f2..4c99fb6 100644 --- a/src/Binder/BoundExpressions/BoundExpression.hpp +++ b/src/Binder/BoundExpressions/BoundExpression.hpp @@ -10,322 +10,330 @@ using namespace std; -enum class BoundExpressionKind{ - Bad, +namespace Porygon::Binder { + enum class BoundExpressionKind { + Bad, - LiteralInteger, - LiteralFloat, - LiteralString, - LiteralBool, - Variable, + LiteralInteger, + LiteralFloat, + LiteralString, + LiteralBool, + Variable, - Unary, - Binary, - FunctionCall, - Index, - PeriodIndex, - NumericalTable, - Table, -}; - -class BoundExpression{ - const unsigned int _start; - const unsigned int _length; - const shared_ptr _type; -public: - BoundExpression(unsigned int start, unsigned int length, shared_ptr type) - : _start(start), - _length(length), - _type(std::move(type)) - { - } - - virtual ~BoundExpression() = default; - - virtual const BoundExpressionKind GetKind() const = 0; - virtual const std::shared_ptr& GetType() const{ - return _type; + Unary, + Binary, + FunctionCall, + Index, + PeriodIndex, + NumericalTable, + Table, }; - const unsigned int GetStartPosition() const{ - return _start; - } - const unsigned int GetLength() const{ - return _length; - } - const unsigned int GetEndPosition() const{ - return _start + _length - 1; - } -}; - -class BoundBadExpression : public BoundExpression{ -public: - BoundBadExpression(unsigned int start, unsigned int length) : BoundExpression(start, length, make_shared(TypeClass::Error)){} - - const BoundExpressionKind GetKind() const final{ - return BoundExpressionKind ::Bad; - } -}; - -class BoundLiteralIntegerExpression : public BoundExpression{ - const long _value; -public: - BoundLiteralIntegerExpression(long value, unsigned int start, unsigned int length) - : BoundExpression(start, length, make_shared(true, false)), - _value(value) - { - } - - const BoundExpressionKind GetKind() const final{ - return BoundExpressionKind ::LiteralInteger; - } - - const long GetValue() const{ - return _value; - } -}; - -class BoundLiteralFloatExpression : public BoundExpression{ - const double _value; -public: - BoundLiteralFloatExpression(double value, unsigned int start, unsigned int length) - : BoundExpression(start, length, make_shared(true, true)), - _value(value) - { - } - - const BoundExpressionKind GetKind() const final{ - return BoundExpressionKind ::LiteralFloat; - } - - const double GetValue() const{ - return _value; - } -}; - -class BoundLiteralStringExpression : public BoundExpression{ - const u16string _value; -public: - BoundLiteralStringExpression(const u16string& value, unsigned int start, unsigned int length) - : BoundExpression(start, length, make_shared(true, HashedString::ConstHash(value.c_str()))), - _value(value) - { - } - - const BoundExpressionKind GetKind() const final{ - return BoundExpressionKind ::LiteralString; - } - - const u16string GetValue() const{ - return _value; - } -}; - -class BoundLiteralBoolExpression : public BoundExpression{ - const bool _value; -public: - BoundLiteralBoolExpression(bool value, unsigned int start, unsigned int length) - : BoundExpression(start, length, make_shared(TypeClass::Bool)), - _value(value) - { - } - - const BoundExpressionKind GetKind() const final{ - return BoundExpressionKind ::LiteralBool; - } - - const bool GetValue() const{ - return _value; - } -}; - -class BoundVariableExpression : public BoundExpression{ - const BoundVariableKey* _key; -public: - BoundVariableExpression(BoundVariableKey* key, shared_ptr type, unsigned int start, unsigned int length) - : BoundExpression(start, length, std::move(type)), - _key(key) - { - } - - ~BoundVariableExpression() override{ - delete _key; - } - - const BoundExpressionKind GetKind() const final{ - return BoundExpressionKind ::Variable; - } - - const BoundVariableKey* GetKey() const{ - return _key; - } -}; - -class BoundBinaryExpression : public BoundExpression { - const BoundExpression* _left; - const BoundExpression* _right; - const BoundBinaryOperation _operation; -public: - BoundBinaryExpression(BoundExpression* left, BoundExpression* right, BoundBinaryOperation op, shared_ptr result, - unsigned int start, unsigned int length) - : BoundExpression(start, length, std::move(result)), - _left(left), - _right(right), - _operation(op) - { - } - - ~BoundBinaryExpression() final{ - delete _left; - delete _right; - } - - const BoundExpressionKind GetKind() const final{ - return BoundExpressionKind ::Binary; - } - - const BoundExpression* GetLeft() const{ - return _left; - } - - const BoundExpression* GetRight() const{ - return _right; - } - - const BoundBinaryOperation GetOperation() const{ - return _operation; - } -}; - -class BoundUnaryExpression : public BoundExpression { - const BoundExpression* _operand; - const BoundUnaryOperation _operation; -public: - BoundUnaryExpression(BoundExpression* operand, BoundUnaryOperation op, shared_ptr result, unsigned int start, unsigned int length) - : BoundExpression(start, length, std::move(result)), - _operand(operand), - _operation(op) - { - } - - ~BoundUnaryExpression() final{ - delete _operand; - } - - const BoundExpressionKind GetKind() const final{ - return BoundExpressionKind ::Unary; - } - - const BoundExpression* GetOperand() const{ - return _operand; - } - - const BoundUnaryOperation GetOperation() const{ - return _operation; - } -}; - -class BoundFunctionCallExpression : public BoundExpression { - const BoundExpression* _functionExpression; - const vector _parameters; -public: - BoundFunctionCallExpression(BoundExpression *functionExpression, vector parameters, shared_ptr result, - unsigned int start, unsigned int length) - : BoundExpression(start, length, std::move(result)), _functionExpression(functionExpression), _parameters(std::move(parameters)) {} - - ~BoundFunctionCallExpression() final{ - delete _functionExpression; - for (auto p : _parameters){ - delete p; + class BoundExpression { + const unsigned int _start; + const unsigned int _length; + const shared_ptr _type; + public: + BoundExpression(unsigned int start, unsigned int length, shared_ptr type) + : _start(start), + _length(length), + _type(std::move(type)) { } - } - const BoundExpressionKind GetKind() const final{ - return BoundExpressionKind ::FunctionCall; - } + virtual ~BoundExpression() = default; - const BoundExpression* GetFunctionExpression() const{ - return _functionExpression; - } + virtual const BoundExpressionKind GetKind() const = 0; - const vector* GetParameters() const{ - return &_parameters; - } -}; + virtual const std::shared_ptr &GetType() const { + return _type; + }; -class BoundIndexExpression : public BoundExpression { - const BoundExpression* _indexableExpression; - const BoundExpression* _indexExpression; -public: - BoundIndexExpression(BoundExpression* indexableExpression, BoundExpression* indexExpression, shared_ptr result, - unsigned int start, unsigned int length) - : BoundExpression(start, length, std::move(result)), _indexableExpression(indexableExpression), _indexExpression(indexExpression) {} - - ~BoundIndexExpression() final{ - delete _indexableExpression; - delete _indexExpression; - } - - const BoundExpressionKind GetKind() const final{ - return BoundExpressionKind ::Index; - } - - const BoundExpression* GetIndexableExpression() const{ - return _indexableExpression; - } - - const BoundExpression* GetIndexExpression() const{ - return _indexExpression; - } -}; - -class BoundPeriodIndexExpression : public BoundExpression { - const BoundExpression* _indexableExpression; - const HashedString _index; -public: - BoundPeriodIndexExpression(BoundExpression* indexableExpression, HashedString index, shared_ptr result, - unsigned int start, unsigned int length) - : BoundExpression(start, length, std::move(result)), _indexableExpression(indexableExpression), _index(index) {} - - ~BoundPeriodIndexExpression() final{ - delete _indexableExpression; - } - - const BoundExpressionKind GetKind() const final{ - return BoundExpressionKind ::PeriodIndex; - } - - const BoundExpression* GetIndexableExpression() const{ - return _indexableExpression; - } - - const HashedString GetIndex() const{ - return _index; - } -}; - -class BoundNumericalTableExpression : public BoundExpression{ - const vector _expressions; -public: - BoundNumericalTableExpression(vector expressions, shared_ptr type, unsigned int start, unsigned int length) - : BoundExpression(start, length, std::move(type)), - _expressions(std::move(expressions)) - {} - - ~BoundNumericalTableExpression() final{ - for (auto e: _expressions){ - delete e; + const unsigned int GetStartPosition() const { + return _start; } - } - const BoundExpressionKind GetKind() const final{ - return BoundExpressionKind ::NumericalTable; - } + const unsigned int GetLength() const { + return _length; + } - const vector* GetExpressions() const{ - return &_expressions; - } -}; + const unsigned int GetEndPosition() const { + return _start + _length - 1; + } + }; + class BoundBadExpression : public BoundExpression { + public: + BoundBadExpression(unsigned int start, unsigned int length) : BoundExpression(start, length, + make_shared( + TypeClass::Error)) {} + + const BoundExpressionKind GetKind() const final { + return BoundExpressionKind::Bad; + } + }; + + class BoundLiteralIntegerExpression : public BoundExpression { + const long _value; + public: + BoundLiteralIntegerExpression(long value, unsigned int start, unsigned int length) + : BoundExpression(start, length, make_shared(true, false)), + _value(value) { + } + + const BoundExpressionKind GetKind() const final { + return BoundExpressionKind::LiteralInteger; + } + + const long GetValue() const { + return _value; + } + }; + + class BoundLiteralFloatExpression : public BoundExpression { + const double _value; + public: + BoundLiteralFloatExpression(double value, unsigned int start, unsigned int length) + : BoundExpression(start, length, make_shared(true, true)), + _value(value) { + } + + const BoundExpressionKind GetKind() const final { + return BoundExpressionKind::LiteralFloat; + } + + const double GetValue() const { + return _value; + } + }; + + class BoundLiteralStringExpression : public BoundExpression { + const u16string _value; + public: + BoundLiteralStringExpression(const u16string &value, unsigned int start, unsigned int length) + : BoundExpression(start, length, + make_shared(true, Utilities::HashedString::ConstHash(value.c_str()))), + _value(value) { + } + + const BoundExpressionKind GetKind() const final { + return BoundExpressionKind::LiteralString; + } + + const u16string GetValue() const { + return _value; + } + }; + + class BoundLiteralBoolExpression : public BoundExpression { + const bool _value; + public: + BoundLiteralBoolExpression(bool value, unsigned int start, unsigned int length) + : BoundExpression(start, length, make_shared(TypeClass::Bool)), + _value(value) { + } + + const BoundExpressionKind GetKind() const final { + return BoundExpressionKind::LiteralBool; + } + + const bool GetValue() const { + return _value; + } + }; + + class BoundVariableExpression : public BoundExpression { + const BoundVariableKey *_key; + public: + BoundVariableExpression(BoundVariableKey *key, shared_ptr type, unsigned int start, + unsigned int length) + : BoundExpression(start, length, std::move(type)), + _key(key) { + } + + ~BoundVariableExpression() override { + delete _key; + } + + const BoundExpressionKind GetKind() const final { + return BoundExpressionKind::Variable; + } + + const BoundVariableKey *GetKey() const { + return _key; + } + }; + + class BoundBinaryExpression : public BoundExpression { + const BoundExpression *_left; + const BoundExpression *_right; + const BoundBinaryOperation _operation; + public: + BoundBinaryExpression(BoundExpression *left, BoundExpression *right, BoundBinaryOperation op, + shared_ptr result, + unsigned int start, unsigned int length) + : BoundExpression(start, length, std::move(result)), + _left(left), + _right(right), + _operation(op) { + } + + ~BoundBinaryExpression() final { + delete _left; + delete _right; + } + + const BoundExpressionKind GetKind() const final { + return BoundExpressionKind::Binary; + } + + const BoundExpression *GetLeft() const { + return _left; + } + + const BoundExpression *GetRight() const { + return _right; + } + + const BoundBinaryOperation GetOperation() const { + return _operation; + } + }; + + class BoundUnaryExpression : public BoundExpression { + const BoundExpression *_operand; + const BoundUnaryOperation _operation; + public: + BoundUnaryExpression(BoundExpression *operand, BoundUnaryOperation op, shared_ptr result, + unsigned int start, unsigned int length) + : BoundExpression(start, length, std::move(result)), + _operand(operand), + _operation(op) { + } + + ~BoundUnaryExpression() final { + delete _operand; + } + + const BoundExpressionKind GetKind() const final { + return BoundExpressionKind::Unary; + } + + const BoundExpression *GetOperand() const { + return _operand; + } + + const BoundUnaryOperation GetOperation() const { + return _operation; + } + }; + + class BoundFunctionCallExpression : public BoundExpression { + const BoundExpression *_functionExpression; + const vector _parameters; + public: + BoundFunctionCallExpression(BoundExpression *functionExpression, vector parameters, + shared_ptr result, + unsigned int start, unsigned int length) + : BoundExpression(start, length, std::move(result)), _functionExpression(functionExpression), + _parameters(std::move(parameters)) {} + + ~BoundFunctionCallExpression() final { + delete _functionExpression; + for (auto p : _parameters) { + delete p; + } + } + + const BoundExpressionKind GetKind() const final { + return BoundExpressionKind::FunctionCall; + } + + const BoundExpression *GetFunctionExpression() const { + return _functionExpression; + } + + const vector *GetParameters() const { + return &_parameters; + } + }; + + class BoundIndexExpression : public BoundExpression { + const BoundExpression *_indexableExpression; + const BoundExpression *_indexExpression; + public: + BoundIndexExpression(BoundExpression *indexableExpression, BoundExpression *indexExpression, + shared_ptr result, + unsigned int start, unsigned int length) + : BoundExpression(start, length, std::move(result)), _indexableExpression(indexableExpression), + _indexExpression(indexExpression) {} + + ~BoundIndexExpression() final { + delete _indexableExpression; + delete _indexExpression; + } + + const BoundExpressionKind GetKind() const final { + return BoundExpressionKind::Index; + } + + const BoundExpression *GetIndexableExpression() const { + return _indexableExpression; + } + + const BoundExpression *GetIndexExpression() const { + return _indexExpression; + } + }; + + class BoundPeriodIndexExpression : public BoundExpression { + const BoundExpression *_indexableExpression; + const Utilities::HashedString _index; + public: + BoundPeriodIndexExpression(BoundExpression *indexableExpression, Utilities::HashedString index, + shared_ptr result, + unsigned int start, unsigned int length) + : BoundExpression(start, length, std::move(result)), _indexableExpression(indexableExpression), + _index(index) {} + + ~BoundPeriodIndexExpression() final { + delete _indexableExpression; + } + + const BoundExpressionKind GetKind() const final { + return BoundExpressionKind::PeriodIndex; + } + + const BoundExpression *GetIndexableExpression() const { + return _indexableExpression; + } + + const Utilities::HashedString GetIndex() const { + return _index; + } + }; + + class BoundNumericalTableExpression : public BoundExpression { + const vector _expressions; + public: + BoundNumericalTableExpression(vector expressions, shared_ptr type, + unsigned int start, unsigned int length) + : BoundExpression(start, length, std::move(type)), + _expressions(std::move(expressions)) {} + + ~BoundNumericalTableExpression() final { + for (auto e: _expressions) { + delete e; + } + } + + const BoundExpressionKind GetKind() const final { + return BoundExpressionKind::NumericalTable; + } + + const vector *GetExpressions() const { + return &_expressions; + } + }; +} #endif //PORYGONLANG_BOUNDEXPRESSION_HPP diff --git a/src/Binder/BoundExpressions/BoundTableExpression.hpp b/src/Binder/BoundExpressions/BoundTableExpression.hpp index c9be54e..c2d65ba 100644 --- a/src/Binder/BoundExpressions/BoundTableExpression.hpp +++ b/src/Binder/BoundExpressions/BoundTableExpression.hpp @@ -6,26 +6,29 @@ #include "../BoundStatements/BoundStatement.hpp" -class BoundTableExpression : public BoundExpression{ - const BoundBlockStatement* _block; -public: - BoundTableExpression(BoundBlockStatement* block, shared_ptr type, unsigned int start, unsigned int length) - : BoundExpression(start, length, std::move(type)){ - _block = block; - } +namespace Porygon::Binder { + class BoundTableExpression : public BoundExpression { + const BoundBlockStatement *_block; + public: + BoundTableExpression(BoundBlockStatement *block, shared_ptr type, unsigned int start, + unsigned int length) + : BoundExpression(start, length, std::move(type)) { + _block = block; + } - ~BoundTableExpression() final{ - delete _block; - } + ~BoundTableExpression() final { + delete _block; + } - const BoundExpressionKind GetKind() const final { - return BoundExpressionKind ::Table; - } + const BoundExpressionKind GetKind() const final { + return BoundExpressionKind::Table; + } - const BoundBlockStatement* GetBlock() const { - return _block; - } -}; + const BoundBlockStatement *GetBlock() const { + return _block; + } + }; +} #include "BoundExpression.hpp" diff --git a/src/Binder/BoundOperators.hpp b/src/Binder/BoundOperators.hpp index b768872..d8251c2 100644 --- a/src/Binder/BoundOperators.hpp +++ b/src/Binder/BoundOperators.hpp @@ -2,26 +2,28 @@ #ifndef PORYGONLANG_BOUNDOPERATORS_HPP #define PORYGONLANG_BOUNDOPERATORS_HPP -enum class BoundBinaryOperation{ - Addition, - Subtraction, - Multiplication, - Division, - Equality, - Inequality, - LessThan, - LessThanEquals, - GreaterThan, - GreaterThanEquals, +namespace Porygon::Binder { + enum class BoundBinaryOperation { + Addition, + Subtraction, + Multiplication, + Division, + Equality, + Inequality, + LessThan, + LessThanEquals, + GreaterThan, + GreaterThanEquals, - LogicalAnd, - LogicalOr, - Concatenation -}; + LogicalAnd, + LogicalOr, + Concatenation + }; -enum class BoundUnaryOperation{ - Negation, - LogicalNegation, -}; + enum class BoundUnaryOperation { + Negation, + LogicalNegation, + }; +} #endif //PORYGONLANG_BOUNDOPERATORS_HPP diff --git a/src/Binder/BoundStatements/BoundFunctionDeclarationStatement.hpp b/src/Binder/BoundStatements/BoundFunctionDeclarationStatement.hpp index 5a019ea..6c2b3a1 100644 --- a/src/Binder/BoundStatements/BoundFunctionDeclarationStatement.hpp +++ b/src/Binder/BoundStatements/BoundFunctionDeclarationStatement.hpp @@ -7,36 +7,38 @@ #include #include "BoundStatement.hpp" -class BoundFunctionDeclarationStatement : public BoundStatement{ - const BoundVariableKey* _key; - const std::shared_ptr _block; - const std::shared_ptr _type; -public: - BoundFunctionDeclarationStatement(std::shared_ptr type, BoundVariableKey* key, BoundBlockStatement* block) - :_key(key), _block(block), _type(std::move(type)) - { - } +namespace Porygon::Binder { + class BoundFunctionDeclarationStatement : public BoundStatement { + const BoundVariableKey *_key; + const std::shared_ptr _block; + const std::shared_ptr _type; + public: + BoundFunctionDeclarationStatement(std::shared_ptr type, BoundVariableKey *key, + BoundBlockStatement *block) + : _key(key), _block(block), _type(std::move(type)) { + } - ~BoundFunctionDeclarationStatement() final{ - delete _key; - } + ~BoundFunctionDeclarationStatement() final { + delete _key; + } - const BoundStatementKind GetKind() const final{ - return BoundStatementKind ::FunctionDeclaration; - } + const BoundStatementKind GetKind() const final { + return BoundStatementKind::FunctionDeclaration; + } - const BoundVariableKey* GetKey() const{ - return _key; - } + const BoundVariableKey *GetKey() const { + return _key; + } - const std::shared_ptr GetBlock() const{ - return _block; - } + const std::shared_ptr GetBlock() const { + return _block; + } - const std::shared_ptr GetType() const{ - return _type; - } -}; + const std::shared_ptr GetType() const { + return _type; + } + }; +} #include "BoundStatement.hpp" diff --git a/src/Binder/BoundStatements/BoundStatement.hpp b/src/Binder/BoundStatements/BoundStatement.hpp index 2fc342f..3594382 100644 --- a/src/Binder/BoundStatements/BoundStatement.hpp +++ b/src/Binder/BoundStatements/BoundStatement.hpp @@ -12,198 +12,197 @@ using namespace std; -enum class BoundStatementKind{ - Bad, - Script, - Block, - Expression, - Assignment, - IndexAssignment, - FunctionDeclaration, - Return, - Conditional, -}; +namespace Porygon::Binder { + enum class BoundStatementKind { + Bad, + Script, + Block, + Expression, + Assignment, + IndexAssignment, + FunctionDeclaration, + Return, + Conditional, + }; -class BoundStatement{ -public: - virtual const BoundStatementKind GetKind() const = 0; - virtual ~BoundStatement() = default; -}; + class BoundStatement { + public: + virtual const BoundStatementKind GetKind() const = 0; -class BoundBadStatement : public BoundStatement{ -public: - const BoundStatementKind GetKind() const final{ - return BoundStatementKind ::Bad; - } -}; + virtual ~BoundStatement() = default; + }; -class BoundBlockStatement : public BoundStatement{ - const vector _statements; -public: - explicit BoundBlockStatement(vector statements) - : _statements(std::move(statements)) - { - } - ~BoundBlockStatement() override { - for (auto s : _statements){ - delete s; + class BoundBadStatement : public BoundStatement { + public: + const BoundStatementKind GetKind() const final { + return BoundStatementKind::Bad; } - } + }; - const BoundStatementKind GetKind() const override { - return BoundStatementKind ::Block; - } + class BoundBlockStatement : public BoundStatement { + const vector _statements; + public: + explicit BoundBlockStatement(vector statements) + : _statements(std::move(statements)) { + } - const vector* GetStatements() const{ - return &_statements; - } -}; + ~BoundBlockStatement() override { + for (auto s : _statements) { + delete s; + } + } -class BoundScriptStatement : public BoundBlockStatement{ - const int _localVariableCount; -public: - explicit BoundScriptStatement(vector statements, int localVariableCount) - : BoundBlockStatement(std::move(statements)), - _localVariableCount(localVariableCount) - { - } + const BoundStatementKind GetKind() const override { + return BoundStatementKind::Block; + } - const BoundStatementKind GetKind() const final{ - return BoundStatementKind ::Script; - } + const vector *GetStatements() const { + return &_statements; + } + }; - const int GetLocalVariableCount() const{ - return _localVariableCount; - } -}; + class BoundScriptStatement : public BoundBlockStatement { + const int _localVariableCount; + public: + explicit BoundScriptStatement(vector statements, int localVariableCount) + : BoundBlockStatement(std::move(statements)), + _localVariableCount(localVariableCount) { + } -class BoundExpressionStatement : public BoundStatement{ - const BoundExpression* _expression; -public: - explicit BoundExpressionStatement(BoundExpression* expression) - : _expression(expression) - { - _expression = expression; - } - ~BoundExpressionStatement() final{ - delete _expression; - } + const BoundStatementKind GetKind() const final { + return BoundStatementKind::Script; + } - const BoundStatementKind GetKind() const final{ - return BoundStatementKind ::Expression; - } + const int GetLocalVariableCount() const { + return _localVariableCount; + } + }; - const BoundExpression* GetExpression() const{ - return _expression; - } -}; + class BoundExpressionStatement : public BoundStatement { + const BoundExpression *_expression; + public: + explicit BoundExpressionStatement(BoundExpression *expression) + : _expression(expression) { + _expression = expression; + } -class BoundAssignmentStatement : public BoundStatement{ - const BoundVariableKey* _key; - const BoundExpression* _expression; -public: - BoundAssignmentStatement(BoundVariableKey* key, BoundExpression* expression) - : _key(key), _expression(expression) - { - } + ~BoundExpressionStatement() final { + delete _expression; + } - ~BoundAssignmentStatement() final{ - delete _key; - delete _expression; - } + const BoundStatementKind GetKind() const final { + return BoundStatementKind::Expression; + } - const BoundStatementKind GetKind() const final{ - return BoundStatementKind ::Assignment; - } + const BoundExpression *GetExpression() const { + return _expression; + } + }; - const BoundVariableKey* GetKey() const { - return _key; - } + class BoundAssignmentStatement : public BoundStatement { + const BoundVariableKey *_key; + const BoundExpression *_expression; + public: + BoundAssignmentStatement(BoundVariableKey *key, BoundExpression *expression) + : _key(key), _expression(expression) { + } - const BoundExpression* GetExpression() const { - return _expression; - } -}; + ~BoundAssignmentStatement() final { + delete _key; + delete _expression; + } -class BoundIndexAssignmentStatement : public BoundStatement{ - const BoundExpression* _indexExpression; - const BoundExpression* _valueExpression; -public: - BoundIndexAssignmentStatement(const BoundExpression* index, BoundExpression* value) - : _indexExpression(index), _valueExpression(value) - { - } + const BoundStatementKind GetKind() const final { + return BoundStatementKind::Assignment; + } - ~BoundIndexAssignmentStatement() final{ - delete _indexExpression; - delete _valueExpression; - } + const BoundVariableKey *GetKey() const { + return _key; + } - const BoundStatementKind GetKind() const final{ - return BoundStatementKind ::IndexAssignment; - } + const BoundExpression *GetExpression() const { + return _expression; + } + }; - const BoundExpression* GetIndexExpression() const { - return _indexExpression; - } + class BoundIndexAssignmentStatement : public BoundStatement { + const BoundExpression *_indexExpression; + const BoundExpression *_valueExpression; + public: + BoundIndexAssignmentStatement(const BoundExpression *index, BoundExpression *value) + : _indexExpression(index), _valueExpression(value) { + } - const BoundExpression* GetValueExpression() const { - return _valueExpression; - } -}; + ~BoundIndexAssignmentStatement() final { + delete _indexExpression; + delete _valueExpression; + } -class BoundReturnStatement : public BoundStatement{ - const BoundExpression* _expression; -public: - explicit BoundReturnStatement(BoundExpression* expression) - : _expression(expression) - { - } - ~BoundReturnStatement() final{ - delete _expression; - } + const BoundStatementKind GetKind() const final { + return BoundStatementKind::IndexAssignment; + } - const BoundStatementKind GetKind() const final{ - return BoundStatementKind ::Return; - } + const BoundExpression *GetIndexExpression() const { + return _indexExpression; + } - const BoundExpression* GetExpression() const{ - return _expression; - } -}; + const BoundExpression *GetValueExpression() const { + return _valueExpression; + } + }; -class BoundConditionalStatement : public BoundStatement{ - const BoundExpression* _condition; - const BoundStatement* _block; - const BoundStatement* _elseStatement; -public: - explicit BoundConditionalStatement(BoundExpression* condition, BoundStatement* block, BoundStatement* next) - :_condition(condition), _block(block), _elseStatement(next) - { - } + class BoundReturnStatement : public BoundStatement { + const BoundExpression *_expression; + public: + explicit BoundReturnStatement(BoundExpression *expression) + : _expression(expression) { + } - ~BoundConditionalStatement() final{ - delete _condition; - delete _block; - delete _elseStatement; - } + ~BoundReturnStatement() final { + delete _expression; + } - const BoundStatementKind GetKind() const final{ - return BoundStatementKind ::Conditional; - } + const BoundStatementKind GetKind() const final { + return BoundStatementKind::Return; + } - const BoundExpression* GetCondition() const{ - return _condition; - } + const BoundExpression *GetExpression() const { + return _expression; + } + }; - const BoundStatement* GetBlock() const{ - return _block; - } + class BoundConditionalStatement : public BoundStatement { + const BoundExpression *_condition; + const BoundStatement *_block; + const BoundStatement *_elseStatement; + public: + explicit BoundConditionalStatement(BoundExpression *condition, BoundStatement *block, BoundStatement *next) + : _condition(condition), _block(block), _elseStatement(next) { + } - const BoundStatement* GetElseStatement() const{ - return _elseStatement; - } -}; + ~BoundConditionalStatement() final { + delete _condition; + delete _block; + delete _elseStatement; + } + + const BoundStatementKind GetKind() const final { + return BoundStatementKind::Conditional; + } + + const BoundExpression *GetCondition() const { + return _condition; + } + + const BoundStatement *GetBlock() const { + return _block; + } + + const BoundStatement *GetElseStatement() const { + return _elseStatement; + } + }; +} #include "BoundFunctionDeclarationStatement.hpp" diff --git a/src/Binder/BoundVariables/BoundScope.cpp b/src/Binder/BoundVariables/BoundScope.cpp index 1c7b334..0aad208 100644 --- a/src/Binder/BoundVariables/BoundScope.cpp +++ b/src/Binder/BoundVariables/BoundScope.cpp @@ -3,95 +3,98 @@ #include "BoundScope.hpp" -BoundScope::BoundScope(unordered_map *tableScope) { - _tableScope = tableScope; - _currentScope = 1; - _lastCreatedScope = 1; - auto localUpmostScope = new unordered_map(); - _localScope.push_back(localUpmostScope); -} +namespace Porygon::Binder { + BoundScope::BoundScope(unordered_map *tableScope) { + _tableScope = tableScope; + _currentScope = 1; + _lastCreatedScope = 1; + auto localUpmostScope = new unordered_map(); + _localScope.push_back(localUpmostScope); + } -BoundScope::~BoundScope() { - for (auto scope : _localScope){ - for (auto v : *scope){ + BoundScope::~BoundScope() { + for (auto scope : _localScope) { + for (auto v : *scope) { + delete v.second; + } + delete scope; + } + } + + void BoundScope::GoInnerScope() { + _lastCreatedScope++; + _currentScope = _lastCreatedScope; + if (_localScope.size() < _currentScope) { + auto innerScope = new unordered_map(); + _localScope.push_back(innerScope); + } + } + + void BoundScope::GoOuterScope() { + auto scope = _localScope[_currentScope - 1]; + for (auto v : *scope) { delete v.second; } - delete scope; + scope->clear(); + _currentScope--; } -} -void BoundScope::GoInnerScope() { - _lastCreatedScope++; - _currentScope = _lastCreatedScope; - if (_localScope.size() < _currentScope){ - auto innerScope = new unordered_map(); - _localScope.push_back(innerScope); + int BoundScope::Exists(int key) { + auto found = this->_tableScope->find(key); + if (found != _tableScope->end()) { + return 0; + } + for (int i = _currentScope - 1; i >= 0; i--) { + auto scope = _localScope.at(i); + found = scope->find(key); + if (found != scope->end()) { + return i + 1; + } + } + return -1; } -} -void BoundScope::GoOuterScope() { - auto scope = _localScope[_currentScope - 1]; - for (auto v : *scope){ - delete v.second; - } - scope->clear(); - _currentScope--; -} - -int BoundScope::Exists(int key) { - auto found = this -> _tableScope -> find(key); - if (found != _tableScope -> end()){ - return 0; - } - for (int i = _currentScope - 1; i >= 0; i--){ - auto scope = _localScope.at(i); - found = scope -> find(key); - if (found != scope -> end()){ - return i + 1; + BoundVariable *BoundScope::GetVariable(uint32_t scope, uint32_t identifier) { + if (scope == 0) { + auto find = this->_tableScope->find(identifier); + if (find != _tableScope->end()) { + return find->second; + } + return nullptr; + } else { + auto s = this->_localScope.at(scope - 1); + auto find = s->find(identifier); + if (find != s->end()) { + return find->second; + } + return nullptr; } } - return -1; -} -BoundVariable *BoundScope::GetVariable(uint32_t scope, uint32_t identifier) { - if (scope == 0){ - auto find = this -> _tableScope->find(identifier); - if (find != _tableScope->end()){ - return find -> second; + VariableAssignment BoundScope::CreateExplicitLocal(uint32_t identifier, std::shared_ptr type) { + auto scope = this->_localScope.at(this->_currentScope - 1); + if (scope->find(identifier) != scope->end()) { + return VariableAssignment(VariableAssignmentResult::ExplicitLocalVariableExists, nullptr); } - return nullptr; - } else{ - auto s = this->_localScope.at(scope - 1); - auto find = s -> find(identifier); - if (find != s -> end()){ - return find -> second; - } - return nullptr; + scope->insert({identifier, new BoundVariable(std::move(type))}); + return VariableAssignment(VariableAssignmentResult::Ok, + new BoundVariableKey(identifier, this->_currentScope, true)); } -} -VariableAssignment BoundScope::CreateExplicitLocal(uint32_t identifier, std::shared_ptr type) { - auto scope = this->_localScope.at(this->_currentScope - 1); - if (scope -> find(identifier) != scope -> end()){ - return VariableAssignment(VariableAssignmentResult::ExplicitLocalVariableExists, nullptr); - } - scope -> insert({identifier, new BoundVariable(std::move(type))}); - return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, this->_currentScope, true)); -} - -VariableAssignment BoundScope::AssignVariable(uint32_t identifier, const std::shared_ptr& type) { - int exists = this->Exists(identifier); - if (exists == -1){ - // Creation - _tableScope->insert({identifier, new BoundVariable(type)}); - return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, 0, true)); - } else{ - // Assigning - auto var = this->GetVariable(exists, identifier); - if (var->GetType().get()->operator!=(type.get())){ - return VariableAssignment(VariableAssignmentResult::VariableDefinedWithDifferentType, nullptr); + VariableAssignment BoundScope::AssignVariable(uint32_t identifier, const std::shared_ptr &type) { + int exists = this->Exists(identifier); + if (exists == -1) { + // Creation + _tableScope->insert({identifier, new BoundVariable(type)}); + return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, 0, true)); + } else { + // Assigning + auto var = this->GetVariable(exists, identifier); + if (var->GetType().get()->operator!=(type.get())) { + return VariableAssignment(VariableAssignmentResult::VariableDefinedWithDifferentType, nullptr); + } + return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, exists, false)); } - return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, exists, false)); } } diff --git a/src/Binder/BoundVariables/BoundScope.hpp b/src/Binder/BoundVariables/BoundScope.hpp index da19c1f..6fe602f 100644 --- a/src/Binder/BoundVariables/BoundScope.hpp +++ b/src/Binder/BoundVariables/BoundScope.hpp @@ -13,31 +13,38 @@ using namespace std; -class BoundScope { - unordered_map* _tableScope; - vector*> _localScope; - int _currentScope; - int _lastCreatedScope; -public: - explicit BoundScope(unordered_map *tableScope); - ~BoundScope(); +namespace Porygon::Binder { + class BoundScope { + unordered_map *_tableScope; + vector *> _localScope; + int _currentScope; + int _lastCreatedScope; + public: + explicit BoundScope(unordered_map *tableScope); - void GoInnerScope(); - void GoOuterScope(); + ~BoundScope(); - int Exists(int key); - BoundVariable* GetVariable(uint32_t scope, uint32_t identifier); - VariableAssignment CreateExplicitLocal(uint32_t identifier, std::shared_ptr type); - VariableAssignment AssignVariable(uint32_t identifier, const std::shared_ptr& type); + void GoInnerScope(); - size_t GetLocalVariableCount(){ - return _localScope.size(); - } + void GoOuterScope(); - int GetCurrentScope(){ - return _currentScope; - } -}; + int Exists(int key); + + BoundVariable *GetVariable(uint32_t scope, uint32_t identifier); + + VariableAssignment CreateExplicitLocal(uint32_t identifier, std::shared_ptr type); + + VariableAssignment AssignVariable(uint32_t identifier, const std::shared_ptr &type); + + size_t GetLocalVariableCount() { + return _localScope.size(); + } + + int GetCurrentScope() { + return _currentScope; + } + }; +} #endif //PORYGONLANG_BOUNDSCOPE_HPP diff --git a/src/Binder/BoundVariables/BoundVariable.hpp b/src/Binder/BoundVariables/BoundVariable.hpp index ea44c93..d6e8e5e 100644 --- a/src/Binder/BoundVariables/BoundVariable.hpp +++ b/src/Binder/BoundVariables/BoundVariable.hpp @@ -9,15 +9,17 @@ using namespace std; -class BoundVariable{ - std::shared_ptr _type; -public: - explicit BoundVariable(std::shared_ptr type) : _type(std::move(type)){ - } +namespace Porygon::Binder { + class BoundVariable { + std::shared_ptr _type; + public: + explicit BoundVariable(std::shared_ptr type) : _type(std::move(type)) { + } - std::shared_ptr GetType(){ - return _type; - } -}; + std::shared_ptr GetType() { + return _type; + } + }; +} #endif //PORYGONLANG_BOUNDVARIABLE_HPP diff --git a/src/Binder/BoundVariables/BoundVariableKey.hpp b/src/Binder/BoundVariables/BoundVariableKey.hpp index ba0e1d2..bd84c53 100644 --- a/src/Binder/BoundVariables/BoundVariableKey.hpp +++ b/src/Binder/BoundVariables/BoundVariableKey.hpp @@ -4,42 +4,43 @@ #include -class BoundVariableKey{ - const int _identifier; - const unsigned int _scopeId; - const bool _isCreation; - const uint64_t _hash; +namespace Porygon::Binder { + class BoundVariableKey { + const int _identifier; + const unsigned int _scopeId; + const bool _isCreation; + const uint64_t _hash; - static uint64_t KnuthsHash(unsigned int i1, unsigned int i2) - { - uint64_t ret = i1; - ret *= 2654435761U; - return ret ^ i2; - } -public: - BoundVariableKey(int id, unsigned int scope, bool creation) - : _identifier(id), - _scopeId(scope), - _isCreation(creation), - _hash(KnuthsHash(id, scope)) - {} + static uint64_t KnuthsHash(unsigned int i1, unsigned int i2) { + uint64_t ret = i1; + ret *= 2654435761U; + return ret ^ i2; + } + + public: + BoundVariableKey(int id, unsigned int scope, bool creation) + : _identifier(id), + _scopeId(scope), + _isCreation(creation), + _hash(KnuthsHash(id, scope)) {} - const int GetIdentifier() const{ - return _identifier; - } + const int GetIdentifier() const { + return _identifier; + } - const unsigned int GetScopeId() const{ - return _scopeId; - } + const unsigned int GetScopeId() const { + return _scopeId; + } - const bool IsCreation() const{ - return _isCreation; - } + const bool IsCreation() const { + return _isCreation; + } - const uint64_t GetHash() const{ - return _hash; - } -}; + const uint64_t GetHash() const { + return _hash; + } + }; +} #endif //PORYGONLANG_BOUNDVARIABLEKEY_HPP diff --git a/src/Binder/BoundVariables/VariableAssigmentResult.hpp b/src/Binder/BoundVariables/VariableAssigmentResult.hpp index 7e449df..2fbcfae 100644 --- a/src/Binder/BoundVariables/VariableAssigmentResult.hpp +++ b/src/Binder/BoundVariables/VariableAssigmentResult.hpp @@ -4,28 +4,30 @@ #include "BoundVariableKey.hpp" -enum class VariableAssignmentResult{ - Ok, - ExplicitLocalVariableExists, - VariableDefinedWithDifferentType -}; +namespace Porygon::Binder { + enum class VariableAssignmentResult { + Ok, + ExplicitLocalVariableExists, + VariableDefinedWithDifferentType + }; -class VariableAssignment{ - VariableAssignmentResult _result; - BoundVariableKey* _key; -public: - VariableAssignment(VariableAssignmentResult result, BoundVariableKey *key) { - _result = result; - _key = key; - } + class VariableAssignment { + VariableAssignmentResult _result; + BoundVariableKey *_key; + public: + VariableAssignment(VariableAssignmentResult result, BoundVariableKey *key) { + _result = result; + _key = key; + } - VariableAssignmentResult GetResult(){ - return _result; - } + VariableAssignmentResult GetResult() { + return _result; + } - BoundVariableKey* GetKey(){ - return _key; - } -}; + BoundVariableKey *GetKey() { + return _key; + } + }; +} #endif //PORYGONLANG_VARIABLEASSIGMENTRESULT_HPP diff --git a/src/Evaluator/BinaryEvaluation.cpp b/src/Evaluator/BinaryEvaluation.cpp index 6de1fd5..80210b4 100644 --- a/src/Evaluator/BinaryEvaluation.cpp +++ b/src/Evaluator/BinaryEvaluation.cpp @@ -5,91 +5,87 @@ #include "EvalValues/NumericEvalValue.hpp" #include "EvalValues/StringEvalValue.hpp" -const shared_ptr Evaluator::EvaluateIntegerBinary(const BoundBinaryExpression *expression) { - auto leftValue = this -> EvaluateIntegerExpression(expression->GetLeft()); - auto rightValue = this -> EvaluateIntegerExpression(expression->GetRight()); +using namespace Porygon::Binder; - switch (expression->GetOperation()){ - case BoundBinaryOperation ::Addition: - return leftValue.get() -> operator+ (rightValue); - case BoundBinaryOperation::Subtraction: - return leftValue.get() -> operator- (rightValue); - case BoundBinaryOperation::Multiplication: - return leftValue.get() -> operator* (rightValue); - case BoundBinaryOperation::Division: - return leftValue.get() -> operator/ (rightValue); - default: - throw EvaluationException("Can't evaluate operation to numeric"); +namespace Porygon::Evaluation { + const shared_ptr Evaluator::EvaluateIntegerBinary(const BoundBinaryExpression *expression) { + auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft()); + auto rightValue = this->EvaluateIntegerExpression(expression->GetRight()); + + switch (expression->GetOperation()) { + case BoundBinaryOperation::Addition: + return leftValue.get()->operator+(rightValue); + case BoundBinaryOperation::Subtraction: + return leftValue.get()->operator-(rightValue); + case BoundBinaryOperation::Multiplication: + return leftValue.get()->operator*(rightValue); + case BoundBinaryOperation::Division: + return leftValue.get()->operator/(rightValue); + default: + throw EvaluationException("Can't evaluate operation to numeric"); + } } -} -const shared_ptr Evaluator::EvaluateBooleanBinary(const BoundBinaryExpression *expression){ - switch (expression->GetOperation()){ - case BoundBinaryOperation::Equality: - { - auto leftValue = this -> EvaluateExpression(expression->GetLeft()); - auto rightValue = this -> EvaluateExpression(expression->GetRight()); - bool equals = leftValue.get()->operator==(rightValue.get()); - return make_shared(equals); - } - case BoundBinaryOperation::Inequality: - { - auto leftValue = this -> EvaluateExpression(expression->GetLeft()); - auto rightValue = this -> EvaluateExpression(expression->GetRight()); - bool equals = leftValue.get()->operator!=(rightValue.get()); - return make_shared(equals); - } - case BoundBinaryOperation ::LessThan: - { - auto leftValue = this -> EvaluateIntegerExpression(expression->GetLeft()); - auto rightValue = this -> EvaluateIntegerExpression(expression->GetRight()); - return leftValue->operator<(rightValue); - } - case BoundBinaryOperation ::LessThanEquals: - { - auto leftValue = this -> EvaluateIntegerExpression(expression->GetLeft()); - auto rightValue = this -> EvaluateIntegerExpression(expression->GetRight()); - return leftValue->operator<=(rightValue); - } - case BoundBinaryOperation ::GreaterThan: - { - auto leftValue = this -> EvaluateIntegerExpression(expression->GetLeft()); - auto rightValue = this -> EvaluateIntegerExpression(expression->GetRight()); - return leftValue->operator>(rightValue); - } - case BoundBinaryOperation ::GreaterThanEquals: - { - auto leftValue = this -> EvaluateIntegerExpression(expression->GetLeft()); - auto rightValue = this -> EvaluateIntegerExpression(expression->GetRight()); - return leftValue->operator>=(rightValue); - } + const shared_ptr Evaluator::EvaluateBooleanBinary(const BoundBinaryExpression *expression) { + switch (expression->GetOperation()) { + case BoundBinaryOperation::Equality: { + auto leftValue = this->EvaluateExpression(expression->GetLeft()); + auto rightValue = this->EvaluateExpression(expression->GetRight()); + bool equals = leftValue.get()->operator==(rightValue.get()); + return make_shared(equals); + } + case BoundBinaryOperation::Inequality: { + auto leftValue = this->EvaluateExpression(expression->GetLeft()); + auto rightValue = this->EvaluateExpression(expression->GetRight()); + bool equals = leftValue.get()->operator!=(rightValue.get()); + return make_shared(equals); + } + case BoundBinaryOperation::LessThan: { + auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft()); + auto rightValue = this->EvaluateIntegerExpression(expression->GetRight()); + return leftValue->operator<(rightValue); + } + case BoundBinaryOperation::LessThanEquals: { + auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft()); + auto rightValue = this->EvaluateIntegerExpression(expression->GetRight()); + return leftValue->operator<=(rightValue); + } + case BoundBinaryOperation::GreaterThan: { + auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft()); + auto rightValue = this->EvaluateIntegerExpression(expression->GetRight()); + return leftValue->operator>(rightValue); + } + case BoundBinaryOperation::GreaterThanEquals: { + auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft()); + auto rightValue = this->EvaluateIntegerExpression(expression->GetRight()); + return leftValue->operator>=(rightValue); + } - case BoundBinaryOperation::LogicalAnd: - { - auto leftValue = this -> EvaluateBoolExpression(expression->GetLeft()); - if (!leftValue->EvaluateBool()) return leftValue; - auto rightValue = this -> EvaluateBoolExpression(expression->GetRight()); - return rightValue; + case BoundBinaryOperation::LogicalAnd: { + auto leftValue = this->EvaluateBoolExpression(expression->GetLeft()); + if (!leftValue->EvaluateBool()) return leftValue; + auto rightValue = this->EvaluateBoolExpression(expression->GetRight()); + return rightValue; + } + case BoundBinaryOperation::LogicalOr: { + auto leftValue = this->EvaluateBoolExpression(expression->GetLeft()); + if (leftValue->EvaluateBool()) return leftValue; + auto rightValue = this->EvaluateBoolExpression(expression->GetRight()); + return rightValue; + } + default: + throw EvaluationException("Can't evaluate operation to boolean"); } - case BoundBinaryOperation::LogicalOr: - { - auto leftValue = this -> EvaluateBoolExpression(expression->GetLeft()); - if (leftValue->EvaluateBool()) return leftValue; - auto rightValue = this -> EvaluateBoolExpression(expression->GetRight()); - return rightValue; - } - default: - throw EvaluationException("Can't evaluate operation to boolean"); } -} -const shared_ptr Evaluator::EvaluateStringBinary(const BoundBinaryExpression *expression){ - if (expression->GetOperation() != BoundBinaryOperation::Concatenation) - throw; - std::basic_ostringstream stringStream; - auto left = this -> EvaluateStringExpression(expression->GetLeft()); - stringStream << *left->EvaluateString(); - auto right = this -> EvaluateExpression(expression->GetRight()); - stringStream << *right->EvaluateString(); - return make_shared(stringStream.str()); + const shared_ptr Evaluator::EvaluateStringBinary(const BoundBinaryExpression *expression) { + if (expression->GetOperation() != BoundBinaryOperation::Concatenation) + throw; + std::basic_ostringstream stringStream; + auto left = this->EvaluateStringExpression(expression->GetLeft()); + stringStream << *left->EvaluateString(); + auto right = this->EvaluateExpression(expression->GetRight()); + stringStream << *right->EvaluateString(); + return make_shared(stringStream.str()); + } } \ No newline at end of file diff --git a/src/Evaluator/EvalValues/EvalValue.cpp b/src/Evaluator/EvalValues/EvalValue.cpp index 2b78cdc..d26b34b 100644 --- a/src/Evaluator/EvalValues/EvalValue.cpp +++ b/src/Evaluator/EvalValues/EvalValue.cpp @@ -3,42 +3,45 @@ #include "StringEvalValue.hpp" #include -extern "C" { - TypeClass GetEvalValueTypeClass(EvalValue* v){ +namespace Porygon::Evaluation { + + extern "C" { + Porygon::TypeClass GetEvalValueTypeClass(EvalValue *v) { return v->GetTypeClass(); } - int64_t EvaluateEvalValueInteger(EvalValue* v){ + int64_t EvaluateEvalValueInteger(EvalValue *v) { return v->EvaluateInteger(); } - double EvaluateEvalValueFloat(EvalValue* v){ + double EvaluateEvalValueFloat(EvalValue *v) { return v->EvaluateFloat(); } - bool EvaluateEvalValueBool(EvalValue* v){ + bool EvaluateEvalValueBool(EvalValue *v) { return v->EvaluateBool(); } - const char16_t * EvaluateEvalValueString(EvalValue* v){ - return v->EvaluateString() -> c_str(); + const char16_t *EvaluateEvalValueString(EvalValue *v) { + return v->EvaluateString()->c_str(); } - EvalValue* CreateIntegerEvalValue(long l){ + EvalValue *CreateIntegerEvalValue(long l) { return new IntegerEvalValue(l); } - EvalValue* CreateFloatEvalValue(double d){ + EvalValue *CreateFloatEvalValue(double d) { return new FloatEvalValue(d); } - EvalValue* CreateBoolEvalValue(bool b){ + EvalValue *CreateBoolEvalValue(bool b) { return new BooleanEvalValue(b); } - EvalValue* CreateStringEvalValue(const char16_t * s){ + EvalValue *CreateStringEvalValue(const char16_t *s) { return new StringEvalValue(s); } + } } #ifdef TESTS_BUILD @@ -47,7 +50,7 @@ extern "C" { TEST_CASE( "Evaluate String", "[integration]" ) { - auto script = Script::Create(u"\"foo bar\""); + auto script = Porygon::Script::Create(u"\"foo bar\""); REQUIRE(!script->Diagnostics -> HasErrors()); script->Evaluate(); auto lastValue = script->GetLastValue(); diff --git a/src/Evaluator/EvalValues/EvalValue.hpp b/src/Evaluator/EvalValues/EvalValue.hpp index 7867588..745d78a 100644 --- a/src/Evaluator/EvalValues/EvalValue.hpp +++ b/src/Evaluator/EvalValues/EvalValue.hpp @@ -8,77 +8,83 @@ #include #include -class EvalValue{ -public: - EvalValue() = default; - virtual ~EvalValue() = default; - virtual const TypeClass GetTypeClass() const = 0; +namespace Porygon::Evaluation { + class EvalValue { + public: + EvalValue() = default; - virtual const bool operator ==(EvalValue* b) const = 0; + virtual ~EvalValue() = default; - virtual const bool operator !=(EvalValue*b) const{ - return ! (this->operator==(b)); - } + virtual const TypeClass GetTypeClass() const = 0; - virtual const shared_ptr Clone() const = 0; + virtual const bool operator==(EvalValue *b) const = 0; - virtual const long EvaluateInteger() const{ - throw EvaluationException("Can't evaluate this EvalValue as integer."); - } - virtual const double EvaluateFloat() const{ - throw EvaluationException("Can't evaluate this EvalValue as float."); - } - virtual const bool EvaluateBool() const{ - throw EvaluationException("Can't evaluate this EvalValue as bool."); - } - virtual const std::u16string* EvaluateString() const { - throw EvaluationException("Can't evaluate this EvalValue as string."); - } + virtual const bool operator!=(EvalValue *b) const { + return !(this->operator==(b)); + } - virtual const std::size_t GetHashCode() const = 0; + virtual const shared_ptr Clone() const = 0; - virtual const shared_ptr IndexValue(EvalValue* val) const{ - throw EvaluationException("Can't index this EvalValue"); - } + virtual const long EvaluateInteger() const { + throw EvaluationException("Can't evaluate this EvalValue as integer."); + } - virtual const shared_ptr IndexValue(uint32_t hash) const{ - throw EvaluationException("Can't index this EvalValue"); - } + virtual const double EvaluateFloat() const { + throw EvaluationException("Can't evaluate this EvalValue as float."); + } - virtual void SetIndexValue(EvalValue *key, const shared_ptr& value) const{ - throw EvaluationException("Can't index this EvalValue"); - } -}; + virtual const bool EvaluateBool() const { + throw EvaluationException("Can't evaluate this EvalValue as bool."); + } -class BooleanEvalValue : public EvalValue{ - const bool _value; -public: - explicit BooleanEvalValue(bool val) - : _value(val) - { - } + virtual const std::u16string *EvaluateString() const { + throw EvaluationException("Can't evaluate this EvalValue as string."); + } - const shared_ptr Clone() const final{ - return make_shared(_value); - } + virtual const std::size_t GetHashCode() const = 0; - const TypeClass GetTypeClass() const final{ - return TypeClass ::Bool; - } + virtual const shared_ptr IndexValue(EvalValue *val) const { + throw EvaluationException("Can't index this EvalValue"); + } - const bool EvaluateBool() const final{ - return _value; - } + virtual const shared_ptr IndexValue(uint32_t hash) const { + throw EvaluationException("Can't index this EvalValue"); + } - const bool operator ==(EvalValue* b) const final{ - if (b->GetTypeClass() != TypeClass::Bool) - return false; - return this->EvaluateBool() == b->EvaluateBool(); + virtual void SetIndexValue(EvalValue *key, const shared_ptr &value) const { + throw EvaluationException("Can't index this EvalValue"); + } }; - const std::size_t GetHashCode() const final{ - return _value; - } -}; + class BooleanEvalValue : public EvalValue { + const bool _value; + public: + explicit BooleanEvalValue(bool val) + : _value(val) { + } + + const shared_ptr Clone() const final { + return make_shared(_value); + } + + const TypeClass GetTypeClass() const final { + return TypeClass::Bool; + } + + const bool EvaluateBool() const final { + return _value; + } + + const bool operator==(EvalValue *b) const final { + if (b->GetTypeClass() != TypeClass::Bool) + return false; + return this->EvaluateBool() == b->EvaluateBool(); + }; + + const std::size_t GetHashCode() const final { + return _value; + } + }; +} #endif //PORYGONLANG_EVALVALUE_HPP diff --git a/src/Evaluator/EvalValues/NumericEvalValue.cpp b/src/Evaluator/EvalValues/NumericEvalValue.cpp index 65ff6e9..e2e4c4a 100644 --- a/src/Evaluator/EvalValues/NumericEvalValue.cpp +++ b/src/Evaluator/EvalValues/NumericEvalValue.cpp @@ -1,144 +1,146 @@ #include "NumericEvalValue.hpp" -const shared_ptr NumericEvalValue::operator+(const shared_ptr& b) const { - if (this->IsFloat()){ - if (b->IsFloat()){ - return make_shared(this->GetFloatValue() + b->GetFloatValue()); - } else{ - return make_shared(this->GetFloatValue() + b->GetIntegerValue()); - } - } else { - if (b->IsFloat()){ - return make_shared(this->GetIntegerValue() + b->GetFloatValue()); - } else{ - return make_shared(this->GetIntegerValue() + b->GetIntegerValue()); +namespace Porygon::Evaluation { + const shared_ptr NumericEvalValue::operator+(const shared_ptr &b) const { + if (this->IsFloat()) { + if (b->IsFloat()) { + return make_shared(this->GetFloatValue() + b->GetFloatValue()); + } else { + return make_shared(this->GetFloatValue() + b->GetIntegerValue()); + } + } else { + if (b->IsFloat()) { + return make_shared(this->GetIntegerValue() + b->GetFloatValue()); + } else { + return make_shared(this->GetIntegerValue() + b->GetIntegerValue()); + } } } -} -const shared_ptr NumericEvalValue::operator-(const shared_ptr& b) const { - if (this->IsFloat()){ - if (b->IsFloat()){ - return make_shared(this->GetFloatValue() - b->GetFloatValue()); - } else{ - return make_shared(this->GetFloatValue() - b->GetIntegerValue()); - } - } else { - if (b->IsFloat()){ - return make_shared(this->GetIntegerValue() - b->GetFloatValue()); - } else{ - return make_shared(this->GetIntegerValue() - b->GetIntegerValue()); + const shared_ptr NumericEvalValue::operator-(const shared_ptr &b) const { + if (this->IsFloat()) { + if (b->IsFloat()) { + return make_shared(this->GetFloatValue() - b->GetFloatValue()); + } else { + return make_shared(this->GetFloatValue() - b->GetIntegerValue()); + } + } else { + if (b->IsFloat()) { + return make_shared(this->GetIntegerValue() - b->GetFloatValue()); + } else { + return make_shared(this->GetIntegerValue() - b->GetIntegerValue()); + } } } -} -const shared_ptr NumericEvalValue::operator*(const shared_ptr& b) const { - if (this->IsFloat()){ - if (b->IsFloat()){ - return make_shared(this->GetFloatValue() * b->GetFloatValue()); - } else{ - return make_shared(this->GetFloatValue() * b->GetIntegerValue()); - } - } else { - if (b->IsFloat()){ - return make_shared(this->GetIntegerValue() * b->GetFloatValue()); - } else{ - return make_shared(this->GetIntegerValue() * b->GetIntegerValue()); + const shared_ptr NumericEvalValue::operator*(const shared_ptr &b) const { + if (this->IsFloat()) { + if (b->IsFloat()) { + return make_shared(this->GetFloatValue() * b->GetFloatValue()); + } else { + return make_shared(this->GetFloatValue() * b->GetIntegerValue()); + } + } else { + if (b->IsFloat()) { + return make_shared(this->GetIntegerValue() * b->GetFloatValue()); + } else { + return make_shared(this->GetIntegerValue() * b->GetIntegerValue()); + } } } -} -const shared_ptr NumericEvalValue::operator/(const shared_ptr& b) const { - if (this->IsFloat()){ - if (b->IsFloat()){ - return make_shared(this->GetFloatValue() / b->GetFloatValue()); - } else{ - return make_shared(this->GetFloatValue() / b->GetIntegerValue()); - } - } else { - if (b->IsFloat()){ - return make_shared(this->GetIntegerValue() / b->GetFloatValue()); - } else{ - return make_shared(this->GetIntegerValue() / b->GetIntegerValue()); + const shared_ptr NumericEvalValue::operator/(const shared_ptr &b) const { + if (this->IsFloat()) { + if (b->IsFloat()) { + return make_shared(this->GetFloatValue() / b->GetFloatValue()); + } else { + return make_shared(this->GetFloatValue() / b->GetIntegerValue()); + } + } else { + if (b->IsFloat()) { + return make_shared(this->GetIntegerValue() / b->GetFloatValue()); + } else { + return make_shared(this->GetIntegerValue() / b->GetIntegerValue()); + } } } -} -const bool NumericEvalValue::operator==(EvalValue *b) const { - if (b->GetTypeClass() != TypeClass::Number) - return false; - auto numVal = (NumericEvalValue*)b; - if (this->IsFloat() != numVal->IsFloat()) - return false; + const bool NumericEvalValue::operator==(EvalValue *b) const { + if (b->GetTypeClass() != TypeClass::Number) + return false; + auto numVal = (NumericEvalValue *) b; + if (this->IsFloat() != numVal->IsFloat()) + return false; - if (this->IsFloat()){ - return this->EvaluateFloat() == numVal->EvaluateFloat(); - } else{ - return this->EvaluateInteger() == numVal->EvaluateInteger(); - } -} - -const shared_ptr NumericEvalValue::operator<(const shared_ptr& b) const { - if (this->IsFloat()){ - if (b->IsFloat()){ - return make_shared(this->GetFloatValue() < b->GetFloatValue()); - } else{ - return make_shared(this->GetFloatValue() < b->GetIntegerValue()); - } - } else { - if (b->IsFloat()){ - return make_shared(this->GetIntegerValue() < b->GetFloatValue()); - } else{ - return make_shared(this->GetIntegerValue() < b->GetIntegerValue()); + if (this->IsFloat()) { + return this->EvaluateFloat() == numVal->EvaluateFloat(); + } else { + return this->EvaluateInteger() == numVal->EvaluateInteger(); } } -} -const shared_ptr NumericEvalValue::operator<=(const shared_ptr& b) const { - if (this->IsFloat()){ - if (b->IsFloat()){ - return make_shared(this->GetFloatValue() <= b->GetFloatValue()); - } else{ - return make_shared(this->GetFloatValue() <= b->GetIntegerValue()); - } - } else { - if (b->IsFloat()){ - return make_shared(this->GetIntegerValue() <= b->GetFloatValue()); - } else{ - return make_shared(this->GetIntegerValue() <= b->GetIntegerValue()); + const shared_ptr NumericEvalValue::operator<(const shared_ptr &b) const { + if (this->IsFloat()) { + if (b->IsFloat()) { + return make_shared(this->GetFloatValue() < b->GetFloatValue()); + } else { + return make_shared(this->GetFloatValue() < b->GetIntegerValue()); + } + } else { + if (b->IsFloat()) { + return make_shared(this->GetIntegerValue() < b->GetFloatValue()); + } else { + return make_shared(this->GetIntegerValue() < b->GetIntegerValue()); + } } } -} -const shared_ptr NumericEvalValue::operator>(const shared_ptr& b) const { - if (this->IsFloat()){ - if (b->IsFloat()){ - return make_shared(this->GetFloatValue() > b->GetFloatValue()); - } else{ - return make_shared(this->GetFloatValue() > b->GetIntegerValue()); - } - } else { - if (b->IsFloat()){ - return make_shared(this->GetIntegerValue() > b->GetFloatValue()); - } else{ - return make_shared(this->GetIntegerValue() > b->GetIntegerValue()); + const shared_ptr NumericEvalValue::operator<=(const shared_ptr &b) const { + if (this->IsFloat()) { + if (b->IsFloat()) { + return make_shared(this->GetFloatValue() <= b->GetFloatValue()); + } else { + return make_shared(this->GetFloatValue() <= b->GetIntegerValue()); + } + } else { + if (b->IsFloat()) { + return make_shared(this->GetIntegerValue() <= b->GetFloatValue()); + } else { + return make_shared(this->GetIntegerValue() <= b->GetIntegerValue()); + } } } -} -const shared_ptr NumericEvalValue::operator>=(const shared_ptr& b) const { - if (this->IsFloat()){ - if (b->IsFloat()){ - return make_shared(this->GetFloatValue() >= b->GetFloatValue()); - } else{ - return make_shared(this->GetFloatValue() >= b->GetIntegerValue()); - } - } else { - if (b->IsFloat()){ - return make_shared(this->GetIntegerValue() >= b->GetFloatValue()); - } else{ - return make_shared(this->GetIntegerValue() >= b->GetIntegerValue()); + const shared_ptr NumericEvalValue::operator>(const shared_ptr &b) const { + if (this->IsFloat()) { + if (b->IsFloat()) { + return make_shared(this->GetFloatValue() > b->GetFloatValue()); + } else { + return make_shared(this->GetFloatValue() > b->GetIntegerValue()); + } + } else { + if (b->IsFloat()) { + return make_shared(this->GetIntegerValue() > b->GetFloatValue()); + } else { + return make_shared(this->GetIntegerValue() > b->GetIntegerValue()); + } } } -} + + const shared_ptr NumericEvalValue::operator>=(const shared_ptr &b) const { + if (this->IsFloat()) { + if (b->IsFloat()) { + return make_shared(this->GetFloatValue() >= b->GetFloatValue()); + } else { + return make_shared(this->GetFloatValue() >= b->GetIntegerValue()); + } + } else { + if (b->IsFloat()) { + return make_shared(this->GetIntegerValue() >= b->GetFloatValue()); + } else { + return make_shared(this->GetIntegerValue() >= b->GetIntegerValue()); + } + } + } +} \ No newline at end of file diff --git a/src/Evaluator/EvalValues/NumericEvalValue.hpp b/src/Evaluator/EvalValues/NumericEvalValue.hpp index 5ed75cf..29430b1 100644 --- a/src/Evaluator/EvalValues/NumericEvalValue.hpp +++ b/src/Evaluator/EvalValues/NumericEvalValue.hpp @@ -4,76 +4,98 @@ #include #include "EvalValue.hpp" +namespace Porygon::Evaluation { + class NumericEvalValue : public EvalValue { -class NumericEvalValue : public EvalValue{ + virtual const long GetIntegerValue() const = 0; - virtual const long GetIntegerValue() const = 0; - virtual const double GetFloatValue() const = 0; + virtual const double GetFloatValue() const = 0; -public: - virtual const bool IsFloat() const = 0; + public: + virtual const bool IsFloat() const = 0; - const TypeClass GetTypeClass() const final{ - return TypeClass ::Number; - } + const TypeClass GetTypeClass() const final { + return TypeClass::Number; + } - const shared_ptr operator +(const shared_ptr& b) const; - const shared_ptr operator -(const shared_ptr& b) const ; - const shared_ptr operator *(const shared_ptr& b) const ; - const shared_ptr operator /(const shared_ptr& b) const ; - const shared_ptr operator <(const shared_ptr& b) const ; - const shared_ptr operator <=(const shared_ptr& b)const ; - const shared_ptr operator >(const shared_ptr& b) const ; - const shared_ptr operator >=(const shared_ptr& b) const ; - const bool operator ==(EvalValue* b) const final; -}; + const shared_ptr operator+(const shared_ptr &b) const; -class IntegerEvalValue : public NumericEvalValue{ - const long _value; - const long GetIntegerValue() const final{return _value;} - const double GetFloatValue() const final{ throw EvaluationException("Attempting to retrieve float from int eval value."); } -public: - explicit IntegerEvalValue(long value) :_value(value){ - } - const bool IsFloat() const final{ - return false; - } + const shared_ptr operator-(const shared_ptr &b) const; - const long EvaluateInteger() const final{ - return _value; - } + const shared_ptr operator*(const shared_ptr &b) const; - const shared_ptr Clone() const final{ - return make_shared(_value); - } + const shared_ptr operator/(const shared_ptr &b) const; - const std::size_t GetHashCode() const final{ - return std::hash{}(_value); - } -}; + const shared_ptr operator<(const shared_ptr &b) const; -class FloatEvalValue : public NumericEvalValue{ - const double _value; - const long GetIntegerValue() const final{ throw EvaluationException("Attempting to retrieve float from int eval value."); } - const double GetFloatValue() const final{return _value;} -public: - explicit FloatEvalValue(double value) :_value(value){ - } - const bool IsFloat() const final{ - return true; - } + const shared_ptr operator<=(const shared_ptr &b) const; - const double EvaluateFloat() const final{ - return _value; - } + const shared_ptr operator>(const shared_ptr &b) const; - const shared_ptr Clone() const final{ - return make_shared(_value); - } + const shared_ptr operator>=(const shared_ptr &b) const; - const std::size_t GetHashCode() const final{ - return std::hash{}(_value); - } -}; + const bool operator==(EvalValue *b) const final; + }; + + class IntegerEvalValue : public NumericEvalValue { + const long _value; + + const long GetIntegerValue() const final { return _value; } + + const double GetFloatValue() const final { + throw EvaluationException("Attempting to retrieve float from int eval value."); + } + + public: + explicit IntegerEvalValue(long value) : _value(value) { + } + + const bool IsFloat() const final { + return false; + } + + const long EvaluateInteger() const final { + return _value; + } + + const shared_ptr Clone() const final { + return make_shared(_value); + } + + const std::size_t GetHashCode() const final { + return std::hash{}(_value); + } + }; + + class FloatEvalValue : public NumericEvalValue { + const double _value; + + const long GetIntegerValue() const final { + throw EvaluationException("Attempting to retrieve float from int eval value."); + } + + const double GetFloatValue() const final { return _value; } + + public: + explicit FloatEvalValue(double value) : _value(value) { + } + + const bool IsFloat() const final { + return true; + } + + const double EvaluateFloat() const final { + return _value; + } + + const shared_ptr Clone() const final { + return make_shared(_value); + } + + const std::size_t GetHashCode() const final { + return std::hash{}(_value); + } + }; +} #endif //PORYGONLANG_NUMERICEVALVALUE_HPP diff --git a/src/Evaluator/EvalValues/ScriptFunctionEvalValue.hpp b/src/Evaluator/EvalValues/ScriptFunctionEvalValue.hpp index 318375b..b788123 100644 --- a/src/Evaluator/EvalValues/ScriptFunctionEvalValue.hpp +++ b/src/Evaluator/EvalValues/ScriptFunctionEvalValue.hpp @@ -11,63 +11,65 @@ #include "../Evaluator.hpp" #include "../EvaluationScope/EvaluationScope.hpp" +namespace Porygon::Evaluation { + class ScriptFunctionEvalValue : public EvalValue { + const std::shared_ptr _innerBlock; + const std::shared_ptr _type; + const std::shared_ptr _scope; + const std::size_t _hash; -class ScriptFunctionEvalValue : public EvalValue{ - const std::shared_ptr _innerBlock; - const std::shared_ptr _type; - const std::shared_ptr _scope; - const std::size_t _hash; - explicit ScriptFunctionEvalValue(std::shared_ptr innerBlock, std::shared_ptr scope, - std::shared_ptr type, size_t hash) - : _type(std::move(type)), - _innerBlock(std::move(innerBlock)), - _scope(std::move(scope)), - _hash(hash) - { - } + explicit ScriptFunctionEvalValue(std::shared_ptr innerBlock, + std::shared_ptr scope, + std::shared_ptr type, size_t hash) + : _type(std::move(type)), + _innerBlock(std::move(innerBlock)), + _scope(std::move(scope)), + _hash(hash) { + } -public: - explicit ScriptFunctionEvalValue(std::shared_ptr innerBlock, std::shared_ptr scope, - std::shared_ptr type) - : _type(std::move(type)), - _innerBlock(std::move(innerBlock)), - _scope(std::move(scope)), - _hash(rand()) - { - } + public: + explicit ScriptFunctionEvalValue(std::shared_ptr innerBlock, + std::shared_ptr scope, + std::shared_ptr type) + : _type(std::move(type)), + _innerBlock(std::move(innerBlock)), + _scope(std::move(scope)), + _hash(rand()) { + } - const std::shared_ptr GetType() const{ - return _type; - } + const std::shared_ptr GetType() const { + return _type; + } - const TypeClass GetTypeClass() const final{ - return TypeClass ::Function; - } + const TypeClass GetTypeClass() const final { + return TypeClass::Function; + } - const shared_ptr Clone() const final{ - // We don't run make_shared here as it can't call private constructors - return shared_ptr(new ScriptFunctionEvalValue(_innerBlock, _scope, _type, _hash)); - } + const shared_ptr Clone() const final { + // We don't run make_shared here as it can't call private constructors + return shared_ptr(new ScriptFunctionEvalValue(_innerBlock, _scope, _type, _hash)); + } - const bool operator ==(EvalValue* b) const final{ - if (b->GetTypeClass() != TypeClass::Function) - return false; - return this->_hash == ((ScriptFunctionEvalValue*)b)->_hash; + const bool operator==(EvalValue *b) const final { + if (b->GetTypeClass() != TypeClass::Function) + return false; + return this->_hash == ((ScriptFunctionEvalValue *) b)->_hash; + }; + + const std::shared_ptr &GetInnerBlock() const { + return _innerBlock; + } + + const std::size_t GetHashCode() const final { + return _hash; + } + + const std::shared_ptr &GetScope() const { + return _scope; + } }; - - const std::shared_ptr& GetInnerBlock() const{ - return _innerBlock; - } - - const std::size_t GetHashCode() const final{ - return _hash; - } - - const std::shared_ptr& GetScope() const{ - return _scope; - } -}; +} #endif //PORYGONLANG_SCRIPTFUNCTIONEVALVALUE_HPP diff --git a/src/Evaluator/EvalValues/StringEvalValue.hpp b/src/Evaluator/EvalValues/StringEvalValue.hpp index 51a22e4..b8ce918 100644 --- a/src/Evaluator/EvalValues/StringEvalValue.hpp +++ b/src/Evaluator/EvalValues/StringEvalValue.hpp @@ -8,43 +8,44 @@ using namespace std; -class StringEvalValue : public EvalValue{ - u16string _value; - size_t _hash; -public: - explicit StringEvalValue(u16string s){ - _value = move(s); - _hash = HashedString::ConstHash (_value.c_str()); - } +namespace Porygon::Evaluation { + class StringEvalValue : public EvalValue { + u16string _value; + size_t _hash; + public: + explicit StringEvalValue(u16string s) { + _value = move(s); + _hash = Utilities::HashedString::ConstHash(_value.c_str()); + } - const TypeClass GetTypeClass() const final{ - return TypeClass ::String; - } + const TypeClass GetTypeClass() const final { + return TypeClass::String; + } - const bool operator ==(EvalValue* b) const final{ - if (b->GetTypeClass() != TypeClass::String) - return false; - return this->_hash == b->GetHashCode(); + const bool operator==(EvalValue *b) const final { + if (b->GetTypeClass() != TypeClass::String) + return false; + return this->_hash == b->GetHashCode(); + }; + + const u16string *EvaluateString() const final { + return &_value; + } + + const shared_ptr Clone() const final { + return make_shared(_value); + } + + const shared_ptr IndexValue(EvalValue *val) const final { + // Porygon is 1-indexed, so we convert to that. + auto l = val->EvaluateInteger() - 1; + return make_shared(u16string(1, _value[l])); + } + + const std::size_t GetHashCode() const final { + return _hash; + } }; - - const u16string* EvaluateString() const final{ - return &_value; - } - - const shared_ptr Clone() const final{ - return make_shared(_value); - } - - const shared_ptr IndexValue(EvalValue* val) const final{ - // Porygon is 1-indexed, so we convert to that. - auto l = val->EvaluateInteger() - 1; - return make_shared(u16string(1, _value[l])); - } - - const std::size_t GetHashCode() const final{ - return _hash; - } -}; - +} #endif //PORYGONLANG_STRINGEVALVALUE_HPP diff --git a/src/Evaluator/EvalValues/TableEvalValue.hpp b/src/Evaluator/EvalValues/TableEvalValue.hpp index b35c9b0..5f1dcd7 100644 --- a/src/Evaluator/EvalValues/TableEvalValue.hpp +++ b/src/Evaluator/EvalValues/TableEvalValue.hpp @@ -6,55 +6,57 @@ using namespace std; -class TableEvalValue : public EvalValue { - shared_ptr>> _table; - size_t _hash; +namespace Porygon::Evaluation { + class TableEvalValue : public EvalValue { + shared_ptr>> _table; + size_t _hash; - explicit TableEvalValue(shared_ptr>> table, size_t hash){ - _table = std::move(table); - _hash = hash; - } -public: - explicit TableEvalValue(shared_ptr>> table){ - _table = std::move(table); - _hash = rand(); - } + explicit TableEvalValue(shared_ptr>> table, size_t hash) { + _table = std::move(table); + _hash = hash; + } - const TypeClass GetTypeClass() const final{ - return TypeClass ::Table; - } + public: + explicit TableEvalValue(shared_ptr>> table) { + _table = std::move(table); + _hash = rand(); + } - const size_t GetHashCode() const final{ - return _hash; - } + const TypeClass GetTypeClass() const final { + return TypeClass::Table; + } - const bool operator ==(EvalValue* b) const final{ - return this -> _hash == b->GetHashCode(); - } + const size_t GetHashCode() const final { + return _hash; + } - const shared_ptr Clone() const final{ - return shared_ptr(new TableEvalValue(_table, _hash)); - } + const bool operator==(EvalValue *b) const final { + return this->_hash == b->GetHashCode(); + } - const shared_ptr IndexValue(EvalValue* val) const final{ - auto hash = val->GetHashCode(); - return this -> _table->at(hash); - } + const shared_ptr Clone() const final { + return shared_ptr(new TableEvalValue(_table, _hash)); + } - const shared_ptr IndexValue(uint32_t hash) const final{ - return this -> _table->at(hash); - } + const shared_ptr IndexValue(EvalValue *val) const final { + auto hash = val->GetHashCode(); + return this->_table->at(hash); + } - const shared_ptr IndexValue(const char* val) const { - auto hash = HashedString::ConstHash(val); - return this -> _table -> at(hash); - } + const shared_ptr IndexValue(uint32_t hash) const final { + return this->_table->at(hash); + } - void SetIndexValue(EvalValue *key, const shared_ptr& value) const final{ - auto hash = key->GetHashCode(); - this -> _table->at(hash) = value; - } -}; + const shared_ptr IndexValue(const char *val) const { + auto hash = Utilities::HashedString::ConstHash(val); + return this->_table->at(hash); + } + void SetIndexValue(EvalValue *key, const shared_ptr &value) const final { + auto hash = key->GetHashCode(); + this->_table->at(hash) = value; + } + }; +} #endif //PORYGONLANG_TABLEEVALVALUE_HPP diff --git a/src/Evaluator/EvaluationException.hpp b/src/Evaluator/EvaluationException.hpp index f301049..30431df 100644 --- a/src/Evaluator/EvaluationException.hpp +++ b/src/Evaluator/EvaluationException.hpp @@ -7,18 +7,20 @@ #include using namespace std; -class EvaluationException : public std::exception { - string _message; -public: - explicit EvaluationException(string message){ - _message = std::move(message); - } +namespace Porygon::Evaluation { + class EvaluationException : public std::exception { + string _message; + public: + explicit EvaluationException(string message) { + _message = std::move(message); + } - const string defaultErrorText = "An evaluation exception occurred: "; - const char* what() const noexcept final{ - return (defaultErrorText + _message).c_str(); - } -}; + const string defaultErrorText = "An evaluation exception occurred: "; + const char *what() const noexcept final { + return (defaultErrorText + _message).c_str(); + } + }; +} #endif //PORYGONLANG_EVALUATIONEXCEPTION_HPP diff --git a/src/Evaluator/EvaluationScope/EvaluationScope.cpp b/src/Evaluator/EvaluationScope/EvaluationScope.cpp index fda399c..c50bf4d 100644 --- a/src/Evaluator/EvaluationScope/EvaluationScope.cpp +++ b/src/Evaluator/EvaluationScope/EvaluationScope.cpp @@ -2,34 +2,37 @@ #include "EvaluationScope.hpp" #include -EvaluationScope::EvaluationScope(unordered_map> *scriptVariables, int localVariableCount) { - _scriptScope = scriptVariables; - _localScope = unordered_map>(localVariableCount); -} +namespace Porygon::Evaluation { + EvaluationScope::EvaluationScope(unordered_map> *scriptVariables, + int localVariableCount) { + _scriptScope = scriptVariables; + _localScope = unordered_map>(localVariableCount); + } -void EvaluationScope::CreateVariable(const BoundVariableKey* key, const shared_ptr &value) { - if (key->GetScopeId() == 0){ - _scriptScope -> at(key->GetIdentifier()) = value; - } else{ - auto insert = _localScope.insert({key->GetHash(), value}); - if (!insert.second){ + void EvaluationScope::CreateVariable(const BoundVariableKey *key, const shared_ptr &value) { + if (key->GetScopeId() == 0) { + _scriptScope->at(key->GetIdentifier()) = value; + } else { + auto insert = _localScope.insert({key->GetHash(), value}); + if (!insert.second) { + _localScope[key->GetHash()] = value; + } + } + } + + void EvaluationScope::SetVariable(const BoundVariableKey *key, const shared_ptr &value) { + if (key->GetScopeId() == 0) { + _scriptScope->at(key->GetIdentifier()) = value; + } else { _localScope[key->GetHash()] = value; } } -} -void EvaluationScope::SetVariable(const BoundVariableKey* key, const shared_ptr &value) { - if (key->GetScopeId() == 0){ - _scriptScope -> at(key->GetIdentifier()) = value; - } else{ - _localScope[key->GetHash()] = value; - } -} - -shared_ptr EvaluationScope::GetVariable(const BoundVariableKey* key) { - if (key->GetScopeId() == 0){ - return _scriptScope -> at(key->GetIdentifier()); - } else{ - return _localScope[key->GetHash()]; + shared_ptr EvaluationScope::GetVariable(const BoundVariableKey *key) { + if (key->GetScopeId() == 0) { + return _scriptScope->at(key->GetIdentifier()); + } else { + return _localScope[key->GetHash()]; + } } } \ No newline at end of file diff --git a/src/Evaluator/EvaluationScope/EvaluationScope.hpp b/src/Evaluator/EvaluationScope/EvaluationScope.hpp index f9e5820..57e8620 100644 --- a/src/Evaluator/EvaluationScope/EvaluationScope.hpp +++ b/src/Evaluator/EvaluationScope/EvaluationScope.hpp @@ -5,18 +5,24 @@ #include #include #include "../EvalValues/EvalValue.hpp" +using namespace Porygon::Binder; -class EvaluationScope { - unordered_map>* _scriptScope; - unordered_map> _localScope; -public: - explicit EvaluationScope(unordered_map>* scriptVariables, int deepestScope); - ~EvaluationScope() = default; +namespace Porygon::Evaluation { + class EvaluationScope { + unordered_map> *_scriptScope; + unordered_map> _localScope; + public: + explicit EvaluationScope(unordered_map> *scriptVariables, int deepestScope); - void CreateVariable(const BoundVariableKey* key, const shared_ptr& value); - void SetVariable(const BoundVariableKey* key, const shared_ptr& value); - shared_ptr GetVariable(const BoundVariableKey* key); -}; + ~EvaluationScope() = default; + + void CreateVariable(const BoundVariableKey *key, const shared_ptr &value); + + void SetVariable(const BoundVariableKey *key, const shared_ptr &value); + + shared_ptr GetVariable(const BoundVariableKey *key); + }; +} #endif //PORYGONLANG_EVALUATIONSCOPE_HPP diff --git a/src/Evaluator/Evaluator.cpp b/src/Evaluator/Evaluator.cpp index db0d53e..af53223 100644 --- a/src/Evaluator/Evaluator.cpp +++ b/src/Evaluator/Evaluator.cpp @@ -11,317 +11,369 @@ #include "../TableScriptType.hpp" using namespace std; +using namespace Porygon::Binder; -EvalValue* Evaluator::Evaluate(const BoundScriptStatement *statement) { - this->_evaluationScope = make_shared(this->_scriptData->_scriptVariables, statement->GetLocalVariableCount()); - EvaluateBlockStatement(statement); - return this -> _returnValue.get(); -} - -void Evaluator::EvaluateStatement(const BoundStatement *statement) { - if (this->_hasReturned) - return; - switch (statement->GetKind()){ - case BoundStatementKind ::Script: throw; // Should never happen - case BoundStatementKind ::Block: return this->EvaluateBlockStatement((BoundBlockStatement *) statement); - case BoundStatementKind ::Expression: return this -> EvaluateExpressionStatement((BoundExpressionStatement*)statement); - case BoundStatementKind ::Assignment: return this -> EvaluateAssignmentStatement((BoundAssignmentStatement*)statement); - case BoundStatementKind::IndexAssignment: - return this -> EvaluateIndexAssignmentStatement((BoundIndexAssignmentStatement*)statement); - case BoundStatementKind ::FunctionDeclaration: return this->EvaluateFunctionDeclarationStatement((BoundFunctionDeclarationStatement*)statement); - case BoundStatementKind::Return: return this -> EvaluateReturnStatement((BoundReturnStatement*)statement); - case BoundStatementKind::Conditional: return this -> EvaluateConditionalStatement((BoundConditionalStatement*)statement); - - case BoundStatementKind::Bad: - throw; +namespace Porygon::Evaluation { + EvalValue *Evaluator::Evaluate(const BoundScriptStatement *statement) { + this->_evaluationScope = make_shared(this->_scriptVariables, + statement->GetLocalVariableCount()); + EvaluateBlockStatement(statement); + return this->_returnValue.get(); } -} -void Evaluator::EvaluateBlockStatement(const BoundBlockStatement *statement) { - for (auto s: *statement->GetStatements()){ - this -> EvaluateStatement(s); + void Evaluator::EvaluateStatement(const BoundStatement *statement) { if (this->_hasReturned) - break; - } -} + return; + switch (statement->GetKind()) { + case BoundStatementKind::Script: + throw; // Should never happen + case BoundStatementKind::Block: + return this->EvaluateBlockStatement((BoundBlockStatement *) statement); + case BoundStatementKind::Expression: + return this->EvaluateExpressionStatement((BoundExpressionStatement *) statement); + case BoundStatementKind::Assignment: + return this->EvaluateAssignmentStatement((BoundAssignmentStatement *) statement); + case BoundStatementKind::IndexAssignment: + return this->EvaluateIndexAssignmentStatement((BoundIndexAssignmentStatement *) statement); + case BoundStatementKind::FunctionDeclaration: + return this->EvaluateFunctionDeclarationStatement((BoundFunctionDeclarationStatement *) statement); + case BoundStatementKind::Return: + return this->EvaluateReturnStatement((BoundReturnStatement *) statement); + case BoundStatementKind::Conditional: + return this->EvaluateConditionalStatement((BoundConditionalStatement *) statement); -void Evaluator::EvaluateExpressionStatement(const BoundExpressionStatement *statement) { - // Save new value - this->_lastValue = this -> EvaluateExpression(statement->GetExpression()); -} - -void Evaluator::EvaluateAssignmentStatement(const BoundAssignmentStatement *statement) { - auto value = this -> EvaluateExpression(statement->GetExpression()); - auto key = statement->GetKey(); - if (key->IsCreation()){ - this->_evaluationScope->CreateVariable(key, value); - } else{ - this->_evaluationScope->SetVariable(key, value); - } -} - -void Evaluator::EvaluateIndexAssignmentStatement(const BoundIndexAssignmentStatement *statement) { - auto indexExpression = statement -> GetIndexExpression(); - auto value = this -> EvaluateExpression(statement -> GetValueExpression()); - auto index = ((BoundIndexExpression*)indexExpression); - auto table = this -> EvaluateExpression(index -> GetIndexableExpression()); - auto key = this -> EvaluateExpression(index->GetIndexExpression()); - table -> SetIndexValue(key.get(), value); -} - -void Evaluator::EvaluateFunctionDeclarationStatement(const BoundFunctionDeclarationStatement *statement) { - auto type = statement->GetType(); - auto key = statement->GetKey(); - auto block = statement->GetBlock(); - auto value = make_shared(block, this->_evaluationScope, type); - if (key->IsCreation()){ - this->_evaluationScope->CreateVariable(key, value); - } else{ - this->_evaluationScope->SetVariable(key, value); - } -} - -void Evaluator::EvaluateReturnStatement(const BoundReturnStatement* statement){ - auto expression = statement->GetExpression(); - if (expression == nullptr){ - this->_hasReturned = true; - return; - } - auto value = this -> EvaluateExpression(expression); - this->_hasReturned = true; - this -> _returnValue = value; -} - -void Evaluator::EvaluateConditionalStatement(const BoundConditionalStatement *statement) { - auto condition = statement->GetCondition(); - if (EvaluateBoolExpression(condition) -> EvaluateBool()){ - this -> EvaluateStatement(statement->GetBlock()); - } else{ - auto elseStatement = statement -> GetElseStatement(); - if (elseStatement != nullptr){ - this->EvaluateStatement(elseStatement); + case BoundStatementKind::Bad: + throw; } } -} -const shared_ptr Evaluator::EvaluateExpression(const BoundExpression *expression) { - auto type = expression -> GetType(); - switch (type->GetClass()){ - case TypeClass ::Number: return this -> EvaluateIntegerExpression(expression); - case TypeClass ::Bool: return this -> EvaluateBoolExpression(expression); - case TypeClass ::String: return this -> EvaluateStringExpression(expression); - case TypeClass ::Function: return this->EvaluateFunctionExpression(expression); - case TypeClass ::Nil: return this->EvaluateNilExpression(expression); - case TypeClass ::Table: return this-> EvaluateTableExpression(expression); - case TypeClass ::UserData: return this -> EvaluateUserDataExpression(expression); - default: throw; - } -} - -const shared_ptr Evaluator::GetVariable(const BoundVariableExpression *expression){ - auto variable = this->_evaluationScope->GetVariable(expression->GetKey()); - if (variable == nullptr){ - throw EvaluationException("Variable not found"); - } - return variable->Clone(); -} - -const shared_ptr Evaluator::EvaluateIntegerExpression(const BoundExpression *expression) { - switch (expression->GetKind()){ - case BoundExpressionKind ::LiteralInteger: return make_shared(((BoundLiteralIntegerExpression*)expression)->GetValue()); - case BoundExpressionKind ::LiteralFloat: return make_shared(((BoundLiteralFloatExpression*)expression)->GetValue()); - case BoundExpressionKind::Unary: return this -> EvaluateIntegerUnary((BoundUnaryExpression*)expression); - case BoundExpressionKind ::Binary: return this -> EvaluateIntegerBinary((BoundBinaryExpression*)expression); - case BoundExpressionKind::Variable: return dynamic_pointer_cast(this->GetVariable((BoundVariableExpression*)expression)); - case BoundExpressionKind ::FunctionCall: return dynamic_pointer_cast(this->EvaluateFunctionCallExpression(expression)); - case BoundExpressionKind ::Index: return dynamic_pointer_cast(this->EvaluateIndexExpression(expression)); - case BoundExpressionKind ::PeriodIndex: return dynamic_pointer_cast(this->EvaluatePeriodIndexExpression(expression)); - - case BoundExpressionKind ::LiteralString: - case BoundExpressionKind ::LiteralBool: - case BoundExpressionKind ::Bad: - case BoundExpressionKind::NumericalTable: - case BoundExpressionKind::Table: - throw; - } -} - -const shared_ptr Evaluator::EvaluateBoolExpression(const BoundExpression *expression) { - switch (expression->GetKind()) { - case BoundExpressionKind ::LiteralBool: return make_shared(((BoundLiteralBoolExpression*)expression)->GetValue()); - case BoundExpressionKind::Unary: return this -> EvaluateBooleanUnary((BoundUnaryExpression*)expression); - case BoundExpressionKind::Binary: return this -> EvaluateBooleanBinary((BoundBinaryExpression*)expression); - case BoundExpressionKind::Variable: return dynamic_pointer_cast(this->GetVariable((BoundVariableExpression*)expression)); - case BoundExpressionKind ::FunctionCall: return dynamic_pointer_cast(this->EvaluateFunctionCallExpression(expression)); - case BoundExpressionKind ::Index: return dynamic_pointer_cast(this->EvaluateIndexExpression(expression)); - case BoundExpressionKind ::PeriodIndex: return dynamic_pointer_cast(this->EvaluatePeriodIndexExpression(expression)); - - case BoundExpressionKind::Bad: - case BoundExpressionKind::LiteralInteger: - case BoundExpressionKind::LiteralFloat: - case BoundExpressionKind::LiteralString: - case BoundExpressionKind::NumericalTable: - case BoundExpressionKind::Table: - throw; - - } -} - -const shared_ptr Evaluator::EvaluateStringExpression(const BoundExpression *expression) { - switch (expression->GetKind()) { - case BoundExpressionKind ::LiteralString: - return make_shared(((BoundLiteralStringExpression*)expression)->GetValue()); - case BoundExpressionKind::Binary: - return this -> EvaluateStringBinary((BoundBinaryExpression*)expression); - case BoundExpressionKind::Variable: return dynamic_pointer_cast(this->GetVariable((BoundVariableExpression*)expression)); - case BoundExpressionKind ::FunctionCall: return dynamic_pointer_cast(this->EvaluateFunctionCallExpression(expression)); - case BoundExpressionKind ::Index: return dynamic_pointer_cast(this->EvaluateIndexExpression(expression)); - case BoundExpressionKind ::PeriodIndex: return dynamic_pointer_cast(this->EvaluatePeriodIndexExpression(expression)); - - case BoundExpressionKind::Bad: - case BoundExpressionKind::LiteralInteger: - case BoundExpressionKind::LiteralFloat: - case BoundExpressionKind::LiteralBool: - case BoundExpressionKind::Unary: - case BoundExpressionKind::NumericalTable: - case BoundExpressionKind::Table: - throw; - - } -} - -const shared_ptr Evaluator::EvaluateFunctionExpression(const BoundExpression *expression){ - switch (expression->GetKind()){ - case BoundExpressionKind ::Variable: return this->GetVariable((BoundVariableExpression*)expression); - case BoundExpressionKind ::Index: return this->EvaluateIndexExpression(expression); - case BoundExpressionKind ::PeriodIndex: return this->EvaluatePeriodIndexExpression(expression); - default: throw; - } -} -const shared_ptr Evaluator::EvaluateNilExpression(const BoundExpression *expression){ - switch (expression->GetKind()){ - case BoundExpressionKind ::FunctionCall: - return this->EvaluateFunctionCallExpression(expression); - default: - return nullptr; - } -} -const shared_ptr Evaluator::EvaluateTableExpression(const BoundExpression *expression){ - switch (expression->GetKind()){ - case BoundExpressionKind ::FunctionCall: - return this->EvaluateFunctionCallExpression(expression); - case BoundExpressionKind ::Variable: return this->GetVariable((BoundVariableExpression*)expression); - case BoundExpressionKind ::Index: return this->EvaluateIndexExpression(expression); - case BoundExpressionKind ::NumericalTable: return this-> EvaluateNumericTableExpression(expression); - case BoundExpressionKind ::Table: return this -> EvaluateComplexTableExpression(expression); - case BoundExpressionKind ::PeriodIndex: return this->EvaluatePeriodIndexExpression(expression); - default: - throw; - } -} - - - - -const shared_ptr Evaluator::EvaluateFunctionCallExpression(const BoundExpression *expression){ - auto functionCall = (BoundFunctionCallExpression*)expression; - auto function = dynamic_pointer_cast(this->EvaluateExpression(functionCall->GetFunctionExpression())); - - auto boundParameters = functionCall->GetParameters(); - auto parameters = vector>(boundParameters->size()); - for (int i = 0; i < boundParameters->size(); i++){ - parameters[i] = this->EvaluateExpression(boundParameters->at(i)); + void Evaluator::EvaluateBlockStatement(const BoundBlockStatement *statement) { + for (auto s: *statement->GetStatements()) { + this->EvaluateStatement(s); + if (this->_hasReturned) + break; + } } - auto type = std::dynamic_pointer_cast(function->GetType()); - auto parameterTypes = type->GetParameterTypes(); - auto parameterKeys = type->GetParameterKeys(); - auto originalScope = this->_evaluationScope; - this->_evaluationScope = function->GetScope(); - - for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++){ - auto parameter = parameters[i]; - auto key = parameterKeys.at(i); - this->_evaluationScope->CreateVariable(key.get(), parameter->Clone()); + void Evaluator::EvaluateExpressionStatement(const BoundExpressionStatement *statement) { + // Save new value + this->_lastValue = this->EvaluateExpression(statement->GetExpression()); } - this->EvaluateBlockStatement(function->GetInnerBlock().get()); - this->_evaluationScope = originalScope; - this->_hasReturned = false; - auto r = this -> _returnValue; - this -> _returnValue = nullptr; - return r; -} - -const shared_ptr Evaluator::EvaluateFunction(const ScriptFunctionEvalValue *function, - const vector ¶meters) { - auto type = std::dynamic_pointer_cast(function->GetType()); - auto parameterTypes = type->GetParameterTypes(); - auto parameterKeys = type->GetParameterKeys(); - - auto originalScope = this->_evaluationScope; - this->_evaluationScope = function->GetScope(); - - for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++){ - auto parameter = parameters[i]; - auto key = parameterKeys.at(i); - this->_evaluationScope->CreateVariable(key.get(), parameter->Clone()); + void Evaluator::EvaluateAssignmentStatement(const BoundAssignmentStatement *statement) { + auto value = this->EvaluateExpression(statement->GetExpression()); + auto key = statement->GetKey(); + if (key->IsCreation()) { + this->_evaluationScope->CreateVariable(key, value); + } else { + this->_evaluationScope->SetVariable(key, value); + } } - this->EvaluateBlockStatement(function->GetInnerBlock().get()); - this->_evaluationScope = originalScope; - this->_hasReturned = false; - auto r = this -> _returnValue; - this -> _returnValue = nullptr; - return r; -} -const shared_ptr Evaluator::EvaluateIndexExpression(const BoundExpression *expression) { - auto indexExpression = (BoundIndexExpression*)expression; - auto index = this -> EvaluateExpression(indexExpression->GetIndexExpression()); - auto indexable = this -> EvaluateExpression(indexExpression->GetIndexableExpression()); - return indexable -> IndexValue(index.get()) -> Clone(); -} - -const shared_ptr Evaluator::EvaluatePeriodIndexExpression(const BoundExpression *expression) { - auto indexExpression = (BoundPeriodIndexExpression*)expression; - auto index = indexExpression -> GetIndex().GetHash(); - auto indexable = this -> EvaluateExpression(indexExpression->GetIndexableExpression()); - return indexable -> IndexValue(index) -> Clone(); -} - -const shared_ptr Evaluator::EvaluateNumericTableExpression(const BoundExpression *expression) { - auto tableExpression = (BoundNumericalTableExpression*)expression; - auto valueExpressions = tableExpression->GetExpressions(); - auto values = new unordered_map>(valueExpressions->size()); - for (int i = 0; i < valueExpressions->size(); i++){ - auto val = this -> EvaluateExpression(valueExpressions -> at(i)); - values -> insert({i + 1, val}); + void Evaluator::EvaluateIndexAssignmentStatement(const BoundIndexAssignmentStatement *statement) { + auto indexExpression = statement->GetIndexExpression(); + auto value = this->EvaluateExpression(statement->GetValueExpression()); + auto index = ((BoundIndexExpression *) indexExpression); + auto table = this->EvaluateExpression(index->GetIndexableExpression()); + auto key = this->EvaluateExpression(index->GetIndexExpression()); + table->SetIndexValue(key.get(), value); } - auto valuesPointer = shared_ptr>>(values); - return make_shared(valuesPointer); -} -const shared_ptr Evaluator::EvaluateComplexTableExpression(const BoundExpression *expression) { - auto tableExpression = (BoundTableExpression*)expression; - auto type = dynamic_pointer_cast(tableExpression->GetType()); - auto declaredVars = type -> GetValues(); - auto variables = make_shared>>(declaredVars->size()); - for (auto i : *declaredVars){ - variables->insert({i.first, nullptr}); + void Evaluator::EvaluateFunctionDeclarationStatement(const BoundFunctionDeclarationStatement *statement) { + auto type = statement->GetType(); + auto key = statement->GetKey(); + auto block = statement->GetBlock(); + auto value = make_shared(block, this->_evaluationScope, type); + if (key->IsCreation()) { + this->_evaluationScope->CreateVariable(key, value); + } else { + this->_evaluationScope->SetVariable(key, value); + } } - auto evaluator = make_shared(variables.get(), type -> GetLocalVariableCount()); - auto currentEvaluator = this -> _evaluationScope; - this -> _evaluationScope = evaluator; - this->EvaluateBlockStatement(tableExpression->GetBlock()); - this -> _evaluationScope = currentEvaluator; - return make_shared(variables); -} -const shared_ptr Evaluator::EvaluateUserDataExpression(const BoundExpression *expression) { - switch (expression->GetKind()){ - case BoundExpressionKind ::Variable: return this->GetVariable((BoundVariableExpression*)expression); - case BoundExpressionKind ::Index: return this -> EvaluateIndexExpression(expression); - default: throw; + void Evaluator::EvaluateReturnStatement(const BoundReturnStatement *statement) { + auto expression = statement->GetExpression(); + if (expression == nullptr) { + this->_hasReturned = true; + return; + } + auto value = this->EvaluateExpression(expression); + this->_hasReturned = true; + this->_returnValue = value; } -} + void Evaluator::EvaluateConditionalStatement(const BoundConditionalStatement *statement) { + auto condition = statement->GetCondition(); + if (EvaluateBoolExpression(condition)->EvaluateBool()) { + this->EvaluateStatement(statement->GetBlock()); + } else { + auto elseStatement = statement->GetElseStatement(); + if (elseStatement != nullptr) { + this->EvaluateStatement(elseStatement); + } + } + } + + const shared_ptr Evaluator::EvaluateExpression(const BoundExpression *expression) { + auto type = expression->GetType(); + switch (type->GetClass()) { + case TypeClass::Number: + return this->EvaluateIntegerExpression(expression); + case TypeClass::Bool: + return this->EvaluateBoolExpression(expression); + case TypeClass::String: + return this->EvaluateStringExpression(expression); + case TypeClass::Function: + return this->EvaluateFunctionExpression(expression); + case TypeClass::Nil: + return this->EvaluateNilExpression(expression); + case TypeClass::Table: + return this->EvaluateTableExpression(expression); + case TypeClass::UserData: + return this->EvaluateUserDataExpression(expression); + default: + throw; + } + } + + const shared_ptr Evaluator::GetVariable(const BoundVariableExpression *expression) { + auto variable = this->_evaluationScope->GetVariable(expression->GetKey()); + if (variable == nullptr) { + throw EvaluationException("Variable not found"); + } + return variable->Clone(); + } + + const shared_ptr Evaluator::EvaluateIntegerExpression(const BoundExpression *expression) { + switch (expression->GetKind()) { + case BoundExpressionKind::LiteralInteger: + return make_shared(((BoundLiteralIntegerExpression *) expression)->GetValue()); + case BoundExpressionKind::LiteralFloat: + return make_shared(((BoundLiteralFloatExpression *) expression)->GetValue()); + case BoundExpressionKind::Unary: + return this->EvaluateIntegerUnary((BoundUnaryExpression *) expression); + case BoundExpressionKind::Binary: + return this->EvaluateIntegerBinary((BoundBinaryExpression *) expression); + case BoundExpressionKind::Variable: + return dynamic_pointer_cast( + this->GetVariable((BoundVariableExpression *) expression)); + case BoundExpressionKind::FunctionCall: + return dynamic_pointer_cast(this->EvaluateFunctionCallExpression(expression)); + case BoundExpressionKind::Index: + return dynamic_pointer_cast(this->EvaluateIndexExpression(expression)); + case BoundExpressionKind::PeriodIndex: + return dynamic_pointer_cast(this->EvaluatePeriodIndexExpression(expression)); + + case BoundExpressionKind::LiteralString: + case BoundExpressionKind::LiteralBool: + case BoundExpressionKind::Bad: + case BoundExpressionKind::NumericalTable: + case BoundExpressionKind::Table: + throw; + } + } + + const shared_ptr Evaluator::EvaluateBoolExpression(const BoundExpression *expression) { + switch (expression->GetKind()) { + case BoundExpressionKind::LiteralBool: + return make_shared(((BoundLiteralBoolExpression *) expression)->GetValue()); + case BoundExpressionKind::Unary: + return this->EvaluateBooleanUnary((BoundUnaryExpression *) expression); + case BoundExpressionKind::Binary: + return this->EvaluateBooleanBinary((BoundBinaryExpression *) expression); + case BoundExpressionKind::Variable: + return dynamic_pointer_cast( + this->GetVariable((BoundVariableExpression *) expression)); + case BoundExpressionKind::FunctionCall: + return dynamic_pointer_cast(this->EvaluateFunctionCallExpression(expression)); + case BoundExpressionKind::Index: + return dynamic_pointer_cast(this->EvaluateIndexExpression(expression)); + case BoundExpressionKind::PeriodIndex: + return dynamic_pointer_cast(this->EvaluatePeriodIndexExpression(expression)); + + case BoundExpressionKind::Bad: + case BoundExpressionKind::LiteralInteger: + case BoundExpressionKind::LiteralFloat: + case BoundExpressionKind::LiteralString: + case BoundExpressionKind::NumericalTable: + case BoundExpressionKind::Table: + throw; + + } + } + + const shared_ptr Evaluator::EvaluateStringExpression(const BoundExpression *expression) { + switch (expression->GetKind()) { + case BoundExpressionKind::LiteralString: + return make_shared(((BoundLiteralStringExpression *) expression)->GetValue()); + case BoundExpressionKind::Binary: + return this->EvaluateStringBinary((BoundBinaryExpression *) expression); + case BoundExpressionKind::Variable: + return dynamic_pointer_cast(this->GetVariable((BoundVariableExpression *) expression)); + case BoundExpressionKind::FunctionCall: + return dynamic_pointer_cast(this->EvaluateFunctionCallExpression(expression)); + case BoundExpressionKind::Index: + return dynamic_pointer_cast(this->EvaluateIndexExpression(expression)); + case BoundExpressionKind::PeriodIndex: + return dynamic_pointer_cast(this->EvaluatePeriodIndexExpression(expression)); + + case BoundExpressionKind::Bad: + case BoundExpressionKind::LiteralInteger: + case BoundExpressionKind::LiteralFloat: + case BoundExpressionKind::LiteralBool: + case BoundExpressionKind::Unary: + case BoundExpressionKind::NumericalTable: + case BoundExpressionKind::Table: + throw; + + } + } + + const shared_ptr Evaluator::EvaluateFunctionExpression(const BoundExpression *expression) { + switch (expression->GetKind()) { + case BoundExpressionKind::Variable: + return this->GetVariable((BoundVariableExpression *) expression); + case BoundExpressionKind::Index: + return this->EvaluateIndexExpression(expression); + case BoundExpressionKind::PeriodIndex: + return this->EvaluatePeriodIndexExpression(expression); + default: + throw; + } + } + + const shared_ptr Evaluator::EvaluateNilExpression(const BoundExpression *expression) { + switch (expression->GetKind()) { + case BoundExpressionKind::FunctionCall: + return this->EvaluateFunctionCallExpression(expression); + default: + return nullptr; + } + } + + const shared_ptr Evaluator::EvaluateTableExpression(const BoundExpression *expression) { + switch (expression->GetKind()) { + case BoundExpressionKind::FunctionCall: + return this->EvaluateFunctionCallExpression(expression); + case BoundExpressionKind::Variable: + return this->GetVariable((BoundVariableExpression *) expression); + case BoundExpressionKind::Index: + return this->EvaluateIndexExpression(expression); + case BoundExpressionKind::NumericalTable: + return this->EvaluateNumericTableExpression(expression); + case BoundExpressionKind::Table: + return this->EvaluateComplexTableExpression(expression); + case BoundExpressionKind::PeriodIndex: + return this->EvaluatePeriodIndexExpression(expression); + default: + throw; + } + } + + + const shared_ptr Evaluator::EvaluateFunctionCallExpression(const BoundExpression *expression) { + auto functionCall = (BoundFunctionCallExpression *) expression; + auto function = dynamic_pointer_cast( + this->EvaluateExpression(functionCall->GetFunctionExpression())); + + auto boundParameters = functionCall->GetParameters(); + auto parameters = vector>(boundParameters->size()); + for (int i = 0; i < boundParameters->size(); i++) { + parameters[i] = this->EvaluateExpression(boundParameters->at(i)); + } + + auto type = std::dynamic_pointer_cast(function->GetType()); + auto parameterTypes = type->GetParameterTypes(); + auto parameterKeys = type->GetParameterKeys(); + auto originalScope = this->_evaluationScope; + this->_evaluationScope = function->GetScope(); + + for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++) { + auto parameter = parameters[i]; + auto key = parameterKeys.at(i); + this->_evaluationScope->CreateVariable(key.get(), parameter->Clone()); + } + this->EvaluateBlockStatement(function->GetInnerBlock().get()); + this->_evaluationScope = originalScope; + + this->_hasReturned = false; + auto r = this->_returnValue; + this->_returnValue = nullptr; + return r; + } + + const shared_ptr Evaluator::EvaluateFunction(const ScriptFunctionEvalValue *function, + const vector ¶meters) { + auto type = std::dynamic_pointer_cast(function->GetType()); + auto parameterTypes = type->GetParameterTypes(); + auto parameterKeys = type->GetParameterKeys(); + + auto originalScope = this->_evaluationScope; + this->_evaluationScope = function->GetScope(); + + for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++) { + auto parameter = parameters[i]; + auto key = parameterKeys.at(i); + this->_evaluationScope->CreateVariable(key.get(), parameter->Clone()); + } + this->EvaluateBlockStatement(function->GetInnerBlock().get()); + this->_evaluationScope = originalScope; + this->_hasReturned = false; + auto r = this->_returnValue; + this->_returnValue = nullptr; + return r; + } + + const shared_ptr Evaluator::EvaluateIndexExpression(const BoundExpression *expression) { + auto indexExpression = (BoundIndexExpression *) expression; + auto index = this->EvaluateExpression(indexExpression->GetIndexExpression()); + auto indexable = this->EvaluateExpression(indexExpression->GetIndexableExpression()); + return indexable->IndexValue(index.get())->Clone(); + } + + const shared_ptr Evaluator::EvaluatePeriodIndexExpression(const BoundExpression *expression) { + auto indexExpression = (BoundPeriodIndexExpression *) expression; + auto index = indexExpression->GetIndex().GetHash(); + auto indexable = this->EvaluateExpression(indexExpression->GetIndexableExpression()); + return indexable->IndexValue(index)->Clone(); + } + + const shared_ptr Evaluator::EvaluateNumericTableExpression(const BoundExpression *expression) { + auto tableExpression = (BoundNumericalTableExpression *) expression; + auto valueExpressions = tableExpression->GetExpressions(); + auto values = new unordered_map>(valueExpressions->size()); + for (int i = 0; i < valueExpressions->size(); i++) { + auto val = this->EvaluateExpression(valueExpressions->at(i)); + values->insert({i + 1, val}); + } + auto valuesPointer = shared_ptr>>(values); + return make_shared(valuesPointer); + } + + const shared_ptr Evaluator::EvaluateComplexTableExpression(const BoundExpression *expression) { + auto tableExpression = (BoundTableExpression *) expression; + auto type = dynamic_pointer_cast(tableExpression->GetType()); + auto declaredVars = type->GetValues(); + auto variables = make_shared>>(declaredVars->size()); + for (auto i : *declaredVars) { + variables->insert({i.first, nullptr}); + } + auto evaluator = make_shared(variables.get(), type->GetLocalVariableCount()); + auto currentEvaluator = this->_evaluationScope; + this->_evaluationScope = evaluator; + this->EvaluateBlockStatement(tableExpression->GetBlock()); + this->_evaluationScope = currentEvaluator; + return make_shared(variables); + } + + const shared_ptr Evaluator::EvaluateUserDataExpression(const BoundExpression *expression) { + switch (expression->GetKind()) { + case BoundExpressionKind::Variable: + return this->GetVariable((BoundVariableExpression *) expression); + case BoundExpressionKind::Index: + return this->EvaluateIndexExpression(expression); + default: + throw; + } + } +} \ No newline at end of file diff --git a/src/Evaluator/Evaluator.hpp b/src/Evaluator/Evaluator.hpp index e413a58..dfe1a81 100644 --- a/src/Evaluator/Evaluator.hpp +++ b/src/Evaluator/Evaluator.hpp @@ -4,7 +4,6 @@ #include #include "../Binder/BoundStatements/BoundStatement.hpp" -#include "../Script.hpp" #include "EvalValues/EvalValue.hpp" #include "EvalValues/NumericEvalValue.hpp" #include "EvalValues/StringEvalValue.hpp" @@ -14,62 +13,65 @@ using namespace std; -class Evaluator { - shared_ptr _returnValue; - bool _hasReturned; - shared_ptr _lastValue; +namespace Porygon::Evaluation{ + class Evaluator { + shared_ptr _returnValue; + unordered_map>* _scriptVariables; + bool _hasReturned; + shared_ptr _lastValue; - Script* _scriptData; - shared_ptr _evaluationScope; + //Porygon::Script* _scriptData; + shared_ptr _evaluationScope; - void EvaluateStatement(const BoundStatement* statement); - void EvaluateBlockStatement(const BoundBlockStatement *statement); - void EvaluateExpressionStatement(const BoundExpressionStatement* statement); - void EvaluateAssignmentStatement(const BoundAssignmentStatement* statement); - void EvaluateIndexAssignmentStatement(const BoundIndexAssignmentStatement* statement); - void EvaluateFunctionDeclarationStatement(const BoundFunctionDeclarationStatement *statement); - void EvaluateReturnStatement(const BoundReturnStatement *statement); - void EvaluateConditionalStatement(const BoundConditionalStatement *statement); + void EvaluateStatement(const BoundStatement* statement); + void EvaluateBlockStatement(const BoundBlockStatement *statement); + void EvaluateExpressionStatement(const BoundExpressionStatement* statement); + void EvaluateAssignmentStatement(const BoundAssignmentStatement* statement); + void EvaluateIndexAssignmentStatement(const BoundIndexAssignmentStatement* statement); + void EvaluateFunctionDeclarationStatement(const BoundFunctionDeclarationStatement *statement); + void EvaluateReturnStatement(const BoundReturnStatement *statement); + void EvaluateConditionalStatement(const BoundConditionalStatement *statement); - const shared_ptr EvaluateExpression(const BoundExpression *expression); - const shared_ptr EvaluateIntegerExpression(const BoundExpression *expression); - const shared_ptr EvaluateBoolExpression(const BoundExpression *expression); - const shared_ptr EvaluateStringExpression(const BoundExpression *expression); - const shared_ptr EvaluateFunctionExpression(const BoundExpression *expression); - const shared_ptr EvaluateNilExpression(const BoundExpression *expression); - const shared_ptr EvaluateTableExpression(const BoundExpression *expression); + const shared_ptr EvaluateExpression(const BoundExpression *expression); + const shared_ptr EvaluateIntegerExpression(const BoundExpression *expression); + const shared_ptr EvaluateBoolExpression(const BoundExpression *expression); + const shared_ptr EvaluateStringExpression(const BoundExpression *expression); + const shared_ptr EvaluateFunctionExpression(const BoundExpression *expression); + const shared_ptr EvaluateNilExpression(const BoundExpression *expression); + const shared_ptr EvaluateTableExpression(const BoundExpression *expression); - const shared_ptr EvaluateIntegerBinary(const BoundBinaryExpression *expression); - const shared_ptr EvaluateBooleanBinary(const BoundBinaryExpression *expression); - const shared_ptr EvaluateStringBinary(const BoundBinaryExpression *expression); + const shared_ptr EvaluateIntegerBinary(const BoundBinaryExpression *expression); + const shared_ptr EvaluateBooleanBinary(const BoundBinaryExpression *expression); + const shared_ptr EvaluateStringBinary(const BoundBinaryExpression *expression); - const shared_ptr EvaluateIntegerUnary(const BoundUnaryExpression *expression); - const shared_ptr EvaluateBooleanUnary(const BoundUnaryExpression *expression); - const shared_ptr EvaluateFunctionCallExpression(const BoundExpression *expression); - const shared_ptr EvaluateIndexExpression(const BoundExpression *expression); - const shared_ptr EvaluatePeriodIndexExpression(const BoundExpression *expression); - const shared_ptr EvaluateNumericTableExpression(const BoundExpression *expression); - const shared_ptr EvaluateComplexTableExpression(const BoundExpression *expression); - const shared_ptr EvaluateUserDataExpression(const BoundExpression *expression); + const shared_ptr EvaluateIntegerUnary(const BoundUnaryExpression *expression); + const shared_ptr EvaluateBooleanUnary(const BoundUnaryExpression *expression); + const shared_ptr EvaluateFunctionCallExpression(const BoundExpression *expression); + const shared_ptr EvaluateIndexExpression(const BoundExpression *expression); + const shared_ptr EvaluatePeriodIndexExpression(const BoundExpression *expression); + const shared_ptr EvaluateNumericTableExpression(const BoundExpression *expression); + const shared_ptr EvaluateComplexTableExpression(const BoundExpression *expression); + const shared_ptr EvaluateUserDataExpression(const BoundExpression *expression); - const shared_ptr GetVariable(const BoundVariableExpression *expression); -public: - explicit Evaluator(Script* script){ - _scriptData = script; - _hasReturned = false; - _returnValue = nullptr; - _evaluationScope = nullptr; - } + const shared_ptr GetVariable(const BoundVariableExpression *expression); + public: + explicit Evaluator(unordered_map>* scriptVariables){ + _scriptVariables = scriptVariables; + _hasReturned = false; + _returnValue = nullptr; + _evaluationScope = nullptr; + } - EvalValue* Evaluate(const BoundScriptStatement* statement); - const shared_ptr EvaluateFunction(const ScriptFunctionEvalValue *function, - const vector ¶meters); + EvalValue* Evaluate(const BoundScriptStatement* statement); + const shared_ptr EvaluateFunction(const ScriptFunctionEvalValue *function, + const vector ¶meters); - EvalValue* GetLastValue(){ - return _lastValue.get(); - } + EvalValue* GetLastValue(){ + return _lastValue.get(); + } -}; + }; +} diff --git a/src/Evaluator/UnaryEvaluation.cpp b/src/Evaluator/UnaryEvaluation.cpp index 123a475..f362a8f 100644 --- a/src/Evaluator/UnaryEvaluation.cpp +++ b/src/Evaluator/UnaryEvaluation.cpp @@ -4,33 +4,33 @@ #include "EvaluationException.hpp" #include "../Script.hpp" -const shared_ptr Evaluator::EvaluateIntegerUnary(const BoundUnaryExpression *expression) { - switch (expression->GetOperation()){ - case BoundUnaryOperation::Negation: - { - auto operandValue = EvaluateIntegerExpression(expression->GetOperand()); - if (operandValue->IsFloat()){ - double f = operandValue->EvaluateFloat(); - return make_shared(-f); - } else{ - long l = operandValue->EvaluateInteger(); - return make_shared(-l); +namespace Porygon::Evaluation { + const shared_ptr Evaluator::EvaluateIntegerUnary(const BoundUnaryExpression *expression) { + switch (expression->GetOperation()) { + case BoundUnaryOperation::Negation: { + auto operandValue = EvaluateIntegerExpression(expression->GetOperand()); + if (operandValue->IsFloat()) { + double f = operandValue->EvaluateFloat(); + return make_shared(-f); + } else { + long l = operandValue->EvaluateInteger(); + return make_shared(-l); + } } + case BoundUnaryOperation::LogicalNegation: + throw; } - case BoundUnaryOperation::LogicalNegation: - throw; } -} -const shared_ptr Evaluator::EvaluateBooleanUnary(const BoundUnaryExpression *expression) { - switch (expression->GetOperation()){ - case BoundUnaryOperation::LogicalNegation: - { - auto val = EvaluateBoolExpression(expression->GetOperand()); - bool b = val->EvaluateBool(); - return make_shared(!b); + const shared_ptr Evaluator::EvaluateBooleanUnary(const BoundUnaryExpression *expression) { + switch (expression->GetOperation()) { + case BoundUnaryOperation::LogicalNegation: { + auto val = EvaluateBoolExpression(expression->GetOperand()); + bool b = val->EvaluateBool(); + return make_shared(!b); + } + case BoundUnaryOperation::Negation: + throw; } - case BoundUnaryOperation::Negation: - throw; } } diff --git a/src/Parser/BinaryOperatorKind.hpp b/src/Parser/BinaryOperatorKind.hpp index 5de5087..7a1ba5b 100644 --- a/src/Parser/BinaryOperatorKind.hpp +++ b/src/Parser/BinaryOperatorKind.hpp @@ -1,23 +1,26 @@ #ifndef PORYGONLANG_BINARYOPERATORKIND_HPP #define PORYGONLANG_BINARYOPERATORKIND_HPP -enum class BinaryOperatorKind{ - // Math - Addition, - Subtraction, - Multiplication, - Division, - // Equality - Equality, - Inequality, - Less, - LessOrEquals, - Greater, - GreaterOrEquals, +namespace Porygon::Parser { + enum class BinaryOperatorKind { + // Math + Addition, + Subtraction, + Multiplication, + Division, - // Logical - LogicalAnd, - LogicalOr, -}; + // Equality + Equality, + Inequality, + Less, + LessOrEquals, + Greater, + GreaterOrEquals, + + // Logical + LogicalAnd, + LogicalOr, + }; +} #endif //PORYGONLANG_BINARYOPERATORKIND_HPP diff --git a/src/Parser/Lexer.cpp b/src/Parser/Lexer.cpp index a4a7ffb..b083dd1 100644 --- a/src/Parser/Lexer.cpp +++ b/src/Parser/Lexer.cpp @@ -5,270 +5,313 @@ #include "Lexer.hpp" -Lexer::Lexer(const u16string& scriptString, class Script* script) - : _scriptString(scriptString) -{ - this->_scriptSize = scriptString.size(); - this -> ScriptData = script; - this -> _position = 0; -} - - -vector Lexer::Lex() { - vector tokens; - while (true){ - IToken* next = this -> LexNext(this -> Next()); - auto nextKind = next -> GetKind(); - if (nextKind != TokenKind::WhiteSpace) - tokens.push_back(next); - else - delete next; - if (nextKind == TokenKind::EndOfFile) - break; +namespace Porygon::Parser { + Lexer::Lexer(const u16string &scriptString, Porygon::Script *script) + : _scriptString(scriptString) { + this->_scriptSize = scriptString.size(); + this->ScriptData = script; + this->_position = 0; } - return tokens; -} -char16_t Lexer::Peek(){ - if (Lexer::_position >= this -> _scriptSize) - return '\0'; - return this -> _scriptString.at(Lexer::_position); -} -char16_t Lexer::Next(){ - char16_t next = Peek(); - Lexer::_position++; - return next; -} + vector Lexer::Lex() { + vector tokens; + while (true) { + IToken *next = this->LexNext(this->Next()); + auto nextKind = next->GetKind(); + if (nextKind != TokenKind::WhiteSpace) + tokens.push_back(next); + else + delete next; + if (nextKind == TokenKind::EndOfFile) + break; + } + return tokens; + } -IToken* Lexer::LexNext(char16_t c){ - switch (c) { - case '\0': - return new SimpleToken(TokenKind::EndOfFile, this -> _position - 1, 1); - case ' ': case '\t': case '\n': case '\r': case '\v': case '\f': - return new SimpleToken(TokenKind::WhiteSpace, this -> _position - 1, 1); - case '+': - return new SimpleToken(TokenKind::PlusToken, this -> _position - 1, 1); - case '-': - return new SimpleToken(TokenKind::MinusToken, this -> _position - 1, 1); - case '/': - return new SimpleToken(TokenKind::SlashToken, this -> _position - 1, 1); - case '*': - return new SimpleToken(TokenKind::StarToken, this -> _position - 1, 1); - case '(': - return new SimpleToken(TokenKind::OpenParenthesis, this -> _position - 1, 1); - case ')': - return new SimpleToken(TokenKind::CloseParenthesis, this -> _position - 1, 1); - case '[': - return new SimpleToken(TokenKind::OpenSquareBracket, this -> _position - 1, 1); - case ']': - return new SimpleToken(TokenKind::CloseSquareBracket, this -> _position - 1, 1); - case '{': - return new SimpleToken(TokenKind::OpenCurlyBracket, this -> _position - 1, 1); - case '}': - return new SimpleToken(TokenKind::CloseCurlyBracket, this -> _position - 1, 1); - case ',': - return new SimpleToken(TokenKind::CommaToken, this -> _position - 1, 1); - case '.': - return new SimpleToken(TokenKind::PeriodToken, this -> _position - 1, 1); - case '=': - if (Lexer::Peek() == '='){ - Lexer::Next(); - return new SimpleToken(TokenKind::EqualityToken, this -> _position - 2, 2); - } - return new SimpleToken(TokenKind::AssignmentToken, this -> _position - 1, 1); - case '<': - if (Lexer::Peek() == '='){ - Lexer::Next(); - return new SimpleToken(TokenKind::LessEquals, this -> _position - 2, 2); - } - return new SimpleToken(TokenKind::Less, this -> _position - 1, 1); - case '>': - if (Lexer::Peek() == '='){ - Lexer::Next(); - return new SimpleToken(TokenKind::GreaterEquals, this -> _position - 2, 2); - } - return new SimpleToken(TokenKind::Greater, this -> _position - 1, 1); - case '~': - if (Lexer::Peek() == '='){ - Lexer::Next(); - return new SimpleToken(TokenKind::InequalityToken, this -> _position - 2, 2); - } - this -> ScriptData -> Diagnostics -> LogError(DiagnosticCode::UnexpectedCharacter, this -> _position - 1, 1); - return new SimpleToken(TokenKind::BadToken, this -> _position - 1, 1); - case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - return LexNumber(c); - case '"': - return LexString(c); - case '\'': - return LexString(c); - case '_': - return LexIdentifierOrKeyword(); - default: - if (isalpha(c) || c > 255){ + char16_t Lexer::Peek() { + if (Lexer::_position >= this->_scriptSize) + return '\0'; + return this->_scriptString.at(Lexer::_position); + } + + char16_t Lexer::Next() { + char16_t next = Peek(); + Lexer::_position++; + return next; + } + + IToken *Lexer::LexNext(char16_t c) { + switch (c) { + case '\0': + return new SimpleToken(TokenKind::EndOfFile, this->_position - 1, 1); + case ' ': + case '\t': + case '\n': + case '\r': + case '\v': + case '\f': + return new SimpleToken(TokenKind::WhiteSpace, this->_position - 1, 1); + case '+': + return new SimpleToken(TokenKind::PlusToken, this->_position - 1, 1); + case '-': + return new SimpleToken(TokenKind::MinusToken, this->_position - 1, 1); + case '/': + return new SimpleToken(TokenKind::SlashToken, this->_position - 1, 1); + case '*': + return new SimpleToken(TokenKind::StarToken, this->_position - 1, 1); + case '(': + return new SimpleToken(TokenKind::OpenParenthesis, this->_position - 1, 1); + case ')': + return new SimpleToken(TokenKind::CloseParenthesis, this->_position - 1, 1); + case '[': + return new SimpleToken(TokenKind::OpenSquareBracket, this->_position - 1, 1); + case ']': + return new SimpleToken(TokenKind::CloseSquareBracket, this->_position - 1, 1); + case '{': + return new SimpleToken(TokenKind::OpenCurlyBracket, this->_position - 1, 1); + case '}': + return new SimpleToken(TokenKind::CloseCurlyBracket, this->_position - 1, 1); + case ',': + return new SimpleToken(TokenKind::CommaToken, this->_position - 1, 1); + case '.': + return new SimpleToken(TokenKind::PeriodToken, this->_position - 1, 1); + case '=': + if (Lexer::Peek() == '=') { + Lexer::Next(); + return new SimpleToken(TokenKind::EqualityToken, this->_position - 2, 2); + } + return new SimpleToken(TokenKind::AssignmentToken, this->_position - 1, 1); + case '<': + if (Lexer::Peek() == '=') { + Lexer::Next(); + return new SimpleToken(TokenKind::LessEquals, this->_position - 2, 2); + } + return new SimpleToken(TokenKind::Less, this->_position - 1, 1); + case '>': + if (Lexer::Peek() == '=') { + Lexer::Next(); + return new SimpleToken(TokenKind::GreaterEquals, this->_position - 2, 2); + } + return new SimpleToken(TokenKind::Greater, this->_position - 1, 1); + case '~': + if (Lexer::Peek() == '=') { + Lexer::Next(); + return new SimpleToken(TokenKind::InequalityToken, this->_position - 2, 2); + } + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedCharacter, this->_position - 1, 1); + return new SimpleToken(TokenKind::BadToken, this->_position - 1, 1); + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return LexNumber(c); + case '"': + return LexString(c); + case '\'': + return LexString(c); + case '_': return LexIdentifierOrKeyword(); - } - this -> ScriptData -> Diagnostics -> LogError(DiagnosticCode::UnexpectedCharacter, this -> _position - 1, 1); - return new SimpleToken(TokenKind::BadToken, this -> _position - 1, 1); - } -} - -int CharToInt(char16_t c){ - switch (c){ - case '0': return 0; - case '1': return 1; - case '2': return 2; - case '3': return 3; - case '4': return 4; - case '5': return 5; - case '6': return 6; - case '7': return 7; - case '8': return 8; - case '9': return 9; - default: return -1; - } -} - -IToken* Lexer::LexNumber(char16_t c){ - long int_value = CharToInt(c); - double float_value = 0; - short decimal_index = 0; - bool has_point = false; - bool is_searching = true; - unsigned int start = this -> _position - 1; - unsigned int length = 1; - while (is_searching){ - char16_t next = this -> Peek(); - int next_val = CharToInt(next); - if (next_val == -1){ - switch (next){ - case '_': - this -> Next(); - length++; - continue; - case '.': - this -> Next(); - has_point = true; - decimal_index = 0; - float_value = int_value; - length++; - continue; - default: - is_searching = false; - continue; - } - } - else{ - this -> Next(); - length++; - if (has_point){ - decimal_index++; - float_value += next_val / pow(10, decimal_index); - } - else { - int_value *= 10; - int_value += next_val; - } + default: + if (isalpha(c) || c > 255) { + return LexIdentifierOrKeyword(); + } + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedCharacter, this->_position - 1, 1); + return new SimpleToken(TokenKind::BadToken, this->_position - 1, 1); } } - if (has_point){ - return new FloatToken(float_value, start, length); - } - else{ - return new IntegerToken(int_value, start, length); - } -} -IToken * Lexer::LexIdentifierOrKeyword() { - auto start = this -> _position - 1; - auto end = start; - while (true){ - char16_t next = this -> Peek(); - if (next == '\0') break; - if (isalpha(next) || next == '_' || next > 255){ - this -> Next(); + int CharToInt(char16_t c) { + switch (c) { + case '0': + return 0; + case '1': + return 1; + case '2': + return 2; + case '3': + return 3; + case '4': + return 4; + case '5': + return 5; + case '6': + return 6; + case '7': + return 7; + case '8': + return 8; + case '9': + return 9; + default: + return -1; + } + } + + IToken *Lexer::LexNumber(char16_t c) { + long int_value = CharToInt(c); + double float_value = 0; + short decimal_index = 0; + bool has_point = false; + bool is_searching = true; + unsigned int start = this->_position - 1; + unsigned int length = 1; + while (is_searching) { + char16_t next = this->Peek(); + int next_val = CharToInt(next); + if (next_val == -1) { + switch (next) { + case '_': + this->Next(); + length++; + continue; + case '.': + this->Next(); + has_point = true; + decimal_index = 0; + float_value = int_value; + length++; + continue; + default: + is_searching = false; + continue; + } + } else { + this->Next(); + length++; + if (has_point) { + decimal_index++; + float_value += next_val / pow(10, decimal_index); + } else { + int_value *= 10; + int_value += next_val; + } + } + } + if (has_point) { + return new FloatToken(float_value, start, length); + } else { + return new IntegerToken(int_value, start, length); + } + } + + IToken *Lexer::LexIdentifierOrKeyword() { + auto start = this->_position - 1; + auto end = start; + while (true) { + char16_t next = this->Peek(); + if (next == '\0') break; + if (isalpha(next) || next == '_' || next > 255) { + this->Next(); + end++; + } else { + break; + } + } + + u16string s = this->_scriptString.substr(start, end - start + 1); + switch (HashedString::ConstHash(s.c_str())) { + case HashedString::ConstHash("and"): + return new SimpleToken(TokenKind::AndKeyword, start, 3); + case HashedString::ConstHash("break"): + return new SimpleToken(TokenKind::BreakKeyword, start, 5); + case HashedString::ConstHash("do"): + return new SimpleToken(TokenKind::DoKeyword, start, 2); + case HashedString::ConstHash("else"): + return new SimpleToken(TokenKind::ElseKeyword, start, 4); + case HashedString::ConstHash("elseif"): + return new SimpleToken(TokenKind::ElseIfKeyword, start, 6); + case HashedString::ConstHash("end"): + return new SimpleToken(TokenKind::EndKeyword, start, 3); + case HashedString::ConstHash("false"): + return new SimpleToken(TokenKind::FalseKeyword, start, 5); + case HashedString::ConstHash("for"): + return new SimpleToken(TokenKind::ForKeyword, start, 3); + case HashedString::ConstHash("function"): + return new SimpleToken(TokenKind::FunctionKeyword, start, 8); + case HashedString::ConstHash("if"): + return new SimpleToken(TokenKind::IfKeyword, start, 2); + case HashedString::ConstHash("in"): + return new SimpleToken(TokenKind::InKeyword, start, 2); + case HashedString::ConstHash("local"): + return new SimpleToken(TokenKind::LocalKeyword, start, 5); + case HashedString::ConstHash("nil"): + return new SimpleToken(TokenKind::NilKeyword, start, 3); + case HashedString::ConstHash("not"): + return new SimpleToken(TokenKind::NotKeyword, start, 3); + case HashedString::ConstHash("or"): + return new SimpleToken(TokenKind::OrKeyword, start, 2); + case HashedString::ConstHash("return"): + return new SimpleToken(TokenKind::ReturnKeyword, start, 6); + case HashedString::ConstHash("then"): + return new SimpleToken(TokenKind::ThenKeyword, start, 4); + case HashedString::ConstHash("true"): + return new SimpleToken(TokenKind::TrueKeyword, start, 4); + case HashedString::ConstHash("while"): + return new SimpleToken(TokenKind::WhileKeyword, start, 5); + default: + return new IdentifierToken(HashedString(s), start, s.length()); + } + } + + const unordered_map ControlCharacters{ // NOLINT(cert-err58-cpp) + {'0', '\0'}, + {'a', '\a'}, + {'b', '\b'}, + {'t', '\t'}, + {'n', '\n'}, + {'v', '\v'}, + {'f', '\f'}, + {'r', '\r'}, + {'"', '\"'}, + {'\'', '\''}, + {'\?', '\?'}, + {'\\', '\\'}, + }; + + IToken *Lexer::LexString(char16_t c) { + auto start = this->_position - 1; + auto end = start; + char16_t last = c; + while (true) { + char16_t next = this->Peek(); + if (next == '\0') break; + if (next == c && last != '\\') break; + this->Next(); end++; + last = next; } - else{ - break; + auto closeToken = this->Next(); + if (closeToken != c) { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedCharacter, this->_position - 1, 1); + return new SimpleToken(TokenKind::BadToken, start, end - start + 1); } - } - u16string s = this -> _scriptString.substr(start, end - start + 1); - switch (HashedString::ConstHash(s.c_str())){ - case HashedString::ConstHash("and"): return new SimpleToken(TokenKind::AndKeyword, start, 3); - case HashedString::ConstHash("break"): return new SimpleToken(TokenKind::BreakKeyword, start, 5); - case HashedString::ConstHash("do"): return new SimpleToken(TokenKind::DoKeyword, start, 2); - case HashedString::ConstHash("else"): return new SimpleToken(TokenKind::ElseKeyword, start, 4); - case HashedString::ConstHash("elseif"): return new SimpleToken(TokenKind::ElseIfKeyword, start, 6); - case HashedString::ConstHash("end"): return new SimpleToken(TokenKind::EndKeyword, start, 3); - case HashedString::ConstHash("false"): return new SimpleToken(TokenKind::FalseKeyword, start, 5); - case HashedString::ConstHash("for"): return new SimpleToken(TokenKind::ForKeyword, start, 3); - case HashedString::ConstHash("function"): return new SimpleToken(TokenKind::FunctionKeyword, start, 8); - case HashedString::ConstHash("if"): return new SimpleToken(TokenKind::IfKeyword, start, 2); - case HashedString::ConstHash("in"): return new SimpleToken(TokenKind::InKeyword, start, 2); - case HashedString::ConstHash("local"): return new SimpleToken(TokenKind::LocalKeyword, start, 5); - case HashedString::ConstHash("nil"): return new SimpleToken(TokenKind::NilKeyword, start, 3); - case HashedString::ConstHash("not"): return new SimpleToken(TokenKind::NotKeyword, start, 3); - case HashedString::ConstHash("or"): return new SimpleToken(TokenKind::OrKeyword, start, 2); - case HashedString::ConstHash("return"): return new SimpleToken(TokenKind::ReturnKeyword, start, 6); - case HashedString::ConstHash("then"): return new SimpleToken(TokenKind::ThenKeyword, start, 4); - case HashedString::ConstHash("true"): return new SimpleToken(TokenKind::TrueKeyword, start, 4); - case HashedString::ConstHash("while"): return new SimpleToken(TokenKind::WhileKeyword, start, 5); - default: return new IdentifierToken(HashedString(s), start, s.length()); - } -} - -const unordered_map ControlCharacters{ // NOLINT(cert-err58-cpp) - {'0', '\0'}, - {'a', '\a'}, - {'b', '\b'}, - {'t', '\t'}, - {'n', '\n'}, - {'v', '\v'}, - {'f', '\f'}, - {'r', '\r'}, - {'"', '\"'}, - {'\'', '\''}, - {'\?', '\?'}, - {'\\', '\\'}, -}; - -IToken* Lexer::LexString(char16_t c){ - auto start = this -> _position - 1; - auto end = start; - char16_t last = c; - while (true){ - char16_t next = this -> Peek(); - if (next == '\0') break; - if (next == c && last != '\\') break; - this -> Next(); - end++; - last = next; - } - auto closeToken = this -> Next(); - if (closeToken != c){ - this -> ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedCharacter, this->_position - 1, 1); - return new SimpleToken(TokenKind::BadToken, start, end -start + 1); - } - - u16string s = this -> _scriptString.substr(start + 1, end - start); - std::basic_ostringstream stream; - for (int i = 0; i < s.size(); i++){ - c = s[i]; - if (c == '\\'){ - i++; + u16string s = this->_scriptString.substr(start + 1, end - start); + std::basic_ostringstream stream; + for (int i = 0; i < s.size(); i++) { c = s[i]; - if (ControlCharacters.find(c) != ControlCharacters.end()) { - stream << ControlCharacters.at(c); - } else{ - this -> ScriptData->Diagnostics->LogError(DiagnosticCode::InvalidStringControlCharacter, start + 1 + i, 1); + if (c == '\\') { + i++; + c = s[i]; + if (ControlCharacters.find(c) != ControlCharacters.end()) { + stream << ControlCharacters.at(c); + } else { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::InvalidStringControlCharacter, + start + 1 + i, 1); + stream << c; + } + } else { stream << c; } - } else{ - stream << c; } + return new StringToken(stream.str(), start, end - start); } - return new StringToken(stream.str(), start, end - start ); -} +} \ No newline at end of file diff --git a/src/Parser/Lexer.hpp b/src/Parser/Lexer.hpp index 366d256..58d1f81 100644 --- a/src/Parser/Lexer.hpp +++ b/src/Parser/Lexer.hpp @@ -7,26 +7,28 @@ using namespace std; -class Lexer { - const u16string& _scriptString; +namespace Porygon::Parser{ + class Lexer { + const u16string& _scriptString; #ifdef TESTS_BUILD -public: + public: #endif - unsigned int _position; - unsigned int _scriptSize; - char16_t Peek(); - char16_t Next(); - IToken* LexNext(char16_t c); - IToken* LexNumber(char16_t c); - IToken* LexIdentifierOrKeyword(); - IToken* LexString(char16_t c); -public: - Script* ScriptData; + unsigned int _position; + unsigned int _scriptSize; + char16_t Peek(); + char16_t Next(); + IToken* LexNext(char16_t c); + IToken* LexNumber(char16_t c); + IToken* LexIdentifierOrKeyword(); + IToken* LexString(char16_t c); + public: + Porygon::Script* ScriptData; - vector Lex(); - explicit Lexer(const u16string& scriptString, class Script* script); + vector Lex(); + explicit Lexer(const u16string& scriptString, Porygon::Script* script); -}; + }; +} #endif //PORYGONLANG_LEXER_HPP diff --git a/src/Parser/ParsedExpressions/ParsedExpression.hpp b/src/Parser/ParsedExpressions/ParsedExpression.hpp index 087c288..3c2e5db 100644 --- a/src/Parser/ParsedExpressions/ParsedExpression.hpp +++ b/src/Parser/ParsedExpressions/ParsedExpression.hpp @@ -11,333 +11,332 @@ #include "../BinaryOperatorKind.hpp" #include "../../Utilities/HashedString.hpp" -enum class ParsedExpressionKind{ - Bad, +namespace Porygon::Parser { + enum class ParsedExpressionKind { + Bad, - LiteralInteger, - LiteralFloat, - LiteralString, - LiteralBool, - Variable, + LiteralInteger, + LiteralFloat, + LiteralString, + LiteralBool, + Variable, - Unary, - Binary, - Parenthesized, - FunctionCall, - Indexer, - PeriodIndexer, - NumericalTable, - Table, -}; + Unary, + Binary, + Parenthesized, + FunctionCall, + Indexer, + PeriodIndexer, + NumericalTable, + Table, + }; -class ParsedExpression { - const unsigned int _position; - const unsigned int _length; -public: - ParsedExpression(unsigned int position, unsigned int length) - : _position(position), - _length(length) - { - } - - virtual ~ParsedExpression() = default; - - virtual const ParsedExpressionKind GetKind() const = 0; - - const unsigned int GetStartPosition() const{ - return _position; - } - - const unsigned int GetEndPosition() const{ - return _position + _length - 1; - } - - const unsigned int GetLength() const{ - return _length; - } -}; - -class BadExpression : public ParsedExpression{ -public: - BadExpression(unsigned int position, unsigned int length) : ParsedExpression(position, length){} - - const ParsedExpressionKind GetKind() const final { - return ParsedExpressionKind::Bad; - } -}; - -class LiteralIntegerExpression : public ParsedExpression{ - const long _value; -public: - const ParsedExpressionKind GetKind() const final{ - return ParsedExpressionKind::LiteralInteger; - } - explicit LiteralIntegerExpression(IntegerToken* token) - : ParsedExpression(token -> GetStartPosition(), token -> GetLength()), - _value(token -> GetValue()) - { - } - - const long GetValue() const{ - return _value; - } -}; - -class LiteralFloatExpression : public ParsedExpression{ - const double _value; -public: - const ParsedExpressionKind GetKind() const final{ - return ParsedExpressionKind::LiteralFloat; - } - explicit LiteralFloatExpression(FloatToken* token) - : ParsedExpression(token -> GetStartPosition(), token -> GetLength()), - _value(token -> GetValue()) - { - } - - const double GetValue() const{ - return _value; - } -}; - -class LiteralStringExpression : public ParsedExpression{ - const u16string _value; -public: - const ParsedExpressionKind GetKind() const final{ - return ParsedExpressionKind::LiteralString; - } - explicit LiteralStringExpression(StringToken* token) - : ParsedExpression(token -> GetStartPosition(), token -> GetLength()), - _value(std::move(token -> GetValue())) - { - } - - const u16string& GetValue() const{ - return _value; - } -}; - -class LiteralBoolExpression : public ParsedExpression{ - const bool _value; -public: - const ParsedExpressionKind GetKind() const final{ - return ParsedExpressionKind::LiteralBool; - } - explicit LiteralBoolExpression(const IToken* token) - : ParsedExpression(token -> GetStartPosition(), token -> GetLength()), - _value(token -> GetKind() == TokenKind::TrueKeyword) - { - } - - const bool GetValue() const{ - return _value; - } -}; - -class VariableExpression : public ParsedExpression{ - const HashedString _value; -public: - const ParsedExpressionKind GetKind() const final{ - return ParsedExpressionKind::Variable; - } - explicit VariableExpression(IdentifierToken* token) : ParsedExpression(token -> GetStartPosition(), token -> GetLength()) - , _value(HashedString(token -> GetValue())) - { - } - - const HashedString GetValue() const{ - return _value; - } -}; - - -class ParenthesizedExpression : public ParsedExpression{ - const ParsedExpression* _expression; -public: - ~ParenthesizedExpression() override { - delete _expression; - } - - const ParsedExpressionKind GetKind() const final{ - return ParsedExpressionKind::Parenthesized; - } - - explicit ParenthesizedExpression(ParsedExpression* innerExpression, unsigned int start, unsigned int length) - : ParsedExpression(start, length), _expression(innerExpression){ - } - - const ParsedExpression* GetInnerExpression() const{ - return _expression; - } -}; - -class UnaryExpression : public ParsedExpression{ - const UnaryOperatorKind _kind; - const ParsedExpression* _operand; -public: - ~UnaryExpression() override { - delete _operand; - } - - const ParsedExpressionKind GetKind() const final{ - return ParsedExpressionKind::Unary; - } - - UnaryExpression(UnaryOperatorKind kind, ParsedExpression* operand, unsigned int start, unsigned int length) - : ParsedExpression(start, length), - _kind(kind), _operand(operand) - { - } - - const UnaryOperatorKind GetOperatorKind() const{ - return _kind; - } - - const ParsedExpression* GetOperand() const{ - return _operand; - } -}; - -class BinaryExpression : public ParsedExpression{ - const BinaryOperatorKind _kind; - const ParsedExpression* _left; - const ParsedExpression* _right; -public: - ~BinaryExpression() override { - delete _left; - delete _right; - } - - const ParsedExpressionKind GetKind() const final{ - return ParsedExpressionKind::Binary; - } - - BinaryExpression(BinaryOperatorKind kind, ParsedExpression* left, ParsedExpression* right, unsigned int start, - unsigned int length) - : ParsedExpression(start, length), - _kind(kind), _left(left), _right(right) - { - } - - const BinaryOperatorKind GetOperatorKind() const{ - return _kind; - } - - const ParsedExpression* GetLeft() const{ - return _left; - } - - const ParsedExpression* GetRight() const{ - return _right; - } -}; - -class FunctionCallExpression : public ParsedExpression{ - const std::unique_ptr _function; - const vector _parameters; -public: - FunctionCallExpression(ParsedExpression* function, vector parameters, unsigned int start, unsigned int length) - : ParsedExpression(start, length), - _function(function), _parameters(std::move(parameters)) - { - } - - ~FunctionCallExpression() final{ - for (auto p : _parameters){ - delete p; + class ParsedExpression { + const unsigned int _position; + const unsigned int _length; + public: + ParsedExpression(unsigned int position, unsigned int length) + : _position(position), + _length(length) { } - } - const ParsedExpressionKind GetKind() const final{ - return ParsedExpressionKind::FunctionCall; - } + virtual ~ParsedExpression() = default; - const ParsedExpression* GetFunction() const{ - return _function.get(); - } - const vector* GetParameters() const{ - return &_parameters; - } -}; + virtual const ParsedExpressionKind GetKind() const = 0; -class IndexExpression : public ParsedExpression{ - const ParsedExpression* _indexerExpression; - const ParsedExpression* _indexExpression; -public: - IndexExpression(ParsedExpression* indexer, ParsedExpression* index, unsigned int start, unsigned int length) - :ParsedExpression(start, length), - _indexerExpression(indexer), _indexExpression(index) - { - } - - ~IndexExpression() final{ - delete _indexerExpression; - delete _indexExpression; - } - - const ParsedExpressionKind GetKind() const final{ - return ParsedExpressionKind::Indexer; - } - - const ParsedExpression* GetIndexer() const{ - return _indexerExpression; - } - - const ParsedExpression* GetIndex() const{ - return _indexExpression; - } -}; - -class PeriodIndexExpression : public ParsedExpression{ - const ParsedExpression* _indexerExpression; - const HashedString _index; -public: - PeriodIndexExpression(ParsedExpression* indexer, HashedString index, unsigned int start, unsigned int length) - :ParsedExpression(start, length), - _indexerExpression(indexer), _index(index) - { - } - - ~PeriodIndexExpression() final{ - delete _indexerExpression; - } - - const ParsedExpressionKind GetKind() const final{ - return ParsedExpressionKind::PeriodIndexer; - } - - const ParsedExpression* GetIndexer() const{ - return _indexerExpression; - } - - const HashedString& GetIndex() const{ - return _index; - } -}; - - -class ParsedNumericalTableExpression : public ParsedExpression{ - vector _expressions; -public: - ParsedNumericalTableExpression(vector expressions, unsigned int start, unsigned int length) - : ParsedExpression(start, length){ - _expressions = std::move(expressions); - } - - ~ParsedNumericalTableExpression() final{ - for (auto s: _expressions){ - delete s; + const unsigned int GetStartPosition() const { + return _position; } - } - const vector* GetExpressions() const{ - return &_expressions; - } + const unsigned int GetEndPosition() const { + return _position + _length - 1; + } - const ParsedExpressionKind GetKind() const final{ - return ParsedExpressionKind::NumericalTable; - } -}; + const unsigned int GetLength() const { + return _length; + } + }; + class BadExpression : public ParsedExpression { + public: + BadExpression(unsigned int position, unsigned int length) : ParsedExpression(position, length) {} + + const ParsedExpressionKind GetKind() const final { + return ParsedExpressionKind::Bad; + } + }; + + class LiteralIntegerExpression : public ParsedExpression { + const long _value; + public: + const ParsedExpressionKind GetKind() const final { + return ParsedExpressionKind::LiteralInteger; + } + + explicit LiteralIntegerExpression(IntegerToken *token) + : ParsedExpression(token->GetStartPosition(), token->GetLength()), + _value(token->GetValue()) { + } + + const long GetValue() const { + return _value; + } + }; + + class LiteralFloatExpression : public ParsedExpression { + const double _value; + public: + const ParsedExpressionKind GetKind() const final { + return ParsedExpressionKind::LiteralFloat; + } + + explicit LiteralFloatExpression(FloatToken *token) + : ParsedExpression(token->GetStartPosition(), token->GetLength()), + _value(token->GetValue()) { + } + + const double GetValue() const { + return _value; + } + }; + + class LiteralStringExpression : public ParsedExpression { + const u16string _value; + public: + const ParsedExpressionKind GetKind() const final { + return ParsedExpressionKind::LiteralString; + } + + explicit LiteralStringExpression(StringToken *token) + : ParsedExpression(token->GetStartPosition(), token->GetLength()), + _value(std::move(token->GetValue())) { + } + + const u16string &GetValue() const { + return _value; + } + }; + + class LiteralBoolExpression : public ParsedExpression { + const bool _value; + public: + const ParsedExpressionKind GetKind() const final { + return ParsedExpressionKind::LiteralBool; + } + + explicit LiteralBoolExpression(const IToken *token) + : ParsedExpression(token->GetStartPosition(), token->GetLength()), + _value(token->GetKind() == TokenKind::TrueKeyword) { + } + + const bool GetValue() const { + return _value; + } + }; + + class VariableExpression : public ParsedExpression { + const HashedString _value; + public: + const ParsedExpressionKind GetKind() const final { + return ParsedExpressionKind::Variable; + } + + explicit VariableExpression(IdentifierToken *token) : ParsedExpression(token->GetStartPosition(), + token->GetLength()), + _value(HashedString(token->GetValue())) { + } + + const HashedString GetValue() const { + return _value; + } + }; + + + class ParenthesizedExpression : public ParsedExpression { + const ParsedExpression *_expression; + public: + ~ParenthesizedExpression() override { + delete _expression; + } + + const ParsedExpressionKind GetKind() const final { + return ParsedExpressionKind::Parenthesized; + } + + explicit ParenthesizedExpression(ParsedExpression *innerExpression, unsigned int start, unsigned int length) + : ParsedExpression(start, length), _expression(innerExpression) { + } + + const ParsedExpression *GetInnerExpression() const { + return _expression; + } + }; + + class UnaryExpression : public ParsedExpression { + const UnaryOperatorKind _kind; + const ParsedExpression *_operand; + public: + ~UnaryExpression() override { + delete _operand; + } + + const ParsedExpressionKind GetKind() const final { + return ParsedExpressionKind::Unary; + } + + UnaryExpression(UnaryOperatorKind kind, ParsedExpression *operand, unsigned int start, unsigned int length) + : ParsedExpression(start, length), + _kind(kind), _operand(operand) { + } + + const UnaryOperatorKind GetOperatorKind() const { + return _kind; + } + + const ParsedExpression *GetOperand() const { + return _operand; + } + }; + + class BinaryExpression : public ParsedExpression { + const BinaryOperatorKind _kind; + const ParsedExpression *_left; + const ParsedExpression *_right; + public: + ~BinaryExpression() override { + delete _left; + delete _right; + } + + const ParsedExpressionKind GetKind() const final { + return ParsedExpressionKind::Binary; + } + + BinaryExpression(BinaryOperatorKind kind, ParsedExpression *left, ParsedExpression *right, unsigned int start, + unsigned int length) + : ParsedExpression(start, length), + _kind(kind), _left(left), _right(right) { + } + + const BinaryOperatorKind GetOperatorKind() const { + return _kind; + } + + const ParsedExpression *GetLeft() const { + return _left; + } + + const ParsedExpression *GetRight() const { + return _right; + } + }; + + class FunctionCallExpression : public ParsedExpression { + const std::unique_ptr _function; + const vector _parameters; + public: + FunctionCallExpression(ParsedExpression *function, vector parameters, + unsigned int start, unsigned int length) + : ParsedExpression(start, length), + _function(function), _parameters(std::move(parameters)) { + } + + ~FunctionCallExpression() final { + for (auto p : _parameters) { + delete p; + } + } + + const ParsedExpressionKind GetKind() const final { + return ParsedExpressionKind::FunctionCall; + } + + const ParsedExpression *GetFunction() const { + return _function.get(); + } + + const vector *GetParameters() const { + return &_parameters; + } + }; + + class IndexExpression : public ParsedExpression { + const ParsedExpression *_indexerExpression; + const ParsedExpression *_indexExpression; + public: + IndexExpression(ParsedExpression *indexer, ParsedExpression *index, unsigned int start, unsigned int length) + : ParsedExpression(start, length), + _indexerExpression(indexer), _indexExpression(index) { + } + + ~IndexExpression() final { + delete _indexerExpression; + delete _indexExpression; + } + + const ParsedExpressionKind GetKind() const final { + return ParsedExpressionKind::Indexer; + } + + const ParsedExpression *GetIndexer() const { + return _indexerExpression; + } + + const ParsedExpression *GetIndex() const { + return _indexExpression; + } + }; + + class PeriodIndexExpression : public ParsedExpression { + const ParsedExpression *_indexerExpression; + const HashedString _index; + public: + PeriodIndexExpression(ParsedExpression *indexer, HashedString index, unsigned int start, unsigned int length) + : ParsedExpression(start, length), + _indexerExpression(indexer), _index(index) { + } + + ~PeriodIndexExpression() final { + delete _indexerExpression; + } + + const ParsedExpressionKind GetKind() const final { + return ParsedExpressionKind::PeriodIndexer; + } + + const ParsedExpression *GetIndexer() const { + return _indexerExpression; + } + + const HashedString &GetIndex() const { + return _index; + } + }; + + + class ParsedNumericalTableExpression : public ParsedExpression { + vector _expressions; + public: + ParsedNumericalTableExpression(vector expressions, unsigned int start, + unsigned int length) + : ParsedExpression(start, length) { + _expressions = std::move(expressions); + } + + ~ParsedNumericalTableExpression() final { + for (auto s: _expressions) { + delete s; + } + } + + const vector *GetExpressions() const { + return &_expressions; + } + + const ParsedExpressionKind GetKind() const final { + return ParsedExpressionKind::NumericalTable; + } + }; +} #endif //PORYGONLANG_PARSEDEXPRESSION_HPP diff --git a/src/Parser/ParsedExpressions/ParsedTableExpression.hpp b/src/Parser/ParsedExpressions/ParsedTableExpression.hpp index 3018385..0452e0d 100644 --- a/src/Parser/ParsedExpressions/ParsedTableExpression.hpp +++ b/src/Parser/ParsedExpressions/ParsedTableExpression.hpp @@ -5,27 +5,27 @@ #include "ParsedExpression.hpp" #include "../ParsedStatements/ParsedStatement.hpp" -class ParsedTableExpression : public ParsedExpression{ - const ParsedBlockStatement* _block; -public: - ParsedTableExpression(ParsedBlockStatement* block, unsigned int start, unsigned int length) - : ParsedExpression(start, length), _block(block) - { - } +namespace Porygon::Parser { + class ParsedTableExpression : public ParsedExpression { + const ParsedBlockStatement *_block; + public: + ParsedTableExpression(ParsedBlockStatement *block, unsigned int start, unsigned int length) + : ParsedExpression(start, length), _block(block) { + } - ~ParsedTableExpression() final{ - delete _block; - } + ~ParsedTableExpression() final { + delete _block; + } - const ParsedBlockStatement* GetBlock() const{ - return _block; - } - - const ParsedExpressionKind GetKind() const final{ - return ParsedExpressionKind::Table; - } -}; + const ParsedBlockStatement *GetBlock() const { + return _block; + } + const ParsedExpressionKind GetKind() const final { + return ParsedExpressionKind::Table; + } + }; +} #include "ParsedExpression.hpp" #endif //PORYGONLANG_PARSEDTABLEEXPRESSION_HPP diff --git a/src/Parser/ParsedStatements/ParsedStatement.hpp b/src/Parser/ParsedStatements/ParsedStatement.hpp index 5736e03..1691930 100644 --- a/src/Parser/ParsedStatements/ParsedStatement.hpp +++ b/src/Parser/ParsedStatements/ParsedStatement.hpp @@ -13,263 +13,270 @@ #include "../../Utilities/HashedString.hpp" #include "../TypedVariableIdentifier.hpp" -enum class ParsedStatementKind{ - Bad, - Script, - Block, - Expression, - Assignment, - IndexAssignment, - FunctionDeclaration, - Return, - Conditional -}; +namespace Porygon::Parser { + enum class ParsedStatementKind { + Bad, + Script, + Block, + Expression, + Assignment, + IndexAssignment, + FunctionDeclaration, + Return, + Conditional + }; -class ParsedStatement { - const unsigned int _start; - const unsigned int _length; -public: - ParsedStatement(unsigned int start, unsigned int length) - :_start(start), _length(length) - { - } - virtual ~ParsedStatement() = default; - virtual const ParsedStatementKind GetKind() const = 0; - - const unsigned int GetStartPosition() const { - return _start; - } - - const unsigned int GetLength() const { - return _length; - } - - const unsigned int GetEndPosition() const { - return _start + _length - 1; - } -}; - -class ParsedBadStatement : public ParsedStatement{ -public: - ParsedBadStatement(unsigned int start, unsigned int length) : ParsedStatement(start, length){}; - const ParsedStatementKind GetKind() const final{ - return ParsedStatementKind ::Bad; - } -}; - -class ParsedBlockStatement : public ParsedStatement{ - const std::vector _statements; -public: - explicit ParsedBlockStatement(std::vector statements) - : ParsedStatement(statements.front()->GetStartPosition(), statements.back()->GetEndPosition() - statements.front()->GetStartPosition()), - _statements(statements) - {} - - ParsedBlockStatement(std::vector statements, unsigned int start) : ParsedStatement(start, 0), - _statements(std::move(statements)) - { - } - - - ~ParsedBlockStatement() override { - for (auto s: _statements){ - delete s; + class ParsedStatement { + const unsigned int _start; + const unsigned int _length; + public: + ParsedStatement(unsigned int start, unsigned int length) + : _start(start), _length(length) { } - } - const ParsedStatementKind GetKind() const override { - return ParsedStatementKind ::Block; - } + virtual ~ParsedStatement() = default; - const std::vector* GetStatements() const{ - return &_statements; - } -}; + virtual const ParsedStatementKind GetKind() const = 0; -class ParsedScriptStatement : public ParsedBlockStatement{ -public: - explicit ParsedScriptStatement(vector statements) : ParsedBlockStatement(move(statements)){} - - const ParsedStatementKind GetKind() const final{ - return ParsedStatementKind ::Script; - } -}; - -class ParsedExpressionStatement : public ParsedStatement{ - const ParsedExpression* _expression; -public: - explicit ParsedExpressionStatement(ParsedExpression* expression) - : ParsedStatement(expression->GetStartPosition(), expression->GetLength()), - _expression(expression) - { - } - - ~ParsedExpressionStatement() override { - delete _expression; - } - - const ParsedStatementKind GetKind() const final{ - return ParsedStatementKind ::Expression; - } - - const ParsedExpression* GetExpression() const{ - return _expression; - } -}; - -class ParsedFunctionDeclarationStatement : public ParsedStatement{ - const HashedString _identifier; - const vector _parameters; - const ParsedBlockStatement* _block; -public: - ParsedFunctionDeclarationStatement(HashedString identifier, vector parameters, ParsedBlockStatement* block, - unsigned int start, unsigned int length) - : ParsedStatement(start, length), _identifier(identifier), _parameters(std::move(parameters)), _block(block){}; - - ~ParsedFunctionDeclarationStatement() override { - for (auto v : _parameters){ - delete v; + const unsigned int GetStartPosition() const { + return _start; } - delete _block; - } - const ParsedStatementKind GetKind() const final{ - return ParsedStatementKind ::FunctionDeclaration; - } + const unsigned int GetLength() const { + return _length; + } - const HashedString GetIdentifier() const{ - return _identifier; - } + const unsigned int GetEndPosition() const { + return _start + _length - 1; + } + }; - const vector* GetParameters() const{ - return &_parameters; - } + class ParsedBadStatement : public ParsedStatement { + public: + ParsedBadStatement(unsigned int start, unsigned int length) : ParsedStatement(start, length) {}; - const ParsedBlockStatement* GetBlock() const{ - return _block; - } -}; + const ParsedStatementKind GetKind() const final { + return ParsedStatementKind::Bad; + } + }; -class ParsedAssignmentStatement : public ParsedStatement{ - const bool _local; - const HashedString _identifier; - const ParsedExpression* _expression; -public: - ParsedAssignmentStatement(bool local, const HashedString identifier, ParsedExpression* expression, unsigned int start, unsigned int length) - : ParsedStatement(start, length), _local(local), _identifier(identifier), _expression(expression) - { - } + class ParsedBlockStatement : public ParsedStatement { + const std::vector _statements; + public: + explicit ParsedBlockStatement(std::vector statements) + : ParsedStatement(statements.front()->GetStartPosition(), + statements.back()->GetEndPosition() - statements.front()->GetStartPosition()), + _statements(statements) {} - ~ParsedAssignmentStatement() final{ - delete _expression; - } + ParsedBlockStatement(std::vector statements, unsigned int start) : ParsedStatement( + start, 0), + _statements( + std::move( + statements)) { + } - const ParsedStatementKind GetKind() const final{ - return ParsedStatementKind ::Assignment; - } - const bool IsLocal() const{ - return _local; - } + ~ParsedBlockStatement() override { + for (auto s: _statements) { + delete s; + } + } - const HashedString GetIdentifier() const{ - return _identifier; - } + const ParsedStatementKind GetKind() const override { + return ParsedStatementKind::Block; + } - const ParsedExpression* GetExpression() const{ - return _expression; - } -}; + const std::vector *GetStatements() const { + return &_statements; + } + }; -class ParsedIndexAssignmentStatement : public ParsedStatement{ - const ParsedExpression* _indexExpression; - const ParsedExpression* _valueExpression; -public: - ParsedIndexAssignmentStatement(ParsedExpression* indexExpression, ParsedExpression* valueExpression, unsigned int start, + class ParsedScriptStatement : public ParsedBlockStatement { + public: + explicit ParsedScriptStatement(vector statements) : ParsedBlockStatement( + move(statements)) {} + + const ParsedStatementKind GetKind() const final { + return ParsedStatementKind::Script; + } + }; + + class ParsedExpressionStatement : public ParsedStatement { + const ParsedExpression *_expression; + public: + explicit ParsedExpressionStatement(ParsedExpression *expression) + : ParsedStatement(expression->GetStartPosition(), expression->GetLength()), + _expression(expression) { + } + + ~ParsedExpressionStatement() override { + delete _expression; + } + + const ParsedStatementKind GetKind() const final { + return ParsedStatementKind::Expression; + } + + const ParsedExpression *GetExpression() const { + return _expression; + } + }; + + class ParsedFunctionDeclarationStatement : public ParsedStatement { + const HashedString _identifier; + const vector _parameters; + const ParsedBlockStatement *_block; + public: + ParsedFunctionDeclarationStatement(HashedString identifier, vector parameters, + ParsedBlockStatement *block, + unsigned int start, unsigned int length) + : ParsedStatement(start, length), _identifier(identifier), _parameters(std::move(parameters)), + _block(block) {}; + + ~ParsedFunctionDeclarationStatement() override { + for (auto v : _parameters) { + delete v; + } + delete _block; + } + + const ParsedStatementKind GetKind() const final { + return ParsedStatementKind::FunctionDeclaration; + } + + const HashedString GetIdentifier() const { + return _identifier; + } + + const vector *GetParameters() const { + return &_parameters; + } + + const ParsedBlockStatement *GetBlock() const { + return _block; + } + }; + + class ParsedAssignmentStatement : public ParsedStatement { + const bool _local; + const HashedString _identifier; + const ParsedExpression *_expression; + public: + ParsedAssignmentStatement(bool local, const HashedString identifier, ParsedExpression *expression, + unsigned int start, unsigned int length) + : ParsedStatement(start, length), _local(local), _identifier(identifier), _expression(expression) { + } + + ~ParsedAssignmentStatement() final { + delete _expression; + } + + const ParsedStatementKind GetKind() const final { + return ParsedStatementKind::Assignment; + } + + const bool IsLocal() const { + return _local; + } + + const HashedString GetIdentifier() const { + return _identifier; + } + + const ParsedExpression *GetExpression() const { + return _expression; + } + }; + + class ParsedIndexAssignmentStatement : public ParsedStatement { + const ParsedExpression *_indexExpression; + const ParsedExpression *_valueExpression; + public: + ParsedIndexAssignmentStatement(ParsedExpression *indexExpression, ParsedExpression *valueExpression, + unsigned int start, + unsigned int length) + : ParsedStatement(start, length), + _indexExpression(indexExpression), _valueExpression(valueExpression) {} + + ~ParsedIndexAssignmentStatement() final { + delete _indexExpression; + delete _valueExpression; + } + + const ParsedStatementKind GetKind() const final { + return ParsedStatementKind::IndexAssignment; + } + + const ParsedExpression *GetIndexExpression() const { + return _indexExpression; + } + + const ParsedExpression *GetValueExpression() const { + return _valueExpression; + } + }; + + class ParsedReturnStatement : public ParsedStatement { + const ParsedExpression *_expression; + public: + ParsedReturnStatement(ParsedExpression *expression, unsigned int start, unsigned int length) + : ParsedStatement(start, length), + _expression(expression) { + } + + ~ParsedReturnStatement() final { + delete _expression; + } + + const ParsedStatementKind GetKind() const final { + return ParsedStatementKind::Return; + } + + const ParsedExpression *GetExpression() const { + return _expression; + } + }; + + class ParsedConditionalStatement : public ParsedStatement { + const ParsedExpression *_condition; + const ParsedStatement *_block; + // This can be either else if or else + const ParsedStatement *_elseStatement; + public: + ParsedConditionalStatement(ParsedExpression *condition, ParsedStatement *block, unsigned int start, unsigned int length) - : ParsedStatement(start, length), - _indexExpression(indexExpression), _valueExpression(valueExpression){} + : ParsedStatement(start, length), _condition(condition), _block(block), _elseStatement(nullptr) { + } - ~ParsedIndexAssignmentStatement() final{ - delete _indexExpression; - delete _valueExpression; - } + ParsedConditionalStatement(ParsedExpression *condition, ParsedStatement *block, ParsedStatement *nextStatement, + unsigned int start, unsigned int length) + : ParsedStatement(start, length), _condition(condition), _block(block), _elseStatement(nextStatement) { + _condition = condition; + _block = block; + _elseStatement = nextStatement; + } - const ParsedStatementKind GetKind() const final{ - return ParsedStatementKind ::IndexAssignment; - } + ~ParsedConditionalStatement() final { + delete _condition; + delete _block; + delete _elseStatement; + } - const ParsedExpression* GetIndexExpression() const{ - return _indexExpression; - } + const ParsedStatementKind GetKind() const final { + return ParsedStatementKind::Conditional; + } - const ParsedExpression* GetValueExpression() const{ - return _valueExpression; - } -}; + const ParsedExpression *GetCondition() const { + return _condition; + } -class ParsedReturnStatement : public ParsedStatement{ - const ParsedExpression* _expression; -public: - ParsedReturnStatement(ParsedExpression* expression, unsigned int start, unsigned int length) - : ParsedStatement(start, length), - _expression(expression) - { - } - - ~ParsedReturnStatement() final{ - delete _expression; - } - - const ParsedStatementKind GetKind() const final{ - return ParsedStatementKind ::Return; - } - - const ParsedExpression* GetExpression() const{ - return _expression; - } -}; - -class ParsedConditionalStatement : public ParsedStatement{ - const ParsedExpression* _condition; - const ParsedStatement* _block; - // This can be either else if or else - const ParsedStatement* _elseStatement; -public: - ParsedConditionalStatement(ParsedExpression* condition, ParsedStatement* block, unsigned int start, unsigned int length) - : ParsedStatement(start, length), _condition(condition), _block(block), _elseStatement(nullptr) - { - } - - ParsedConditionalStatement(ParsedExpression* condition, ParsedStatement* block, ParsedStatement* nextStatement, unsigned int start, unsigned int length) - : ParsedStatement(start, length), _condition(condition), _block(block), _elseStatement(nextStatement) - { - _condition = condition; - _block = block; - _elseStatement = nextStatement; - } - - ~ParsedConditionalStatement() final{ - delete _condition; - delete _block; - delete _elseStatement; - } - - const ParsedStatementKind GetKind() const final{ - return ParsedStatementKind ::Conditional; - } - - const ParsedExpression* GetCondition() const { - return _condition; - } - - const ParsedStatement* GetBlock() const { - return _block; - } - - const ParsedStatement* GetElseStatement() const { - return _elseStatement; - } -}; + const ParsedStatement *GetBlock() const { + return _block; + } + const ParsedStatement *GetElseStatement() const { + return _elseStatement; + } + }; +} #endif //PORYGONLANG_PARSEDSTATEMENT_HPP diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index fd2a59c..f79a767 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -7,426 +7,496 @@ #include "TypedVariableIdentifier.hpp" #include "ParsedExpressions/ParsedTableExpression.hpp" - -ParsedScriptStatement* Parser::Parse() { - vector statements; - while (this->_position < this->_tokens.size()){ - auto next = this -> Next(); - if (next->GetKind() == TokenKind::EndOfFile){ - break; +namespace Porygon::Parser { + ParsedScriptStatement *Parser::Parse() { + vector statements; + while (this->_position < this->_tokens.size()) { + auto next = this->Next(); + if (next->GetKind() == TokenKind::EndOfFile) { + break; + } + statements.push_back(this->ParseStatement(next)); } - statements.push_back(this -> ParseStatement(next)); - } - return new ParsedScriptStatement(statements); -} - -const IToken *Parser::Peek() { - return this -> _tokens[_position]; -} - -const IToken *Parser::PeekAt(int offset) { - return this -> _tokens[_position + offset]; -} - -const IToken *Parser::Next() { - this -> _position++; - return this -> _tokens[_position - 1]; -} - -ParsedStatement* Parser::ParseStatement(const IToken* current){ - auto currentKind = current->GetKind(); - switch (currentKind){ - case TokenKind ::LocalKeyword: return this->ParseVariableAssignment(current); - case TokenKind ::FunctionKeyword: return this -> ParseFunctionDeclaration(current); - case TokenKind ::ReturnKeyword: return this->ParseReturnStatement(current); - case TokenKind ::IfKeyword: return this -> ParseIfStatement(current); - default: break; - } - if (this->Peek()->GetKind() == TokenKind::AssignmentToken){ - return ParseVariableAssignment(current); - } - auto expression = this -> ParseExpression(current); - auto expKind = expression -> GetKind(); - if ((expKind == ParsedExpressionKind::Indexer || expKind == ParsedExpressionKind::PeriodIndexer) - && this -> Peek()->GetKind() == TokenKind::AssignmentToken){ - return this -> ParseIndexAssignment(expression); - } - return new ParsedExpressionStatement(expression); -} - -ParsedStatement *Parser::ParseVariableAssignment(const IToken *current) { - bool isLocal = false; - const IToken* identifier; - if (current -> GetKind() == TokenKind::LocalKeyword){ - isLocal = true; - identifier = this -> Next(); - } else{ - identifier = current; - } - auto assignmentToken = this->Next(); - auto expression = this -> ParseExpression(this -> Next()); - - if (identifier -> GetKind() != TokenKind::Identifier){ - this -> ScriptData -> Diagnostics -> LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(), identifier->GetLength()); - return new ParsedBadStatement(identifier->GetStartPosition(), identifier->GetLength()); - } - if (assignmentToken -> GetKind() != TokenKind::AssignmentToken){ - this -> ScriptData -> Diagnostics -> LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(), identifier->GetLength()); - return new ParsedBadStatement(identifier->GetStartPosition(), identifier->GetLength()); + return new ParsedScriptStatement(statements); } - auto start = current -> GetStartPosition(); - return new ParsedAssignmentStatement(isLocal, ((IdentifierToken*)identifier) -> GetValue(), expression, start, expression->GetEndPosition() - start); -} + const IToken *Parser::Peek() { + return this->_tokens[_position]; + } -ParsedStatement *Parser::ParseIndexAssignment(ParsedExpression *indexer) { - this -> Next(); // Consume assignment token - auto valueExpression = this -> ParseExpression(this -> Next()); - auto start = indexer->GetStartPosition(); - return new ParsedIndexAssignmentStatement(indexer, valueExpression, start, valueExpression->GetEndPosition() - start); -} + const IToken *Parser::PeekAt(int offset) { + return this->_tokens[_position + offset]; + } + const IToken *Parser::Next() { + this->_position++; + return this->_tokens[_position - 1]; + } -ParsedStatement *Parser::ParseBlock(const vector& endTokens, const vector& openStatements) { - auto statements = openStatements; - auto start = this->_position; - while (this->_position < this->_tokens.size()){ - auto next = this -> Next(); - auto nextKind = next->GetKind(); - if (std::find(endTokens.begin(), endTokens.end(), nextKind) != endTokens.end()){ - break; + ParsedStatement *Parser::ParseStatement(const IToken *current) { + auto currentKind = current->GetKind(); + switch (currentKind) { + case TokenKind::LocalKeyword: + return this->ParseVariableAssignment(current); + case TokenKind::FunctionKeyword: + return this->ParseFunctionDeclaration(current); + case TokenKind::ReturnKeyword: + return this->ParseReturnStatement(current); + case TokenKind::IfKeyword: + return this->ParseIfStatement(current); + default: + break; } - if (nextKind == TokenKind::EndOfFile){ - this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, next->GetStartPosition(), next->GetLength()); - break; + if (this->Peek()->GetKind() == TokenKind::AssignmentToken) { + return ParseVariableAssignment(current); } - statements.push_back(this -> ParseStatement(next)); - } - if (statements.empty()){ - return new ParsedBlockStatement(statements,start); - } - return new ParsedBlockStatement(statements); -} - -ParsedStatement *Parser::ParseFunctionDeclaration(const IToken *current) { - auto functionIdentifierToken = this->Next(); - auto openParenthesis = this->Next(); - vector parameters; - bool hasErrors = false; - if (functionIdentifierToken->GetKind() != TokenKind::Identifier){ - this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, functionIdentifierToken->GetStartPosition(), functionIdentifierToken->GetLength()); - hasErrors = true; - } - if (openParenthesis->GetKind() != TokenKind::OpenParenthesis && !hasErrors){ - this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, openParenthesis->GetStartPosition(), openParenthesis->GetLength()); - hasErrors = true; - } - - while (this -> _position < this->_tokens.size()){ - auto type = this->Next(); - if (type->GetKind() == TokenKind::CloseParenthesis){ - break; - } - auto identifier = this->Next(); - auto next = this->Next(); - if (type->GetKind() != TokenKind::Identifier &&!hasErrors){ - this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, type->GetStartPosition(), type->GetLength()); - hasErrors = true; - continue; - } - if (identifier->GetKind() != TokenKind::Identifier &&!hasErrors){ - this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(), identifier->GetLength()); - hasErrors = true; - continue; - } - - if (type->GetKind() != TokenKind::Identifier || identifier->GetKind() != TokenKind::Identifier){ - this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, type->GetStartPosition(), type->GetLength()); - hasErrors = true; - continue; - } - auto typeToken = (IdentifierToken*)type; - auto identifierToken = (IdentifierToken*)identifier; - parameters.push_back(new TypedVariableIdentifier(typeToken->GetValue(), identifierToken->GetValue())); - - auto nextKind = next->GetKind(); - if (nextKind == TokenKind::CloseParenthesis || nextKind == TokenKind::EndOfFile){ - break; - } else if (nextKind != TokenKind::CommaToken && !hasErrors){ - this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, next->GetStartPosition(), next->GetLength()); - hasErrors = true; + auto expression = this->ParseExpression(current); + auto expKind = expression->GetKind(); + if ((expKind == ParsedExpressionKind::Indexer || expKind == ParsedExpressionKind::PeriodIndexer) + && this->Peek()->GetKind() == TokenKind::AssignmentToken) { + return this->ParseIndexAssignment(expression); } + return new ParsedExpressionStatement(expression); } - auto block = this -> ParseBlock({TokenKind ::EndKeyword}); - auto start = current->GetStartPosition(); - if (hasErrors){ - return new ParsedBadStatement(start, block->GetEndPosition() - start); - } - if (block->GetKind() == ParsedStatementKind::Bad){ - return new ParsedBadStatement(start, block->GetEndPosition() - start); - } - auto functionIdentifier = ((IdentifierToken*) functionIdentifierToken)->GetValue(); - return new ParsedFunctionDeclarationStatement(HashedString(functionIdentifier), parameters, (ParsedBlockStatement*)block, start, block->GetEndPosition() - start); -} - -ParsedStatement* Parser::ParseReturnStatement(const IToken* current){ - //TODO: if next token is on a different line, don't parse it as return expression. - auto expression = this->ParseExpression(this->Next()); - auto start = current->GetStartPosition(); - return new ParsedReturnStatement(expression, start, expression->GetEndPosition() - start); -} - -ParsedStatement* Parser::ParseIfStatement(const IToken* current){ - auto condition = this->ParseExpression(this->Next()); - auto next = this -> Next(); - if (next->GetKind() != TokenKind::ThenKeyword){ - this -> ScriptData -> Diagnostics -> LogError(DiagnosticCode::UnexpectedToken, next->GetStartPosition(), next->GetLength()); - return new ParsedBadStatement(next->GetStartPosition(), next->GetLength()); - } - auto block = this -> ParseBlock({TokenKind ::EndKeyword, TokenKind ::ElseKeyword, TokenKind ::ElseIfKeyword}); - auto closeToken = this->PeekAt(-1); - auto start = current->GetStartPosition(); - if (closeToken->GetKind() == TokenKind::ElseIfKeyword){ - auto elseIfStatement = this -> ParseIfStatement(closeToken); - return new ParsedConditionalStatement(condition, block, elseIfStatement, start, elseIfStatement->GetEndPosition() - start); - } else if (closeToken->GetKind() == TokenKind::ElseKeyword){ - auto elseStatement = this -> ParseBlock({TokenKind ::EndKeyword}); - return new ParsedConditionalStatement(condition, block, elseStatement, start, elseStatement->GetEndPosition() - start); - } - return new ParsedConditionalStatement(condition, block, start, block->GetEndPosition() - start); -} - -ParsedExpression* Parser::ParseExpression(const IToken* current){ - auto expression = this -> ParseBinaryExpression(current, OperatorPrecedence::No); - auto peekKind = this->Peek()->GetKind(); - while (peekKind == TokenKind::OpenParenthesis || - peekKind == TokenKind::OpenSquareBracket || - peekKind == TokenKind::PeriodToken){ - if (peekKind == TokenKind::OpenParenthesis){ - expression = this->ParseFunctionCallExpression(expression); - } else if (peekKind == TokenKind::OpenSquareBracket){ - expression = this->ParseIndexExpression(expression); + ParsedStatement *Parser::ParseVariableAssignment(const IToken *current) { + bool isLocal = false; + const IToken *identifier; + if (current->GetKind() == TokenKind::LocalKeyword) { + isLocal = true; + identifier = this->Next(); } else { - expression = this -> ParsePeriodIndexExpression(expression); + identifier = current; } - if (this -> _position >= this->_tokens.size()) - break; - peekKind = this->Peek()->GetKind(); - } - return expression; -} + auto assignmentToken = this->Next(); + auto expression = this->ParseExpression(this->Next()); -OperatorPrecedence GetUnaryPrecedence(TokenKind kind){ - switch (kind){ - case TokenKind::PlusToken: - case TokenKind::MinusToken: - case TokenKind::NotKeyword: - return OperatorPrecedence::Unary; - default: - return OperatorPrecedence::No; - } -} - -UnaryOperatorKind GetUnaryOperatorKind(TokenKind kind){ - switch (kind){ - case TokenKind::PlusToken: return UnaryOperatorKind::Identity; - case TokenKind::MinusToken: return UnaryOperatorKind::Negation; - case TokenKind::NotKeyword: return UnaryOperatorKind::LogicalNegation; - default: // This should never trigger, so throw. - throw; - } -} - -BinaryOperatorKind GetBinaryOperatorKind(TokenKind kind){ - switch (kind){ - // Math operators - case TokenKind::PlusToken: return BinaryOperatorKind ::Addition; - case TokenKind::MinusToken: return BinaryOperatorKind ::Subtraction; - case TokenKind::StarToken: return BinaryOperatorKind ::Multiplication; - case TokenKind::SlashToken: return BinaryOperatorKind ::Division; - - // Equality operators - case TokenKind::EqualityToken: return BinaryOperatorKind ::Equality; - case TokenKind::InequalityToken: return BinaryOperatorKind ::Inequality; - case TokenKind ::Less: return BinaryOperatorKind ::Less; - case TokenKind ::LessEquals: return BinaryOperatorKind ::LessOrEquals; - case TokenKind ::Greater: return BinaryOperatorKind ::Greater; - case TokenKind ::GreaterEquals: return BinaryOperatorKind ::GreaterOrEquals; - - // logical operators - case TokenKind::AndKeyword: return BinaryOperatorKind ::LogicalAnd; - case TokenKind::OrKeyword: return BinaryOperatorKind ::LogicalOr; - default: // This should never trigger, so throw. - throw; - } -} - -OperatorPrecedence GetBinaryPrecedence(TokenKind kind){ - switch (kind){ - // Math - case TokenKind::PlusToken: return OperatorPrecedence ::Additive; - case TokenKind::MinusToken: return OperatorPrecedence ::Additive; - case TokenKind::StarToken: return OperatorPrecedence ::Multiplication; - case TokenKind::SlashToken: return OperatorPrecedence ::Multiplication; - - // Equality - case TokenKind::EqualityToken: return OperatorPrecedence ::Equality; - case TokenKind::InequalityToken: return OperatorPrecedence ::Equality; - case TokenKind ::Less: return OperatorPrecedence ::Equality; - case TokenKind ::LessEquals: return OperatorPrecedence ::Equality; - case TokenKind ::Greater: return OperatorPrecedence ::Equality; - case TokenKind ::GreaterEquals: return OperatorPrecedence ::Equality; - - // Logical - case TokenKind::AndKeyword: return OperatorPrecedence ::LogicalAnd; - case TokenKind::OrKeyword: return OperatorPrecedence ::LogicalOr; - default: - return OperatorPrecedence::No; - } -} - -ParsedExpression* Parser::ParseBinaryExpression(const IToken* current, OperatorPrecedence parentPrecedence){ - OperatorPrecedence unaryPrecedence = GetUnaryPrecedence(current -> GetKind()); - ParsedExpression* left; - if (unaryPrecedence != OperatorPrecedence::No && unaryPrecedence >= parentPrecedence){ - UnaryOperatorKind operatorKind = GetUnaryOperatorKind(current -> GetKind()); - auto next = this -> Next(); - auto operand = this -> ParseBinaryExpression(next, unaryPrecedence); - auto startPos = current -> GetStartPosition(); - left = new UnaryExpression(operatorKind, operand, startPos, operand -> GetEndPosition() - startPos); - } else{ - left = this -> ParsePrimaryExpression(current); - } - while (true){ - auto next = this -> Peek(); - OperatorPrecedence binaryPrecedence = GetBinaryPrecedence(next -> GetKind()); - if (binaryPrecedence == OperatorPrecedence::No || binaryPrecedence <= parentPrecedence){ - break; + if (identifier->GetKind() != TokenKind::Identifier) { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(), + identifier->GetLength()); + return new ParsedBadStatement(identifier->GetStartPosition(), identifier->GetLength()); } - auto operatorKind = GetBinaryOperatorKind(next -> GetKind()); - this -> Next(); - auto right = this -> ParseBinaryExpression(this -> Next(), binaryPrecedence); - auto startPos = left -> GetStartPosition(); - left = new BinaryExpression(operatorKind, left, right, startPos, right -> GetEndPosition() - startPos); - } - return left; -} - -ParsedExpression *Parser::ParsePrimaryExpression(const IToken *current) { - switch (current -> GetKind()){ - case TokenKind ::Integer: return new LiteralIntegerExpression((IntegerToken*)current); - case TokenKind ::Float: return new LiteralFloatExpression((FloatToken*)current); - case TokenKind ::String: return new LiteralStringExpression((StringToken*)current); - case TokenKind ::TrueKeyword: return new LiteralBoolExpression(current); - case TokenKind ::FalseKeyword: return new LiteralBoolExpression(current); - case TokenKind ::Identifier: return new VariableExpression((IdentifierToken*)current); - case TokenKind ::OpenParenthesis: return this -> ParseParenthesizedExpression(current); - case TokenKind ::OpenCurlyBracket: return this -> ParseTableExpression(current); - // If we find a bad token here, we should have already logged it in the lexer, so don't log another error. - case TokenKind ::BadToken: return new BadExpression(current->GetStartPosition(), current->GetLength()); - default: - this -> ScriptData -> Diagnostics -> LogError(DiagnosticCode::UnexpectedToken, current->GetStartPosition(), current->GetLength()); - return new BadExpression(current->GetStartPosition(), current->GetLength()); - } -} - -ParsedExpression *Parser::ParseParenthesizedExpression(const IToken *current) { - auto next = this -> Next(); - auto expression = this -> ParseExpression(next); - auto closeToken = this -> Next(); - if (closeToken -> GetKind() != TokenKind::CloseParenthesis){ - this -> ScriptData -> Diagnostics -> LogError(DiagnosticCode::UnexpectedToken, closeToken->GetStartPosition(), closeToken->GetLength()); - return new BadExpression(closeToken->GetStartPosition(), closeToken->GetLength()); - } - auto start = current -> GetStartPosition(); - return new ParenthesizedExpression(expression, start, closeToken->GetEndPosition() - start); -} - -ParsedExpression *Parser::ParseFunctionCallExpression(ParsedExpression* functionExpression) { - this -> Next(); // consume the open parenthesis - vector parameters; - auto peeked = this -> Peek(); - auto peekedKind = peeked->GetKind(); - if (peekedKind == TokenKind::CloseParenthesis){ - this->Next(); - } else{ - while (peekedKind != TokenKind::CloseParenthesis){ - if (peekedKind == TokenKind ::EndOfFile){ - this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, peeked->GetStartPosition(), peeked->GetLength()); - return new BadExpression(peeked->GetStartPosition(), peeked->GetLength()); - } - parameters.push_back(this->ParseExpression(this->Next())); - peeked = this -> Next() ; - peekedKind = peeked->GetKind(); - if (peekedKind != TokenKind::CloseParenthesis && peekedKind != TokenKind::CommaToken){ - this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, peeked->GetStartPosition(), peeked->GetLength()); - return new BadExpression(peeked->GetStartPosition(), peeked->GetLength()); - } + if (assignmentToken->GetKind() != TokenKind::AssignmentToken) { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(), + identifier->GetLength()); + return new ParsedBadStatement(identifier->GetStartPosition(), identifier->GetLength()); } - } - auto start = functionExpression->GetStartPosition(); - return new FunctionCallExpression(functionExpression, parameters, start, peeked->GetEndPosition() - start); -} -ParsedExpression* Parser::ParseIndexExpression(ParsedExpression* indexingExpression){ - this->Next(); // consume '[' token - auto indexExpression = this -> ParseExpression(this -> Next()); - auto closeBracket = this->Next(); - if (closeBracket->GetKind() != TokenKind::CloseSquareBracket){ - this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, closeBracket->GetStartPosition(), closeBracket->GetLength()); - return new BadExpression(closeBracket->GetStartPosition(), closeBracket->GetLength()); - } - auto start = indexingExpression->GetStartPosition(); - return new IndexExpression(indexingExpression, indexExpression, start, closeBracket->GetEndPosition() - start); -} - -ParsedExpression* Parser::ParsePeriodIndexExpression(ParsedExpression* indexingExpression){ - this->Next(); // consume '.' token - auto identifier = this -> Next(); - if (identifier->GetKind() != TokenKind::Identifier){ - this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(), identifier->GetLength()); - return new BadExpression(indexingExpression->GetStartPosition(), identifier->GetEndPosition() - indexingExpression->GetStartPosition()); - } - auto start = indexingExpression->GetStartPosition(); - return new PeriodIndexExpression(indexingExpression, ((IdentifierToken*)identifier)->GetValue(), start, identifier->GetEndPosition() - start); -} - - -ParsedExpression* Parser::ParseTableExpression(const IToken* current){ - if (this -> Peek() -> GetKind() == TokenKind::CloseCurlyBracket){ - this -> Next(); auto start = current->GetStartPosition(); - return new ParsedNumericalTableExpression({}, start, this -> Peek()->GetEndPosition() - start); + return new ParsedAssignmentStatement(isLocal, ((IdentifierToken *) identifier)->GetValue(), expression, start, + expression->GetEndPosition() - start); } - auto start = current->GetStartPosition(); - auto firstItem = this->ParseStatement(this -> Next()); - // If the first item is an expression, and is followed by a comma, we're dealing with a simple {1, 2, 3} kind of array - if (firstItem->GetKind() == ParsedStatementKind::Expression && - (this->Peek()->GetKind() == TokenKind::CommaToken )){ - auto expr = ((ParsedExpressionStatement*)firstItem)->GetExpression(); - auto expressions = vector{expr}; - auto n = this -> Next(); // consume the comma + + ParsedStatement *Parser::ParseIndexAssignment(ParsedExpression *indexer) { + this->Next(); // Consume assignment token + auto valueExpression = this->ParseExpression(this->Next()); + auto start = indexer->GetStartPosition(); + return new ParsedIndexAssignmentStatement(indexer, valueExpression, start, + valueExpression->GetEndPosition() - start); + } + + + ParsedStatement * + Parser::ParseBlock(const vector &endTokens, const vector &openStatements) { + auto statements = openStatements; + auto start = this->_position; + while (this->_position < this->_tokens.size()) { + auto next = this->Next(); + auto nextKind = next->GetKind(); + if (std::find(endTokens.begin(), endTokens.end(), nextKind) != endTokens.end()) { + break; + } + if (nextKind == TokenKind::EndOfFile) { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, next->GetStartPosition(), + next->GetLength()); + break; + } + statements.push_back(this->ParseStatement(next)); + } + if (statements.empty()) { + return new ParsedBlockStatement(statements, start); + } + return new ParsedBlockStatement(statements); + } + + ParsedStatement *Parser::ParseFunctionDeclaration(const IToken *current) { + auto functionIdentifierToken = this->Next(); + auto openParenthesis = this->Next(); + vector parameters; bool hasErrors = false; - while (n->GetKind() != TokenKind::CloseCurlyBracket){ - auto expression = this->ParseExpression(this->Next()); - expressions.push_back(expression); - n = this->Next(); - if (n->GetKind() != TokenKind::CommaToken && n->GetKind() != TokenKind ::CloseCurlyBracket && !hasErrors){ - this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, n->GetStartPosition(), n->GetLength()); + if (functionIdentifierToken->GetKind() != TokenKind::Identifier) { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, + functionIdentifierToken->GetStartPosition(), + functionIdentifierToken->GetLength()); + hasErrors = true; + } + if (openParenthesis->GetKind() != TokenKind::OpenParenthesis && !hasErrors) { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, + openParenthesis->GetStartPosition(), openParenthesis->GetLength()); + hasErrors = true; + } + + while (this->_position < this->_tokens.size()) { + auto type = this->Next(); + if (type->GetKind() == TokenKind::CloseParenthesis) { + break; + } + auto identifier = this->Next(); + auto next = this->Next(); + if (type->GetKind() != TokenKind::Identifier && !hasErrors) { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, type->GetStartPosition(), + type->GetLength()); + hasErrors = true; + continue; + } + if (identifier->GetKind() != TokenKind::Identifier && !hasErrors) { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(), + identifier->GetLength()); + hasErrors = true; + continue; + } + + if (type->GetKind() != TokenKind::Identifier || identifier->GetKind() != TokenKind::Identifier) { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, type->GetStartPosition(), + type->GetLength()); + hasErrors = true; + continue; + } + auto typeToken = (IdentifierToken *) type; + auto identifierToken = (IdentifierToken *) identifier; + parameters.push_back(new TypedVariableIdentifier(typeToken->GetValue(), identifierToken->GetValue())); + + auto nextKind = next->GetKind(); + if (nextKind == TokenKind::CloseParenthesis || nextKind == TokenKind::EndOfFile) { + break; + } else if (nextKind != TokenKind::CommaToken && !hasErrors) { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, next->GetStartPosition(), + next->GetLength()); hasErrors = true; } } - if (hasErrors){ - return new BadExpression(start, n->GetEndPosition() - start); - } - return new ParsedNumericalTableExpression(expressions, start, n->GetEndPosition() - start); - } - // Otherwise we have a more complex table, which can be defined by a block - else { - auto block = (ParsedBlockStatement*)this -> ParseBlock({TokenKind ::CloseCurlyBracket}, {firstItem}); - auto closeToken = this -> PeekAt(-1); - return new ParsedTableExpression(block, start, closeToken->GetEndPosition() - start); - } -} + auto block = this->ParseBlock({TokenKind::EndKeyword}); + auto start = current->GetStartPosition(); + if (hasErrors) { + return new ParsedBadStatement(start, block->GetEndPosition() - start); + } + if (block->GetKind() == ParsedStatementKind::Bad) { + return new ParsedBadStatement(start, block->GetEndPosition() - start); + } + auto functionIdentifier = ((IdentifierToken *) functionIdentifierToken)->GetValue(); + return new ParsedFunctionDeclarationStatement(HashedString(functionIdentifier), parameters, + (ParsedBlockStatement *) block, start, + block->GetEndPosition() - start); + } + + ParsedStatement *Parser::ParseReturnStatement(const IToken *current) { + //TODO: if next token is on a different line, don't parse it as return expression. + auto expression = this->ParseExpression(this->Next()); + auto start = current->GetStartPosition(); + return new ParsedReturnStatement(expression, start, expression->GetEndPosition() - start); + } + + ParsedStatement *Parser::ParseIfStatement(const IToken *current) { + auto condition = this->ParseExpression(this->Next()); + auto next = this->Next(); + if (next->GetKind() != TokenKind::ThenKeyword) { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, next->GetStartPosition(), + next->GetLength()); + return new ParsedBadStatement(next->GetStartPosition(), next->GetLength()); + } + auto block = this->ParseBlock({TokenKind::EndKeyword, TokenKind::ElseKeyword, TokenKind::ElseIfKeyword}); + auto closeToken = this->PeekAt(-1); + auto start = current->GetStartPosition(); + if (closeToken->GetKind() == TokenKind::ElseIfKeyword) { + auto elseIfStatement = this->ParseIfStatement(closeToken); + return new ParsedConditionalStatement(condition, block, elseIfStatement, start, + elseIfStatement->GetEndPosition() - start); + } else if (closeToken->GetKind() == TokenKind::ElseKeyword) { + auto elseStatement = this->ParseBlock({TokenKind::EndKeyword}); + return new ParsedConditionalStatement(condition, block, elseStatement, start, + elseStatement->GetEndPosition() - start); + } + return new ParsedConditionalStatement(condition, block, start, block->GetEndPosition() - start); + } + + ParsedExpression *Parser::ParseExpression(const IToken *current) { + auto expression = this->ParseBinaryExpression(current, OperatorPrecedence::No); + auto peekKind = this->Peek()->GetKind(); + while (peekKind == TokenKind::OpenParenthesis || + peekKind == TokenKind::OpenSquareBracket || + peekKind == TokenKind::PeriodToken) { + if (peekKind == TokenKind::OpenParenthesis) { + expression = this->ParseFunctionCallExpression(expression); + } else if (peekKind == TokenKind::OpenSquareBracket) { + expression = this->ParseIndexExpression(expression); + } else { + expression = this->ParsePeriodIndexExpression(expression); + } + if (this->_position >= this->_tokens.size()) + break; + peekKind = this->Peek()->GetKind(); + } + return expression; + } + + OperatorPrecedence GetUnaryPrecedence(TokenKind kind) { + switch (kind) { + case TokenKind::PlusToken: + case TokenKind::MinusToken: + case TokenKind::NotKeyword: + return OperatorPrecedence::Unary; + default: + return OperatorPrecedence::No; + } + } + + UnaryOperatorKind GetUnaryOperatorKind(TokenKind kind) { + switch (kind) { + case TokenKind::PlusToken: + return UnaryOperatorKind::Identity; + case TokenKind::MinusToken: + return UnaryOperatorKind::Negation; + case TokenKind::NotKeyword: + return UnaryOperatorKind::LogicalNegation; + default: // This should never trigger, so throw. + throw; + } + } + + BinaryOperatorKind GetBinaryOperatorKind(TokenKind kind) { + switch (kind) { + // Math operators + case TokenKind::PlusToken: + return BinaryOperatorKind::Addition; + case TokenKind::MinusToken: + return BinaryOperatorKind::Subtraction; + case TokenKind::StarToken: + return BinaryOperatorKind::Multiplication; + case TokenKind::SlashToken: + return BinaryOperatorKind::Division; + + // Equality operators + case TokenKind::EqualityToken: + return BinaryOperatorKind::Equality; + case TokenKind::InequalityToken: + return BinaryOperatorKind::Inequality; + case TokenKind::Less: + return BinaryOperatorKind::Less; + case TokenKind::LessEquals: + return BinaryOperatorKind::LessOrEquals; + case TokenKind::Greater: + return BinaryOperatorKind::Greater; + case TokenKind::GreaterEquals: + return BinaryOperatorKind::GreaterOrEquals; + + // logical operators + case TokenKind::AndKeyword: + return BinaryOperatorKind::LogicalAnd; + case TokenKind::OrKeyword: + return BinaryOperatorKind::LogicalOr; + default: // This should never trigger, so throw. + throw; + } + } + + OperatorPrecedence GetBinaryPrecedence(TokenKind kind) { + switch (kind) { + // Math + case TokenKind::PlusToken: + return OperatorPrecedence::Additive; + case TokenKind::MinusToken: + return OperatorPrecedence::Additive; + case TokenKind::StarToken: + return OperatorPrecedence::Multiplication; + case TokenKind::SlashToken: + return OperatorPrecedence::Multiplication; + + // Equality + case TokenKind::EqualityToken: + return OperatorPrecedence::Equality; + case TokenKind::InequalityToken: + return OperatorPrecedence::Equality; + case TokenKind::Less: + return OperatorPrecedence::Equality; + case TokenKind::LessEquals: + return OperatorPrecedence::Equality; + case TokenKind::Greater: + return OperatorPrecedence::Equality; + case TokenKind::GreaterEquals: + return OperatorPrecedence::Equality; + + // Logical + case TokenKind::AndKeyword: + return OperatorPrecedence::LogicalAnd; + case TokenKind::OrKeyword: + return OperatorPrecedence::LogicalOr; + default: + return OperatorPrecedence::No; + } + } + + ParsedExpression *Parser::ParseBinaryExpression(const IToken *current, OperatorPrecedence parentPrecedence) { + OperatorPrecedence unaryPrecedence = GetUnaryPrecedence(current->GetKind()); + ParsedExpression *left; + if (unaryPrecedence != OperatorPrecedence::No && unaryPrecedence >= parentPrecedence) { + UnaryOperatorKind operatorKind = GetUnaryOperatorKind(current->GetKind()); + auto next = this->Next(); + auto operand = this->ParseBinaryExpression(next, unaryPrecedence); + auto startPos = current->GetStartPosition(); + left = new UnaryExpression(operatorKind, operand, startPos, operand->GetEndPosition() - startPos); + } else { + left = this->ParsePrimaryExpression(current); + } + while (true) { + auto next = this->Peek(); + OperatorPrecedence binaryPrecedence = GetBinaryPrecedence(next->GetKind()); + if (binaryPrecedence == OperatorPrecedence::No || binaryPrecedence <= parentPrecedence) { + break; + } + auto operatorKind = GetBinaryOperatorKind(next->GetKind()); + this->Next(); + auto right = this->ParseBinaryExpression(this->Next(), binaryPrecedence); + auto startPos = left->GetStartPosition(); + left = new BinaryExpression(operatorKind, left, right, startPos, right->GetEndPosition() - startPos); + } + return left; + } + + ParsedExpression *Parser::ParsePrimaryExpression(const IToken *current) { + switch (current->GetKind()) { + case TokenKind::Integer: + return new LiteralIntegerExpression((IntegerToken *) current); + case TokenKind::Float: + return new LiteralFloatExpression((FloatToken *) current); + case TokenKind::String: + return new LiteralStringExpression((StringToken *) current); + case TokenKind::TrueKeyword: + return new LiteralBoolExpression(current); + case TokenKind::FalseKeyword: + return new LiteralBoolExpression(current); + case TokenKind::Identifier: + return new VariableExpression((IdentifierToken *) current); + case TokenKind::OpenParenthesis: + return this->ParseParenthesizedExpression(current); + case TokenKind::OpenCurlyBracket: + return this->ParseTableExpression(current); + // If we find a bad token here, we should have already logged it in the lexer, so don't log another error. + case TokenKind::BadToken: + return new BadExpression(current->GetStartPosition(), current->GetLength()); + default: + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, current->GetStartPosition(), + current->GetLength()); + return new BadExpression(current->GetStartPosition(), current->GetLength()); + } + } + + ParsedExpression *Parser::ParseParenthesizedExpression(const IToken *current) { + auto next = this->Next(); + auto expression = this->ParseExpression(next); + auto closeToken = this->Next(); + if (closeToken->GetKind() != TokenKind::CloseParenthesis) { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, closeToken->GetStartPosition(), + closeToken->GetLength()); + return new BadExpression(closeToken->GetStartPosition(), closeToken->GetLength()); + } + auto start = current->GetStartPosition(); + return new ParenthesizedExpression(expression, start, closeToken->GetEndPosition() - start); + } + + ParsedExpression *Parser::ParseFunctionCallExpression(ParsedExpression *functionExpression) { + this->Next(); // consume the open parenthesis + vector parameters; + auto peeked = this->Peek(); + auto peekedKind = peeked->GetKind(); + if (peekedKind == TokenKind::CloseParenthesis) { + this->Next(); + } else { + while (peekedKind != TokenKind::CloseParenthesis) { + if (peekedKind == TokenKind::EndOfFile) { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, peeked->GetStartPosition(), + peeked->GetLength()); + return new BadExpression(peeked->GetStartPosition(), peeked->GetLength()); + } + parameters.push_back(this->ParseExpression(this->Next())); + peeked = this->Next(); + peekedKind = peeked->GetKind(); + if (peekedKind != TokenKind::CloseParenthesis && peekedKind != TokenKind::CommaToken) { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, peeked->GetStartPosition(), + peeked->GetLength()); + return new BadExpression(peeked->GetStartPosition(), peeked->GetLength()); + } + } + } + auto start = functionExpression->GetStartPosition(); + return new FunctionCallExpression(functionExpression, parameters, start, peeked->GetEndPosition() - start); + } + + ParsedExpression *Parser::ParseIndexExpression(ParsedExpression *indexingExpression) { + this->Next(); // consume '[' token + auto indexExpression = this->ParseExpression(this->Next()); + auto closeBracket = this->Next(); + if (closeBracket->GetKind() != TokenKind::CloseSquareBracket) { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, closeBracket->GetStartPosition(), + closeBracket->GetLength()); + return new BadExpression(closeBracket->GetStartPosition(), closeBracket->GetLength()); + } + auto start = indexingExpression->GetStartPosition(); + return new IndexExpression(indexingExpression, indexExpression, start, closeBracket->GetEndPosition() - start); + } + + ParsedExpression *Parser::ParsePeriodIndexExpression(ParsedExpression *indexingExpression) { + this->Next(); // consume '.' token + auto identifier = this->Next(); + if (identifier->GetKind() != TokenKind::Identifier) { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(), + identifier->GetLength()); + return new BadExpression(indexingExpression->GetStartPosition(), + identifier->GetEndPosition() - indexingExpression->GetStartPosition()); + } + auto start = indexingExpression->GetStartPosition(); + return new PeriodIndexExpression(indexingExpression, ((IdentifierToken *) identifier)->GetValue(), start, + identifier->GetEndPosition() - start); + } + + + ParsedExpression *Parser::ParseTableExpression(const IToken *current) { + if (this->Peek()->GetKind() == TokenKind::CloseCurlyBracket) { + this->Next(); + auto start = current->GetStartPosition(); + return new ParsedNumericalTableExpression({}, start, this->Peek()->GetEndPosition() - start); + } + auto start = current->GetStartPosition(); + auto firstItem = this->ParseStatement(this->Next()); + // If the first item is an expression, and is followed by a comma, we're dealing with a simple {1, 2, 3} kind of array + if (firstItem->GetKind() == ParsedStatementKind::Expression && + (this->Peek()->GetKind() == TokenKind::CommaToken)) { + auto expr = ((ParsedExpressionStatement *) firstItem)->GetExpression(); + auto expressions = vector{expr}; + auto n = this->Next(); // consume the comma + bool hasErrors = false; + while (n->GetKind() != TokenKind::CloseCurlyBracket) { + auto expression = this->ParseExpression(this->Next()); + expressions.push_back(expression); + n = this->Next(); + if (n->GetKind() != TokenKind::CommaToken && n->GetKind() != TokenKind::CloseCurlyBracket && + !hasErrors) { + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, n->GetStartPosition(), + n->GetLength()); + hasErrors = true; + } + } + if (hasErrors) { + return new BadExpression(start, n->GetEndPosition() - start); + } + return new ParsedNumericalTableExpression(expressions, start, n->GetEndPosition() - start); + } + // Otherwise we have a more complex table, which can be defined by a block + else { + auto block = (ParsedBlockStatement *) this->ParseBlock({TokenKind::CloseCurlyBracket}, {firstItem}); + auto closeToken = this->PeekAt(-1); + return new ParsedTableExpression(block, start, closeToken->GetEndPosition() - start); + } + } + +} \ No newline at end of file diff --git a/src/Parser/Parser.hpp b/src/Parser/Parser.hpp index 845ee01..81c0951 100644 --- a/src/Parser/Parser.hpp +++ b/src/Parser/Parser.hpp @@ -7,51 +7,69 @@ #include "ParsedStatements/ParsedStatement.hpp" #include "../Script.hpp" -enum class OperatorPrecedence { - No, - LogicalOr, - LogicalAnd, - Equality, - Additive, - Multiplication, - Unary, -}; +namespace Porygon::Parser { + enum class OperatorPrecedence { + No, + LogicalOr, + LogicalAnd, + Equality, + Additive, + Multiplication, + Unary, + }; -class Parser { - vector _tokens; - unsigned int _position; - Script* ScriptData; + class Parser { + vector _tokens; + unsigned int _position; + Porygon::Script *ScriptData; - const IToken* Peek(); - const IToken *PeekAt(int offset); - const IToken* Next(); + const IToken *Peek(); - ParsedStatement* ParseStatement(const IToken* current); - ParsedStatement* ParseVariableAssignment(const IToken *current); - ParsedStatement* ParseIndexAssignment(ParsedExpression *indexer); - ParsedStatement *ParseBlock(const vector& endTokens, const vector& openStatements = {}); - ParsedStatement* ParseFunctionDeclaration(const IToken* current); - ParsedStatement *ParseReturnStatement(const IToken *current); - ParsedStatement *ParseIfStatement(const IToken *current); + const IToken *PeekAt(int offset); - ParsedExpression* ParseExpression(const IToken* current); - ParsedExpression* ParseBinaryExpression(const IToken* current, OperatorPrecedence parentPrecedence); - ParsedExpression* ParsePrimaryExpression(const IToken* current); - ParsedExpression* ParseParenthesizedExpression(const IToken *current); + const IToken *Next(); - ParsedExpression* ParseFunctionCallExpression(ParsedExpression* functionExpression); - ParsedExpression *ParseIndexExpression(ParsedExpression *indexingExpression); - ParsedExpression *ParsePeriodIndexExpression(ParsedExpression *indexingExpression); - ParsedExpression *ParseTableExpression(const IToken *current); -public: - ParsedScriptStatement* Parse(); - explicit Parser(const vector& tokens, Script* scriptData){ - _tokens = tokens; - _position = 0; - ScriptData = scriptData; - } + ParsedStatement *ParseStatement(const IToken *current); -}; + ParsedStatement *ParseVariableAssignment(const IToken *current); + ParsedStatement *ParseIndexAssignment(ParsedExpression *indexer); + + ParsedStatement * + ParseBlock(const vector &endTokens, const vector &openStatements = {}); + + ParsedStatement *ParseFunctionDeclaration(const IToken *current); + + ParsedStatement *ParseReturnStatement(const IToken *current); + + ParsedStatement *ParseIfStatement(const IToken *current); + + ParsedExpression *ParseExpression(const IToken *current); + + ParsedExpression *ParseBinaryExpression(const IToken *current, OperatorPrecedence parentPrecedence); + + ParsedExpression *ParsePrimaryExpression(const IToken *current); + + ParsedExpression *ParseParenthesizedExpression(const IToken *current); + + ParsedExpression *ParseFunctionCallExpression(ParsedExpression *functionExpression); + + ParsedExpression *ParseIndexExpression(ParsedExpression *indexingExpression); + + ParsedExpression *ParsePeriodIndexExpression(ParsedExpression *indexingExpression); + + ParsedExpression *ParseTableExpression(const IToken *current); + + public: + ParsedScriptStatement *Parse(); + + explicit Parser(const vector &tokens, Porygon::Script *scriptData) { + _tokens = tokens; + _position = 0; + ScriptData = scriptData; + } + + }; +} #endif //PORYGONLANG_PARSER_HPP diff --git a/src/Parser/Token.hpp b/src/Parser/Token.hpp index 366e756..ec70b1a 100644 --- a/src/Parser/Token.hpp +++ b/src/Parser/Token.hpp @@ -10,122 +10,119 @@ #include "../Utilities/HashedString.hpp" using namespace std; +using namespace Porygon::Utilities; -class IToken{ - const unsigned int _position; - const unsigned int _length; -public: - virtual const TokenKind GetKind() const = 0; +namespace Porygon::Parser { + class IToken { + const unsigned int _position; + const unsigned int _length; + public: + virtual const TokenKind GetKind() const = 0; - IToken(unsigned int position, unsigned int length) - : _position(position), _length(length) - { - } + IToken(unsigned int position, unsigned int length) + : _position(position), _length(length) { + } - const unsigned int GetStartPosition() const{ - return _position; - } + const unsigned int GetStartPosition() const { + return _position; + } - const unsigned int GetEndPosition() const{ - return _position + _length - 1; - } + const unsigned int GetEndPosition() const { + return _position + _length - 1; + } - const unsigned int GetLength() const{ - return _length; - } + const unsigned int GetLength() const { + return _length; + } - virtual ~IToken() = default; -}; + virtual ~IToken() = default; + }; -class SimpleToken : public IToken{ - const TokenKind _kind; -public: + class SimpleToken : public IToken { + const TokenKind _kind; + public: - explicit SimpleToken(TokenKind kind, unsigned int position, unsigned int length) - : IToken(position, length), - _kind(kind) - { - } + explicit SimpleToken(TokenKind kind, unsigned int position, unsigned int length) + : IToken(position, length), + _kind(kind) { + } - const TokenKind GetKind() const final{ - return _kind; - } -}; + const TokenKind GetKind() const final { + return _kind; + } + }; -class IntegerToken : public IToken{ - const long _value; -public: + class IntegerToken : public IToken { + const long _value; + public: - explicit IntegerToken(long value, unsigned int position, unsigned int length) - : IToken(position, length), - _value(value) - { - } + explicit IntegerToken(long value, unsigned int position, unsigned int length) + : IToken(position, length), + _value(value) { + } - const TokenKind GetKind() const final{ - return TokenKind::Integer; - } + const TokenKind GetKind() const final { + return TokenKind::Integer; + } - const long GetValue() const{ - return _value; - } -}; + const long GetValue() const { + return _value; + } + }; -class FloatToken : public IToken{ - const double _value; -public: + class FloatToken : public IToken { + const double _value; + public: - explicit FloatToken(double value, unsigned int position, unsigned int length) - : IToken(position, length), - _value(value) - { - } + explicit FloatToken(double value, unsigned int position, unsigned int length) + : IToken(position, length), + _value(value) { + } - const TokenKind GetKind() const final{ - return TokenKind::Float; - } + const TokenKind GetKind() const final { + return TokenKind::Float; + } - const double GetValue() const{ - return _value; - } -}; + const double GetValue() const { + return _value; + } + }; -class StringToken : public IToken{ - const u16string _value; -public: + class StringToken : public IToken { + const u16string _value; + public: - explicit StringToken(u16string value, unsigned int position, unsigned int length) - : IToken(position, length), - _value(std::move(value)) - { - } + explicit StringToken(u16string value, unsigned int position, unsigned int length) + : IToken(position, length), + _value(std::move(value)) { + } - const TokenKind GetKind() const final{ - return TokenKind::String; - } + const TokenKind GetKind() const final { + return TokenKind::String; + } - const u16string& GetValue() const{ - return _value; - } -}; + const u16string &GetValue() const { + return _value; + } + }; -class IdentifierToken : public IToken{ - const HashedString _value; -public: + class IdentifierToken : public IToken { + const Utilities::HashedString _value; + public: - explicit IdentifierToken(const HashedString value, unsigned int position, unsigned int length) - : IToken(position, length), - _value(value) - { - } + explicit IdentifierToken(const HashedString value, unsigned int position, unsigned int length) + : IToken(position, length), + _value(value) { + } - const TokenKind GetKind() const final{ - return TokenKind::Identifier; - } + const TokenKind GetKind() const final { + return TokenKind::Identifier; + } - const HashedString GetValue() const{ - return _value; - } -}; + const HashedString GetValue() const { + return _value; + } + }; +} #endif //PORYGONLANG_TOKEN_HPP diff --git a/src/Parser/TokenKind.hpp b/src/Parser/TokenKind.hpp index 9473a39..2b12964 100644 --- a/src/Parser/TokenKind.hpp +++ b/src/Parser/TokenKind.hpp @@ -1,59 +1,60 @@ #ifndef PORYGONLANG_TOKENKIND_HPP #define PORYGONLANG_TOKENKIND_HPP -enum class TokenKind{ - EndOfFile, - BadToken, - WhiteSpace, +namespace Porygon::Parser { + enum class TokenKind { + EndOfFile, + BadToken, + WhiteSpace, - PlusToken, - MinusToken, - SlashToken, - StarToken, - AssignmentToken, - EqualityToken, - InequalityToken, - Less, - LessEquals, - Greater, - GreaterEquals, + PlusToken, + MinusToken, + SlashToken, + StarToken, + AssignmentToken, + EqualityToken, + InequalityToken, + Less, + LessEquals, + Greater, + GreaterEquals, - OpenParenthesis, - CloseParenthesis, - OpenSquareBracket, - CloseSquareBracket, - OpenCurlyBracket, - CloseCurlyBracket, + OpenParenthesis, + CloseParenthesis, + OpenSquareBracket, + CloseSquareBracket, + OpenCurlyBracket, + CloseCurlyBracket, - PeriodToken, - CommaToken, + PeriodToken, + CommaToken, - Identifier, + Identifier, - Integer, - Float, - String, - - AndKeyword, - BreakKeyword, - DoKeyword, - ElseKeyword, - ElseIfKeyword, - EndKeyword, - FalseKeyword, - ForKeyword, - FunctionKeyword, - IfKeyword, - InKeyword, - LocalKeyword, - NilKeyword, - NotKeyword, - OrKeyword, - ReturnKeyword, - ThenKeyword, - TrueKeyword, - WhileKeyword, -}; + Integer, + Float, + String, + AndKeyword, + BreakKeyword, + DoKeyword, + ElseKeyword, + ElseIfKeyword, + EndKeyword, + FalseKeyword, + ForKeyword, + FunctionKeyword, + IfKeyword, + InKeyword, + LocalKeyword, + NilKeyword, + NotKeyword, + OrKeyword, + ReturnKeyword, + ThenKeyword, + TrueKeyword, + WhileKeyword, + }; +} #endif //PORYGONLANG_TOKENKIND_HPP diff --git a/src/Parser/TypedVariableIdentifier.hpp b/src/Parser/TypedVariableIdentifier.hpp index c289e79..e96ed71 100644 --- a/src/Parser/TypedVariableIdentifier.hpp +++ b/src/Parser/TypedVariableIdentifier.hpp @@ -4,22 +4,23 @@ #include "../Utilities/HashedString.hpp" -class TypedVariableIdentifier{ - HashedString _type; - HashedString _identifier; -public: - TypedVariableIdentifier(HashedString type, HashedString identifier) - : _type(type), _identifier(identifier) - { - } +namespace Porygon::Parser { + class TypedVariableIdentifier { + HashedString _type; + HashedString _identifier; + public: + TypedVariableIdentifier(HashedString type, HashedString identifier) + : _type(type), _identifier(identifier) { + } - HashedString GetType(){ - return _type; - } + HashedString GetType() { + return _type; + } - HashedString GetIdentifier(){ - return _identifier; - } -}; + HashedString GetIdentifier() { + return _identifier; + } + }; +} #endif //PORYGONLANG_TYPEDVARIABLEIDENTIFIER_HPP diff --git a/src/Parser/UnaryOperatorKind.hpp b/src/Parser/UnaryOperatorKind.hpp index 4ff8732..305a42e 100644 --- a/src/Parser/UnaryOperatorKind.hpp +++ b/src/Parser/UnaryOperatorKind.hpp @@ -2,9 +2,11 @@ #ifndef PORYGONLANG_UNARYOPERATORKIND_HPP #define PORYGONLANG_UNARYOPERATORKIND_HPP -enum class UnaryOperatorKind{ - Identity, - Negation, - LogicalNegation, -}; +namespace Porygon::Parser { + enum class UnaryOperatorKind { + Identity, + Negation, + LogicalNegation, + }; +} #endif //PORYGONLANG_UNARYOPERATORKIND_HPP diff --git a/src/Script.cpp b/src/Script.cpp index d42b349..04b0972 100644 --- a/src/Script.cpp +++ b/src/Script.cpp @@ -9,7 +9,7 @@ #include "Parser/Parser.hpp" #include "Binder/Binder.hpp" -Script* Script::Create(const u16string& script) { +Porygon::Script* Porygon::Script::Create(const u16string& script) { auto s = new Script(); s -> Parse(script); return s; @@ -20,22 +20,22 @@ std::u16string To_UTF16(const string &s) std::wstring_convert, char16_t> conv; return conv.from_bytes(s); } -Script *Script::Create(const string &script) { +Porygon::Script *Porygon::Script::Create(const string &script) { return Script::Create(To_UTF16(script)); } -Script::Script() { +Porygon::Script::Script() { Diagnostics = new DiagnosticsHolder(); - _evaluator = new Evaluator(this); _boundScript = nullptr; _scriptVariables = new unordered_map>(0); + _evaluator = new Evaluator(this -> _scriptVariables); } -EvalValue* Script::Evaluate() { +EvalValue* Porygon::Script::Evaluate() { return _evaluator->Evaluate(_boundScript); } -Script::~Script() { +Porygon::Script::~Script() { delete this -> Diagnostics; delete this -> _boundScript; delete this -> _evaluator; @@ -43,10 +43,10 @@ Script::~Script() { delete this->_scriptVariables; } -void Script::Parse(const u16string& script) { +void Porygon::Script::Parse(const u16string& script) { auto lexer = Lexer(script, this); auto lexResult = lexer.Lex(); - auto parser = Parser(lexResult, this); + auto parser = Parser::Parser(lexResult, this); auto parseResult = parser.Parse(); for (auto token : lexResult){ delete token; @@ -55,7 +55,7 @@ void Script::Parse(const u16string& script) { if (!Diagnostics->HasErrors()){ unordered_map scriptScope; auto bindScope = new BoundScope(&scriptScope); - this->_boundScript = Binder::Bind(this, parseResult, bindScope); + this->_boundScript = Binder::Binder::Bind(this, parseResult, bindScope); for (const auto& v : scriptScope){ this->_scriptVariables -> insert({v.first, nullptr}); delete v.second; @@ -65,59 +65,57 @@ void Script::Parse(const u16string& script) { delete parseResult; } -EvalValue *Script::GetVariable(const u16string &key) { +EvalValue *Porygon::Script::GetVariable(const u16string &key) { return _scriptVariables -> at(HashedString(key).GetHash()).get(); } -bool Script::HasVariable(const u16string &key) { +bool Porygon::Script::HasVariable(const u16string &key) { auto f = _scriptVariables->find(HashedString(key).GetHash()); return f != _scriptVariables->end(); } -EvalValue *Script::GetLastValue() { +EvalValue *Porygon::Script::GetLastValue() { return _evaluator->GetLastValue(); } -bool Script::HasFunction(const u16string &key) { +bool Porygon::Script::HasFunction(const u16string &key) { auto f = _scriptVariables->find(HashedString(key).GetHash()); return f != _scriptVariables->end() && f.operator->()->second->GetTypeClass() == TypeClass ::Function; } -shared_ptr Script::CallFunction(const u16string &key, const vector& variables) { +shared_ptr Porygon::Script::CallFunction(const u16string &key, const vector& variables) { auto var = (ScriptFunctionEvalValue*)GetVariable(key); return this->_evaluator->EvaluateFunction(var, variables); } extern "C" { - Script* CreateScript(char16_t * s){ - return Script::Create(s); + Porygon::Script* CreateScript(char16_t * s){ + return Porygon::Script::Create(s); } - void EvaluateScript(Script* script){ + void EvaluateScript(Porygon::Script* script){ script->Evaluate(); } - EvalValue* GetLastValue(Script* script){ + EvalValue* GetLastValue(Porygon::Script* script){ return script->GetLastValue(); } - bool HasVariable(Script* script, const char16_t* key){ + bool HasVariable(Porygon::Script* script, const char16_t* key){ return script->HasVariable(key); } - EvalValue* GetVariable(Script* script, const char16_t* key){ + EvalValue* GetVariable(Porygon::Script* script, const char16_t* key){ return script->GetVariable(key); } - bool HasFunction(Script* script, const char16_t* key){ + bool HasFunction(Porygon::Script* script, const char16_t* key){ return script->HasFunction(key); } - EvalValue* CallFunction(Script* script, const char16_t* key, EvalValue* parameters[], int parameterCount){ + EvalValue* CallFunction(Porygon::Script* script, const char16_t* key, EvalValue* parameters[], int parameterCount){ std::vector v(parameters, parameters + parameterCount); return script->CallFunction(key, v).get(); } -} - - +} \ No newline at end of file diff --git a/src/Script.hpp b/src/Script.hpp index a95ccf0..d21d32e 100644 --- a/src/Script.hpp +++ b/src/Script.hpp @@ -1,3 +1,5 @@ +#include + #ifndef PORYGONLANG_SCRIPT_HPP #define PORYGONLANG_SCRIPT_HPP @@ -6,49 +8,49 @@ #include #include "Diagnostics/DiagnosticsHolder.hpp" #include "Binder/BoundStatements/BoundStatement.hpp" -class Script; -class Evaluator; #include "Evaluator/Evaluator.hpp" #include "Evaluator/EvalValues/EvalValue.hpp" #include "Utilities/HashedString.hpp" using namespace std; +using namespace Porygon::Evaluation; -class Script { - friend class Evaluator; +namespace Porygon{ + class Script { + Evaluator* _evaluator; + unordered_map>* _scriptVariables; + Binder::BoundScriptStatement* _boundScript; + shared_ptr _returnType; - Evaluator* _evaluator; - unordered_map>* _scriptVariables; - BoundScriptStatement* _boundScript; - shared_ptr _returnType; + explicit Script(); + void Parse(const u16string& script); + public: + static Script* Create(const u16string& script); + static Script* Create(const string& script); + DiagnosticsHolder* Diagnostics; - explicit Script(); - void Parse(const u16string& script); -public: - static Script* Create(const u16string& script); - static Script* Create(const string& script); - DiagnosticsHolder* Diagnostics; + ~Script(); - ~Script(); + shared_ptr GetReturnType(){ + return _returnType; + } - shared_ptr GetReturnType(){ - return _returnType; - } + void SetReturnType(shared_ptr t){ + _returnType = std::move(t); + } - void SetReturnType(shared_ptr t){ - _returnType = t; - } + EvalValue* Evaluate(); - EvalValue* Evaluate(); + EvalValue* GetLastValue(); - EvalValue* GetLastValue(); + EvalValue* GetVariable(const u16string& key); + bool HasVariable(const u16string& key); - EvalValue* GetVariable(const u16string& key); - bool HasVariable(const u16string& key); + shared_ptr CallFunction(const u16string& key, const vector& variables); + bool HasFunction(const u16string& key); + }; - shared_ptr CallFunction(const u16string& key, const vector& variables); - bool HasFunction(const u16string& key); -}; +} #endif //PORYGONLANG_SCRIPT_HPP diff --git a/src/ScriptType.cpp b/src/ScriptType.cpp index d4fde09..7f0e407 100644 --- a/src/ScriptType.cpp +++ b/src/ScriptType.cpp @@ -1,27 +1,30 @@ #include "Script.hpp" -const bool ScriptType::CanBeIndexedWith(ScriptType *indexer) const{ - // String type is the only simple script type we want to - return _class == TypeClass::String && indexer->_class == TypeClass::Number && !((NumericScriptType*)indexer)->IsFloat(); +namespace Porygon{ + const bool ScriptType::CanBeIndexedWith(ScriptType *indexer) const{ + // String type is the only simple script type we want to + return _class == TypeClass::String && indexer->_class == TypeClass::Number && !((NumericScriptType*)indexer)->IsFloat(); + } + + const shared_ptr ScriptType::GetIndexedType(ScriptType *indexer) const{ + if (_class == TypeClass::String){ + return make_shared(TypeClass::String); + } + return make_shared(TypeClass::Error); + } + + extern "C"{ + ScriptType* CreateScriptType(Porygon::TypeClass t){ + return new ScriptType(t); + } + + ScriptType* CreateNumericScriptType(bool isAware, bool isFloat){ + return new NumericScriptType(isAware, isFloat); + } + + ScriptType* CreateStringScriptType(bool knownAtBind, uint32_t hash){ + return new StringScriptType(knownAtBind, hash); + } + } } -const shared_ptr ScriptType::GetIndexedType(ScriptType *indexer) const{ - if (_class == TypeClass::String){ - return make_shared(TypeClass::String); - } - return make_shared(TypeClass::Error); -} - -extern "C"{ - ScriptType* CreateScriptType(TypeClass t){ - return new ScriptType(t); - } - - ScriptType* CreateNumericScriptType(bool isAware, bool isFloat){ - return new NumericScriptType(isAware, isFloat); - } - - ScriptType* CreateStringScriptType(bool knownAtBind, uint32_t hash){ - return new StringScriptType(knownAtBind, hash); - } -} \ No newline at end of file diff --git a/src/ScriptType.hpp b/src/ScriptType.hpp index 796bb07..1b8f894 100644 --- a/src/ScriptType.hpp +++ b/src/ScriptType.hpp @@ -12,145 +12,147 @@ using namespace std; -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; +namespace Porygon{ + enum class TypeClass{ + Error, + Nil, + Number, + Bool, + String, + Function, + UserData, + Table, }; - virtual bool operator ==(ScriptType* b) const{ - return _class == b->_class; + 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 "Shouldn't be possible"; + } }; - virtual bool operator !=(const ScriptType& b) const{ - return ! (operator==(b)); - } - virtual bool operator !=(ScriptType* b) const{ - return ! (operator==(b)); - } + 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; + } - virtual const bool CanBeIndexedWith(ScriptType* indexer) const; - virtual const bool CanBeIndexedWithIdentifier(uint32_t hash) const{ - return false; - } + const bool IsAwareOfFloat() const{ + return _awareOfFloat; + } - virtual const shared_ptr GetIndexedType(ScriptType* indexer) const; - virtual const shared_ptr GetIndexedType(uint32_t hash) const{ - throw "Shouldn't be possible"; - } -}; + const bool IsFloat() const{ + return _isFloat; + } + }; -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; - } + 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 IsAwareOfFloat() const{ - return _awareOfFloat; - } + const bool IsKnownAtBind() const{ + return _isKnownAtBind; + } - const bool IsFloat() const{ - return _isFloat; - } -}; + const uint32_t GetHashValue() const{ + return _hashValue; + } + }; -class StringScriptType : public ScriptType{ - bool _isKnownAtBind; - uint32_t _hashValue; -public: - explicit StringScriptType(bool knownAtBind, uint32_t hashValue): ScriptType(TypeClass::String){ - _isKnownAtBind = knownAtBind; - _hashValue = hashValue; - } + class FunctionScriptType : public ScriptType{ + shared_ptr _returnType; + vector> _parameterTypes; + vector> _parameterKeys; + int _scopeIndex; + public: + FunctionScriptType(std::shared_ptr returnType, vector> parameterTypes, + vector> parameterKeys, int scopeIndex) + : ScriptType(TypeClass::Function){ + _returnType = std::move(returnType); + _parameterTypes = std::move(parameterTypes); + _parameterKeys = std::move(parameterKeys); + _scopeIndex = scopeIndex; + } + const shared_ptr GetReturnType() const{ + return _returnType; + } - const bool IsKnownAtBind() const{ - return _isKnownAtBind; - } + void SetReturnType(shared_ptr t){ + _returnType = std::move(t); + } - const uint32_t GetHashValue() const{ - return _hashValue; - } -}; + const vector> GetParameterTypes() const{ + return _parameterTypes; + } -class FunctionScriptType : public ScriptType{ - shared_ptr _returnType; - vector> _parameterTypes; - vector> _parameterKeys; - int _scopeIndex; -public: - FunctionScriptType(std::shared_ptr returnType, vector> parameterTypes, - vector> parameterKeys, int scopeIndex) - : ScriptType(TypeClass::Function){ - _returnType = std::move(returnType); - _parameterTypes = std::move(parameterTypes); - _parameterKeys = std::move(parameterKeys); - _scopeIndex = scopeIndex; - } - const shared_ptr GetReturnType() const{ - return _returnType; - } + const vector> GetParameterKeys() const{ + return _parameterKeys; + } - void SetReturnType(shared_ptr t){ - _returnType = std::move(t); - } + const int GetScopeIndex() const{ + return _scopeIndex; + } + }; - const vector> GetParameterTypes() const{ - return _parameterTypes; - } + 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 vector> GetParameterKeys() const{ - return _parameterKeys; - } + const bool CanBeIndexedWith(ScriptType* indexer) const final{ + return indexer->GetClass() == TypeClass ::Number; + } - const int GetScopeIndex() const{ - return _scopeIndex; - } -}; - -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{ - return indexer->GetClass() == TypeClass ::Number; - } - - const shared_ptr GetIndexedType(ScriptType* indexer) const final{ - return _valueType; - } -}; + const shared_ptr GetIndexedType(ScriptType* indexer) const final{ + return _valueType; + } + }; +} #endif //PORYGONLANG_SCRIPTTYPE_HPP diff --git a/src/TableScriptType.hpp b/src/TableScriptType.hpp index bc6929f..ca04433 100644 --- a/src/TableScriptType.hpp +++ b/src/TableScriptType.hpp @@ -4,52 +4,54 @@ #include #include "Binder/BoundVariables/BoundVariable.hpp" -class TableScriptType : public ScriptType{ - const unordered_map* _values; - const int _localVariableCount; -public: - explicit TableScriptType(unordered_map* values, int localVariableCount) - : ScriptType(TypeClass::Table), - _values(values), - _localVariableCount(localVariableCount) +namespace Porygon{ + class TableScriptType : public ScriptType{ + const unordered_map* _values; + const int _localVariableCount; + public: + explicit TableScriptType(unordered_map* values, int localVariableCount) + : ScriptType(TypeClass::Table), + _values(values), + _localVariableCount(localVariableCount) {} - ~TableScriptType() final{ - for (auto i : *_values){ - delete i.second; + ~TableScriptType() final{ + for (auto i : *_values){ + delete i.second; + } + delete _values; } - delete _values; - } - const bool CanBeIndexedWith(ScriptType* indexer) const final{ - return indexer->GetClass() == TypeClass ::String; - } - - const bool CanBeIndexedWithIdentifier(uint32_t hash) const final{ - return true; - } - - const shared_ptr GetIndexedType(ScriptType* indexer) const final{ - auto stringKey = (StringScriptType*)indexer; - if (stringKey->IsKnownAtBind()){ - return _values-> at(stringKey->GetHashValue())->GetType(); + const bool CanBeIndexedWith(ScriptType* indexer) const final{ + return indexer->GetClass() == TypeClass ::String; } - throw "TODO: indexing with dynamic keys"; - } - const shared_ptr GetIndexedType(uint32_t hash) const final{ - return _values-> at(hash)->GetType(); - } + const bool CanBeIndexedWithIdentifier(uint32_t hash) const final{ + return true; + } - const unordered_map* GetValues() const{ - return _values; - } + const shared_ptr GetIndexedType(ScriptType* indexer) const final{ + auto stringKey = (StringScriptType*)indexer; + if (stringKey->IsKnownAtBind()){ + return _values-> at(stringKey->GetHashValue())->GetType(); + } + throw "TODO: indexing with dynamic keys"; + } - const int GetLocalVariableCount() const{ - return _localVariableCount; - } + const shared_ptr GetIndexedType(uint32_t hash) const final{ + return _values-> at(hash)->GetType(); + } -}; + const unordered_map* GetValues() const{ + return _values; + } + + const int GetLocalVariableCount() const{ + return _localVariableCount; + } + + }; +} #include "ScriptType.hpp" diff --git a/src/UserData/UserData.cpp b/src/UserData/UserData.cpp index 50e83a8..7cc91ce 100644 --- a/src/UserData/UserData.cpp +++ b/src/UserData/UserData.cpp @@ -2,19 +2,21 @@ #include "UserData.hpp" #include "UserDataStorage.hpp" -extern "C"{ - void RegisterUserDataType(uint32_t id){ +namespace Porygon::UserData { + extern "C" { + void RegisterUserDataType(uint32_t id) { auto ud = new UserData({}); UserDataStorage::RegisterType(id, ud); } - void RegisterUserDataField(uint32_t typeId, uint32_t fieldId, UserDataField* field){ + void RegisterUserDataField(uint32_t typeId, uint32_t fieldId, UserDataField *field) { auto ud = UserDataStorage::GetUserDataType(typeId); - ud -> CreateField(fieldId, field); + ud->CreateField(fieldId, field); } - int32_t GetUserDataFieldCount(uint32_t typeId){ + int32_t GetUserDataFieldCount(uint32_t typeId) { auto ud = UserDataStorage::GetUserDataType(typeId); - return ud ->GetFieldCount(); + return ud->GetFieldCount(); + } } } \ No newline at end of file diff --git a/src/UserData/UserData.hpp b/src/UserData/UserData.hpp index 8617979..c6df473 100644 --- a/src/UserData/UserData.hpp +++ b/src/UserData/UserData.hpp @@ -5,29 +5,31 @@ #include #include "UserDataField.hpp" -class UserData { - std::unordered_map _fields; -public: - explicit UserData(std::unordered_map fields){ - _fields = std::move(fields); - } +namespace Porygon::UserData { + class UserData { + std::unordered_map _fields; + public: + explicit UserData(std::unordered_map fields) { + _fields = std::move(fields); + } - bool ContainsField(uint32_t fieldId){ - return _fields.find(fieldId) != _fields.end(); - } + bool ContainsField(uint32_t fieldId) { + return _fields.find(fieldId) != _fields.end(); + } - UserDataField* GetField(uint32_t fieldId){ - return _fields[fieldId]; - } + UserDataField *GetField(uint32_t fieldId) { + return _fields[fieldId]; + } - void CreateField(uint32_t fieldId, UserDataField* field){ - _fields.insert({fieldId, field}); - } + void CreateField(uint32_t fieldId, UserDataField *field) { + _fields.insert({fieldId, field}); + } - int32_t GetFieldCount(){ - return _fields.size(); - } -}; + int32_t GetFieldCount() { + return _fields.size(); + } + }; +} #endif //PORYGONLANG_USERDATA_HPP diff --git a/src/UserData/UserDataField.cpp b/src/UserData/UserDataField.cpp index dce665d..6275dc4 100644 --- a/src/UserData/UserDataField.cpp +++ b/src/UserData/UserDataField.cpp @@ -1,8 +1,11 @@ #include "UserDataField.hpp" -extern "C"{ - UserDataField* CreateUserDataField(ScriptType* type, EvalValue* (*getter)(void* obj), void (*setter)(void* obj, EvalValue* val)){ +namespace Porygon::UserData { + extern "C" { + UserDataField * + CreateUserDataField(ScriptType *type, Evaluation::EvalValue *(*getter)(void *obj), void (*setter)(void *obj, Evaluation::EvalValue *val)) { return new UserDataField(type, getter, setter); } + } } \ No newline at end of file diff --git a/src/UserData/UserDataField.hpp b/src/UserData/UserDataField.hpp index d79ad2f..b161c76 100644 --- a/src/UserData/UserDataField.hpp +++ b/src/UserData/UserDataField.hpp @@ -6,37 +6,39 @@ #include "../Evaluator/EvalValues/EvalValue.hpp" #include "../Evaluator/EvalValues/NumericEvalValue.hpp" -class UserDataField { - shared_ptr _type; - EvalValue* (*_get)(void* obj); - void (*_set)(void* obj, EvalValue* val); -public: - UserDataField(ScriptType* type, EvalValue* (*getter)(void* obj), void (*setter)(void* obj, EvalValue* val)){ - _type = shared_ptr(type); - _get = getter; - _set = setter; - } +namespace Porygon::UserData{ + class UserDataField { + shared_ptr _type; + Evaluation::EvalValue* (*_get)(void* obj); + void (*_set)(void* obj, Evaluation::EvalValue* val); + public: + UserDataField(ScriptType* type, Evaluation::EvalValue* (*getter)(void* obj), void (*setter)(void* obj, Evaluation::EvalValue* val)){ + _type = shared_ptr(type); + _get = getter; + _set = setter; + } - shared_ptr GetType(){ - return _type; - } + shared_ptr GetType(){ + return _type; + } - bool HasGetter(){ - return _get != nullptr; - } + bool HasGetter(){ + return _get != nullptr; + } - EvalValue* Get(void* obj){ - return this ->_get(obj); - } + Evaluation::EvalValue* Get(void* obj){ + return this ->_get(obj); + } - bool HasSetter(){ - return _set != nullptr; - } + bool HasSetter(){ + return _set != nullptr; + } - void Set(void* obj, EvalValue* val){ - this->_set(obj, val); - } -}; + void Set(void* obj, Evaluation::EvalValue* val){ + this->_set(obj, val); + } + }; +} #endif //PORYGONLANG_USERDATAFIELD_HPP diff --git a/src/UserData/UserDataScriptType.hpp b/src/UserData/UserDataScriptType.hpp index bd50211..a043879 100644 --- a/src/UserData/UserDataScriptType.hpp +++ b/src/UserData/UserDataScriptType.hpp @@ -8,46 +8,49 @@ #include "UserData.hpp" #include "UserDataStorage.hpp" -class UserDataScriptType : public ScriptType{ - shared_ptr _userData; -public: - explicit UserDataScriptType(uint32_t id) : ScriptType(TypeClass::UserData){ - _userData = UserDataStorage::GetUserDataType(id); - } - explicit UserDataScriptType(shared_ptr ud) : ScriptType(TypeClass::UserData){ - _userData = std::move(ud); - } - - const bool CanBeIndexedWith(ScriptType* indexer) const final{ - if (indexer->GetClass() != TypeClass ::String){ - return false; +namespace Porygon::UserData { + class UserDataScriptType : public ScriptType { + shared_ptr _userData; + public: + explicit UserDataScriptType(uint32_t id) : ScriptType(TypeClass::UserData) { + _userData = UserDataStorage::GetUserDataType(id); } - auto str = (StringScriptType*)indexer; - if (!str->IsKnownAtBind()) - return false; - return _userData->ContainsField(str->GetHashValue()); - } - const bool CanBeIndexedWithIdentifier(uint32_t hash) const final{ - return true; - } - - UserDataField* GetField(uint32_t id){ - return _userData -> GetField(id); - } - - const shared_ptr GetIndexedType(ScriptType* indexer) const final{ - auto stringKey = (StringScriptType*)indexer; - if (stringKey->IsKnownAtBind()){ - return _userData->GetField(stringKey->GetHashValue())->GetType(); + explicit UserDataScriptType(shared_ptr ud) : ScriptType(TypeClass::UserData) { + _userData = std::move(ud); } - throw "TODO: indexing with dynamic keys"; - } - const shared_ptr GetIndexedType(uint32_t hash) const final{ - return _userData->GetField(hash)->GetType(); - } -}; + const bool CanBeIndexedWith(ScriptType *indexer) const final { + if (indexer->GetClass() != TypeClass::String) { + return false; + } + auto str = (StringScriptType *) indexer; + if (!str->IsKnownAtBind()) + return false; + return _userData->ContainsField(str->GetHashValue()); + } + + const bool CanBeIndexedWithIdentifier(uint32_t hash) const final { + return true; + } + + UserDataField *GetField(uint32_t id) { + return _userData->GetField(id); + } + + const shared_ptr GetIndexedType(ScriptType *indexer) const final { + auto stringKey = (StringScriptType *) indexer; + if (stringKey->IsKnownAtBind()) { + return _userData->GetField(stringKey->GetHashValue())->GetType(); + } + throw "TODO: indexing with dynamic keys"; + } + + const shared_ptr GetIndexedType(uint32_t hash) const final { + return _userData->GetField(hash)->GetType(); + } + }; +} #endif //PORYGONLANG_USERDATASCRIPTTYPE_HPP diff --git a/src/UserData/UserDataStorage.cpp b/src/UserData/UserDataStorage.cpp index b008b02..466ae94 100644 --- a/src/UserData/UserDataStorage.cpp +++ b/src/UserData/UserDataStorage.cpp @@ -1,4 +1,6 @@ #include "UserDataStorage.hpp" -UserDataStorage::_internalDataStorage UserDataStorage::_internal = UserDataStorage::_internalDataStorage(); +namespace Porygon::UserData { + UserDataStorage::_internalDataStorage UserDataStorage::_internal = UserDataStorage::_internalDataStorage(); +} \ No newline at end of file diff --git a/src/UserData/UserDataStorage.hpp b/src/UserData/UserDataStorage.hpp index 603e1d3..319e833 100644 --- a/src/UserData/UserDataStorage.hpp +++ b/src/UserData/UserDataStorage.hpp @@ -5,26 +5,28 @@ #include #include "UserData.hpp" -class UserDataStorage { - class _internalDataStorage{ +namespace Porygon::UserData { + class UserDataStorage { + class _internalDataStorage { + public: + std::unordered_map> _userData; + }; + + static _internalDataStorage _internal; + public: - std::unordered_map> _userData; + static void RegisterType(uint32_t i, UserData *ud) { + UserDataStorage::_internal._userData.insert({i, shared_ptr(ud)}); + } + + static bool HasUserDataType(uint32_t i) { + return UserDataStorage::_internal._userData.find(i) != UserDataStorage::_internal._userData.end(); + } + + static shared_ptr GetUserDataType(uint32_t i) { + return UserDataStorage::_internal._userData[i]; + } }; - static _internalDataStorage _internal; - -public: - static void RegisterType(uint32_t i, UserData* ud){ - UserDataStorage::_internal._userData.insert({i, shared_ptr(ud)}); - } - - static bool HasUserDataType(uint32_t i){ - return UserDataStorage::_internal._userData.find(i) != UserDataStorage::_internal._userData.end(); - } - - static shared_ptr GetUserDataType(uint32_t i){ - return UserDataStorage::_internal._userData[i]; - } -}; - +} #endif //PORYGONLANG_USERDATASTORAGE_HPP diff --git a/src/UserData/UserDataValue.cpp b/src/UserData/UserDataValue.cpp index 83df841..2d444b1 100644 --- a/src/UserData/UserDataValue.cpp +++ b/src/UserData/UserDataValue.cpp @@ -1,8 +1,10 @@ #include "UserDataValue.hpp" -extern "C"{ - UserDataValue* CreateUserDataEvalValue(uint32_t typeHash, void* obj){ +namespace Porygon::UserData { + extern "C" { + UserDataValue *CreateUserDataEvalValue(uint32_t typeHash, void *obj) { return new UserDataValue(typeHash, obj); } + } } \ No newline at end of file diff --git a/src/UserData/UserDataValue.hpp b/src/UserData/UserDataValue.hpp index e6ef66a..afe09a5 100644 --- a/src/UserData/UserDataValue.hpp +++ b/src/UserData/UserDataValue.hpp @@ -7,57 +7,56 @@ #include "UserData.hpp" #include "UserDataStorage.hpp" -class UserDataValue : public EvalValue{ - const shared_ptr _userData; - void* _obj; -public: - UserDataValue(shared_ptr userData, void* obj) - : _userData(std::move(userData)) - { - _obj = obj; - } +namespace Porygon::UserData { + class UserDataValue : public Evaluation::EvalValue { + const shared_ptr _userData; + void *_obj; + public: + UserDataValue(shared_ptr userData, void *obj) + : _userData(std::move(userData)) { + _obj = obj; + } - UserDataValue(uint32_t userDataId, void* obj) - : _userData(UserDataStorage::GetUserDataType(userDataId)) - { - _obj = obj; - } + UserDataValue(uint32_t userDataId, void *obj) + : _userData(UserDataStorage::GetUserDataType(userDataId)) { + _obj = obj; + } - const TypeClass GetTypeClass() const final{ - return TypeClass ::UserData; - } + const TypeClass GetTypeClass() const final { + return TypeClass::UserData; + } - const bool operator ==(EvalValue* b) const final { - if (b->GetTypeClass() != TypeClass::UserData) - return false; - return _obj == ((UserDataValue*)b)->_obj; - } + const bool operator==(EvalValue *b) const final { + if (b->GetTypeClass() != TypeClass::UserData) + return false; + return _obj == ((UserDataValue *) b)->_obj; + } - const shared_ptr Clone() const final{ - return make_shared(_userData, _obj); - } + const shared_ptr Clone() const final { + return make_shared(_userData, _obj); + } - const std::size_t GetHashCode() const final{ - return reinterpret_cast(_obj); - } + const std::size_t GetHashCode() const final { + return reinterpret_cast(_obj); + } - const shared_ptr IndexValue(EvalValue* val) const final { - auto fieldId = val->GetHashCode(); - auto field = _userData->GetField(fieldId); - return shared_ptr(field->Get(_obj)); - } + const shared_ptr IndexValue(EvalValue *val) const final { + auto fieldId = val->GetHashCode(); + auto field = _userData->GetField(fieldId); + return shared_ptr(field->Get(_obj)); + } - const shared_ptr IndexValue(uint32_t hash) const final{ - auto field = _userData->GetField(hash); - return shared_ptr(field->Get(_obj)); - } - - void SetIndexValue(EvalValue *key, const shared_ptr& value) const final{ - auto fieldId = key->GetHashCode(); - auto field = _userData->GetField(fieldId); - field -> Set(_obj, value.get()); - } -}; + const shared_ptr IndexValue(uint32_t hash) const final { + auto field = _userData->GetField(hash); + return shared_ptr(field->Get(_obj)); + } + void SetIndexValue(EvalValue *key, const shared_ptr &value) const final { + auto fieldId = key->GetHashCode(); + auto field = _userData->GetField(fieldId); + field->Set(_obj, value.get()); + } + }; +} #endif //PORYGONLANG_USERDATAVALUE_HPP diff --git a/src/Utilities/HashedString.hpp b/src/Utilities/HashedString.hpp index 56d64ce..eb3d96d 100644 --- a/src/Utilities/HashedString.hpp +++ b/src/Utilities/HashedString.hpp @@ -4,41 +4,43 @@ #include -class HashedString{ - const uint32_t _hash; -public: - explicit HashedString(const std::u16string& s) : _hash(ConstHash(s.c_str())){ - } - explicit HashedString(char16_t const *input) : _hash(ConstHash(input)){ - } +namespace Porygon::Utilities{ + class HashedString{ + const uint32_t _hash; + public: + explicit HashedString(const std::u16string& s) : _hash(ConstHash(s.c_str())){ + } + explicit HashedString(char16_t const *input) : _hash(ConstHash(input)){ + } - explicit HashedString(char const *input) : _hash(ConstHash(input)){ - } + explicit HashedString(char const *input) : _hash(ConstHash(input)){ + } - HashedString(const HashedString& b) = default; + HashedString(const HashedString& b) = default; - static uint32_t constexpr ConstHash(char16_t const *input) { - return *input ? - static_cast(*input) + 33 * ConstHash(input + 1) : - 5381; - } + static uint32_t constexpr ConstHash(char16_t const *input) { + return *input ? + static_cast(*input) + 33 * ConstHash(input + 1) : + 5381; + } - static uint32_t constexpr ConstHash(char const *input) { - return *input ? - static_cast(*input) + 33 * ConstHash(input + 1) : - 5381; - } + static uint32_t constexpr ConstHash(char const *input) { + return *input ? + static_cast(*input) + 33 * ConstHash(input + 1) : + 5381; + } - const uint32_t GetHash() const{ - return _hash; - } + const uint32_t GetHash() const{ + return _hash; + } - bool operator==(const HashedString& b) const{ - return _hash == b._hash; - } - bool operator!=(const HashedString& b) const{ - return _hash != b._hash; - } -}; + bool operator==(const HashedString& b) const{ + return _hash == b._hash; + } + bool operator!=(const HashedString& b) const{ + return _hash != b._hash; + } + }; +} #endif //PORYGONLANG_HASHEDSTRING_HPP diff --git a/tests/integration/ConditionalTests.cpp b/tests/integration/ConditionalTests.cpp index 10348c2..78846c6 100644 --- a/tests/integration/ConditionalTests.cpp +++ b/tests/integration/ConditionalTests.cpp @@ -2,6 +2,8 @@ #include #include "../src/Script.hpp" +using namespace Porygon; + TEST_CASE( "Basic conditional", "[integration]" ) { Script* script = Script::Create("if true then foo = true end"); REQUIRE(!script->Diagnostics -> HasErrors()); diff --git a/tests/integration/DiagnosticsTests.cpp b/tests/integration/DiagnosticsTests.cpp index 7a37c9c..6ab5b30 100644 --- a/tests/integration/DiagnosticsTests.cpp +++ b/tests/integration/DiagnosticsTests.cpp @@ -3,6 +3,7 @@ #include #include "../src/Script.hpp" +using namespace Porygon; TEST_CASE( "Diagnostic invalid character", "[integration]" ) { auto script = Script::Create("1 + 1 @"); REQUIRE(script->Diagnostics -> HasErrors()); diff --git a/tests/integration/EqualityOperationsTests.cpp b/tests/integration/EqualityOperationsTests.cpp index 7edf93f..d2fbc79 100644 --- a/tests/integration/EqualityOperationsTests.cpp +++ b/tests/integration/EqualityOperationsTests.cpp @@ -3,6 +3,7 @@ #include #include "../src/Script.hpp" +using namespace Porygon; TEST_CASE( "True Equals True", "[integration]" ) { auto script = Script::Create("true == true"); REQUIRE(!script->Diagnostics -> HasErrors()); diff --git a/tests/integration/Functions.cpp b/tests/integration/Functions.cpp index 12b0415..ed4ee7c 100644 --- a/tests/integration/Functions.cpp +++ b/tests/integration/Functions.cpp @@ -2,6 +2,8 @@ #include #include "../src/Script.hpp" +using namespace Porygon; + TEST_CASE( "Define script function", "[integration]" ) { Script* script = Script::Create("function add(number a, number b) a + b end"); REQUIRE(!script->Diagnostics -> HasErrors()); diff --git a/tests/integration/IndexTests.cpp b/tests/integration/IndexTests.cpp index a60a895..8405c16 100644 --- a/tests/integration/IndexTests.cpp +++ b/tests/integration/IndexTests.cpp @@ -1,6 +1,7 @@ #ifdef TESTS_BUILD #include #include "../src/Script.hpp" +using namespace Porygon; TEST_CASE( "String indexing", "[integration]" ) { auto script = Script::Create("'foobar'[4]"); diff --git a/tests/integration/LogicalOperationsTests.cpp b/tests/integration/LogicalOperationsTests.cpp index 577445f..c7c1dd4 100644 --- a/tests/integration/LogicalOperationsTests.cpp +++ b/tests/integration/LogicalOperationsTests.cpp @@ -1,6 +1,7 @@ #ifdef TESTS_BUILD #include #include "../src/Script.hpp" +using namespace Porygon; TEST_CASE( "Basic True", "[integration]" ) { auto script = Script::Create("true"); diff --git a/tests/integration/NumericalOperationsTests.cpp b/tests/integration/NumericalOperationsTests.cpp index 57fc9f9..22febc4 100644 --- a/tests/integration/NumericalOperationsTests.cpp +++ b/tests/integration/NumericalOperationsTests.cpp @@ -1,6 +1,7 @@ #ifdef TESTS_BUILD #include #include "../src/Script.hpp" +using namespace Porygon; TEST_CASE( "Integer Negation", "[integration]" ) { auto script = Script::Create("-60"); diff --git a/tests/integration/StringOperationsTests.cpp b/tests/integration/StringOperationsTests.cpp index 8cb3e3d..009c65a 100644 --- a/tests/integration/StringOperationsTests.cpp +++ b/tests/integration/StringOperationsTests.cpp @@ -3,6 +3,7 @@ #include #include "../src/Script.hpp" +using namespace Porygon; TEST_CASE( "Simple String", "[integration]" ) { auto script = Script::Create("\"foo bar\""); diff --git a/tests/integration/Tables.cpp b/tests/integration/Tables.cpp index afabd5c..89c5157 100644 --- a/tests/integration/Tables.cpp +++ b/tests/integration/Tables.cpp @@ -2,6 +2,7 @@ #include #include "../src/Script.hpp" #include "../../src/Evaluator/EvalValues/TableEvalValue.hpp" +using namespace Porygon; TEST_CASE( "Create empty table", "[integration]" ) { Script* script = Script::Create("table = {}"); diff --git a/tests/integration/UserData.cpp b/tests/integration/UserData.cpp index 282f69b..6b82134 100644 --- a/tests/integration/UserData.cpp +++ b/tests/integration/UserData.cpp @@ -5,6 +5,9 @@ #include "../../src/UserData/UserData.hpp" #include "../../src/UserData/UserDataStorage.hpp" #include "../../src/UserData/UserDataValue.hpp" +using namespace Porygon; +using namespace Porygon::UserData; +using namespace Porygon::Utilities; class UserDataTestObject{ public: @@ -18,8 +21,8 @@ public: ((UserDataTestObject*)obj)->foo = val->EvaluateInteger(); } - static UserData* CreateData(){ - return new UserData({ + static Porygon::UserData::UserData* CreateData(){ + return new Porygon::UserData::UserData({ { HashedString::ConstHash("foo"), new UserDataField(new NumericScriptType(true, false), GetFoo, SetFoo) diff --git a/tests/integration/Variables.cpp b/tests/integration/Variables.cpp index ecfe129..8bdb145 100644 --- a/tests/integration/Variables.cpp +++ b/tests/integration/Variables.cpp @@ -1,6 +1,7 @@ #ifdef TESTS_BUILD #include #include "../src/Script.hpp" +using namespace Porygon; TEST_CASE( "Create script variable", "[integration]" ) { Script* script = Script::Create("foo = true"); diff --git a/tests/parser/LexerTests.cpp b/tests/parser/LexerTests.cpp index be2e291..5e5d7ac 100644 --- a/tests/parser/LexerTests.cpp +++ b/tests/parser/LexerTests.cpp @@ -3,6 +3,7 @@ #include #include #include "../../src/Parser/Lexer.hpp" +using namespace Porygon::Parser; TEST_CASE( "When at end of script return terminator", "[lexer]" ) { Lexer lexer = Lexer(u"", nullptr); diff --git a/tests/parser/ParserTests.cpp b/tests/parser/ParserTests.cpp index ba5b3b5..b791094 100644 --- a/tests/parser/ParserTests.cpp +++ b/tests/parser/ParserTests.cpp @@ -3,6 +3,7 @@ #ifdef TESTS_BUILD #include #include "../../src/Parser/Parser.hpp" +using namespace Porygon::Parser; TEST_CASE( "Parse single true keyword", "[parser]" ) { vector v {new SimpleToken(TokenKind::TrueKeyword,0,0), new SimpleToken(TokenKind::EndOfFile,0,0)};