Added namespaces to most classes, general cleanup
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Deukhoofd 2019-06-17 18:35:12 +02:00
parent 21d3329c55
commit fde102d954
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
66 changed files with 4301 additions and 3909 deletions

View File

@ -6,6 +6,9 @@
#include "../UserData/UserDataScriptType.hpp" #include "../UserData/UserDataScriptType.hpp"
#include <memory> #include <memory>
using namespace Porygon::Parser;
namespace Porygon::Binder {
BoundScriptStatement *Binder::Bind(Script *script, const ParsedScriptStatement *s, BoundScope *scriptScope) { BoundScriptStatement *Binder::Bind(Script *script, const ParsedScriptStatement *s, BoundScope *scriptScope) {
auto binder = Binder(); auto binder = Binder();
binder._scriptData = script; binder._scriptData = script;
@ -25,16 +28,25 @@ Binder::~Binder() {
BoundStatement *Binder::BindStatement(const ParsedStatement *statement) { BoundStatement *Binder::BindStatement(const ParsedStatement *statement) {
switch (statement->GetKind()) { switch (statement->GetKind()) {
case ParsedStatementKind ::Script: throw; // This shouldn't happen. case ParsedStatementKind::Script:
case ParsedStatementKind ::Block: return this -> BindBlockStatement(statement); throw; // This shouldn't happen.
case ParsedStatementKind ::Expression: return this -> BindExpressionStatement(statement); case ParsedStatementKind::Block:
case ParsedStatementKind::Assignment: return this -> BindAssignmentStatement(statement); return this->BindBlockStatement(statement);
case ParsedStatementKind::IndexAssignment: return this -> BindIndexAssignmentStatement(statement); case ParsedStatementKind::Expression:
case ParsedStatementKind ::FunctionDeclaration: return this->BindFunctionDeclarationStatement(statement); return this->BindExpressionStatement(statement);
case ParsedStatementKind::Return: return this -> BindReturnStatement(statement); case ParsedStatementKind::Assignment:
case ParsedStatementKind::Conditional: return this -> BindConditionalStatement(statement); 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(); case ParsedStatementKind::Bad:
return new BoundBadStatement();
} }
} }
@ -64,9 +76,9 @@ BoundStatement* Binder::BindAssignmentStatement(const ParsedStatement *statement
if (assignment.GetResult() == VariableAssignmentResult::Ok) { if (assignment.GetResult() == VariableAssignmentResult::Ok) {
auto key = assignment.GetKey(); auto key = assignment.GetKey();
return new BoundAssignmentStatement(key, boundExpression); return new BoundAssignmentStatement(key, boundExpression);
} } else {
else{ this->_scriptData->Diagnostics->LogError(DiagnosticCode::CantAssignVariable, statement->GetStartPosition(),
this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::CantAssignVariable, statement->GetStartPosition(), statement->GetLength()); statement->GetLength());
return new BoundBadStatement(); return new BoundBadStatement();
} }
} }
@ -82,8 +94,10 @@ BoundStatement *Binder::BindIndexAssignmentStatement(const ParsedStatement *stat
} }
auto valueExpression = this->BindExpression(s->GetValueExpression()); auto valueExpression = this->BindExpression(s->GetValueExpression());
auto boundIndexType = indexable->GetType(); auto boundIndexType = indexable->GetType();
if (boundIndexType ->GetClass() != TypeClass ::Error && boundIndexType->operator!=(valueExpression->GetType().get())){ if (boundIndexType->GetClass() != TypeClass::Error &&
this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidTableValueType, statement->GetStartPosition(), statement->GetLength()); boundIndexType->operator!=(valueExpression->GetType().get())) {
this->_scriptData->Diagnostics->LogError(DiagnosticCode::InvalidTableValueType,
statement->GetStartPosition(), statement->GetLength());
return new BoundBadStatement(); return new BoundBadStatement();
} }
@ -93,14 +107,17 @@ BoundStatement *Binder::BindIndexAssignmentStatement(const ParsedStatement *stat
std::shared_ptr<ScriptType> ParseTypeIdentifier(HashedString s) { std::shared_ptr<ScriptType> ParseTypeIdentifier(HashedString s) {
auto hash = s.GetHash(); auto hash = s.GetHash();
switch (hash) { switch (hash) {
case HashedString::ConstHash("number"): return std::make_shared<NumericScriptType>(false, false); case HashedString::ConstHash("number"):
case HashedString::ConstHash("bool"): return std::make_shared<ScriptType>(TypeClass::Bool); return std::make_shared<NumericScriptType>(false, false);
case HashedString::ConstHash("string"): return std::make_shared<StringScriptType>(false, 0); case HashedString::ConstHash("bool"):
return std::make_shared<ScriptType>(TypeClass::Bool);
case HashedString::ConstHash("string"):
return std::make_shared<StringScriptType>(false, 0);
default: default:
if (!UserDataStorage::HasUserDataType(hash)){ if (!UserData::UserDataStorage::HasUserDataType(hash)) {
return nullptr; return nullptr;
} }
return std::make_shared<UserDataScriptType>(hash); return std::make_shared<UserData::UserDataScriptType>(hash);
} }
} }
@ -116,15 +133,15 @@ BoundStatement *Binder::BindFunctionDeclarationStatement(const ParsedStatement *
auto var = parameters->at(i); auto var = parameters->at(i);
auto parsedType = ParseTypeIdentifier(var->GetType()); auto parsedType = ParseTypeIdentifier(var->GetType());
if (parsedType == nullptr) { if (parsedType == nullptr) {
this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidTypeName, statement->GetStartPosition(), statement->GetLength()); this->_scriptData->Diagnostics->LogError(DiagnosticCode::InvalidTypeName, statement->GetStartPosition(),
statement->GetLength());
return new BoundBadStatement(); return new BoundBadStatement();
} }
parameterTypes.at(i) = parsedType; parameterTypes.at(i) = parsedType;
auto parameterAssignment = this->_scope->CreateExplicitLocal(var->GetIdentifier().GetHash(), parsedType); auto parameterAssignment = this->_scope->CreateExplicitLocal(var->GetIdentifier().GetHash(), parsedType);
if (parameterAssignment.GetResult() == VariableAssignmentResult::Ok) { if (parameterAssignment.GetResult() == VariableAssignmentResult::Ok) {
parameterKeys.at(i) = std::shared_ptr<BoundVariableKey>(parameterAssignment.GetKey()); parameterKeys.at(i) = std::shared_ptr<BoundVariableKey>(parameterAssignment.GetKey());
} } else {
else{
//TODO: log error //TODO: log error
continue; continue;
} }
@ -137,7 +154,8 @@ BoundStatement *Binder::BindFunctionDeclarationStatement(const ParsedStatement *
auto assignment = this->_scope->AssignVariable(identifier.GetHash(), type); auto assignment = this->_scope->AssignVariable(identifier.GetHash(), type);
if (assignment.GetResult() != VariableAssignmentResult::Ok) { if (assignment.GetResult() != VariableAssignmentResult::Ok) {
this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::CantAssignVariable, statement->GetStartPosition(), statement->GetLength()); this->_scriptData->Diagnostics->LogError(DiagnosticCode::CantAssignVariable, statement->GetStartPosition(),
statement->GetLength());
return new BoundBadStatement(); return new BoundBadStatement();
} }
auto boundBlock = this->BindBlockStatement(functionStatement->GetBlock()); auto boundBlock = this->BindBlockStatement(functionStatement->GetBlock());
@ -155,7 +173,8 @@ BoundStatement *Binder::BindReturnStatement(const ParsedStatement* statement){
currentReturnType = this->_currentFunction->GetReturnType(); currentReturnType = this->_currentFunction->GetReturnType();
} }
if (expression == nullptr && currentReturnType != nullptr) { if (expression == nullptr && currentReturnType != nullptr) {
this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidReturnType, statement->GetStartPosition(), statement->GetLength()); this->_scriptData->Diagnostics->LogError(DiagnosticCode::InvalidReturnType, statement->GetStartPosition(),
statement->GetLength());
return new BoundBadStatement(); return new BoundBadStatement();
} }
auto boundExpression = this->BindExpression(expression); auto boundExpression = this->BindExpression(expression);
@ -169,7 +188,8 @@ BoundStatement *Binder::BindReturnStatement(const ParsedStatement* statement){
return new BoundReturnStatement(boundExpression); return new BoundReturnStatement(boundExpression);
} }
if (currentReturnType.get()->operator!=(expresionType.get())) { if (currentReturnType.get()->operator!=(expresionType.get())) {
this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidReturnType, statement->GetStartPosition(), statement->GetLength()); this->_scriptData->Diagnostics->LogError(DiagnosticCode::InvalidReturnType, statement->GetStartPosition(),
statement->GetLength());
return new BoundBadStatement(); return new BoundBadStatement();
} }
return new BoundReturnStatement(boundExpression); return new BoundReturnStatement(boundExpression);
@ -179,7 +199,8 @@ BoundStatement *Binder::BindConditionalStatement(const ParsedStatement* statemen
auto conditionalStatement = (ParsedConditionalStatement *) statement; auto conditionalStatement = (ParsedConditionalStatement *) statement;
auto boundCondition = this->BindExpression(conditionalStatement->GetCondition()); auto boundCondition = this->BindExpression(conditionalStatement->GetCondition());
if (boundCondition->GetType()->GetClass() != TypeClass::Bool) { if (boundCondition->GetType()->GetClass() != TypeClass::Bool) {
this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::ConditionNotABool, statement->GetStartPosition(), statement->GetLength()); this->_scriptData->Diagnostics->LogError(DiagnosticCode::ConditionNotABool, statement->GetStartPosition(),
statement->GetLength());
return new BoundBadStatement(); return new BoundBadStatement();
} }
auto boundBlock = this->BindStatement(conditionalStatement->GetBlock()); auto boundBlock = this->BindStatement(conditionalStatement->GetBlock());
@ -193,13 +214,17 @@ BoundStatement *Binder::BindConditionalStatement(const ParsedStatement* statemen
BoundExpression *Binder::BindExpression(const ParsedExpression *expression) { BoundExpression *Binder::BindExpression(const ParsedExpression *expression) {
switch (expression->GetKind()) { switch (expression->GetKind()) {
case ParsedExpressionKind::LiteralInteger: case ParsedExpressionKind::LiteralInteger:
return new BoundLiteralIntegerExpression(((LiteralIntegerExpression*)expression)->GetValue(), expression->GetStartPosition(), expression->GetLength()); return new BoundLiteralIntegerExpression(((LiteralIntegerExpression *) expression)->GetValue(),
expression->GetStartPosition(), expression->GetLength());
case ParsedExpressionKind::LiteralFloat: case ParsedExpressionKind::LiteralFloat:
return new BoundLiteralFloatExpression(((LiteralFloatExpression*)expression)->GetValue(), expression->GetStartPosition(), expression->GetLength()); return new BoundLiteralFloatExpression(((LiteralFloatExpression *) expression)->GetValue(),
expression->GetStartPosition(), expression->GetLength());
case ParsedExpressionKind::LiteralString: case ParsedExpressionKind::LiteralString:
return new BoundLiteralStringExpression(((LiteralStringExpression*)expression)->GetValue(), expression->GetStartPosition(), expression->GetLength()); return new BoundLiteralStringExpression(((LiteralStringExpression *) expression)->GetValue(),
expression->GetStartPosition(), expression->GetLength());
case ParsedExpressionKind::LiteralBool: case ParsedExpressionKind::LiteralBool:
return new BoundLiteralBoolExpression(((LiteralBoolExpression*)expression)->GetValue(), expression->GetStartPosition(), expression->GetLength()); return new BoundLiteralBoolExpression(((LiteralBoolExpression *) expression)->GetValue(),
expression->GetStartPosition(), expression->GetLength());
case ParsedExpressionKind::Variable: case ParsedExpressionKind::Variable:
return this->BindVariableExpression((VariableExpression *) expression); return this->BindVariableExpression((VariableExpression *) expression);
@ -231,12 +256,14 @@ BoundExpression* Binder::BindVariableExpression(const VariableExpression* expres
auto key = expression->GetValue(); auto key = expression->GetValue();
auto scope = this->_scope->Exists(key.GetHash()); auto scope = this->_scope->Exists(key.GetHash());
if (scope == -1) { if (scope == -1) {
this -> _scriptData -> Diagnostics->LogError(DiagnosticCode::VariableNotFound, expression->GetStartPosition(), expression->GetLength()); this->_scriptData->Diagnostics->LogError(DiagnosticCode::VariableNotFound, expression->GetStartPosition(),
expression->GetLength());
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
} }
auto var = this->_scope->GetVariable(scope, key.GetHash()); auto var = this->_scope->GetVariable(scope, key.GetHash());
auto type = var->GetType(); auto type = var->GetType();
return new BoundVariableExpression(new BoundVariableKey(key.GetHash(), scope, false), type, expression->GetStartPosition(), expression->GetLength()); return new BoundVariableExpression(new BoundVariableKey(key.GetHash(), scope, false), type,
expression->GetStartPosition(), expression->GetLength());
} }
BoundExpression *Binder::BindBinaryOperator(const BinaryExpression *expression) { BoundExpression *Binder::BindBinaryOperator(const BinaryExpression *expression) {
@ -254,16 +281,18 @@ BoundExpression* Binder::BindBinaryOperator(const BinaryExpression* expression){
if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()) { if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()) {
return new BoundBinaryExpression(boundLeft, boundRight, return new BoundBinaryExpression(boundLeft, boundRight,
BoundBinaryOperation::Addition, BoundBinaryOperation::Addition,
std::make_shared<NumericScriptType>(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()), std::make_shared<NumericScriptType>(true,
leftNumeric->IsFloat() ||
rightNumeric->IsFloat()),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
} } else {
else{
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Addition, return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Addition,
std::make_shared<NumericScriptType>(false, false), std::make_shared<NumericScriptType>(false, false),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
} }
} else if (boundLeftType->GetClass() == TypeClass::String) { } else if (boundLeftType->GetClass() == TypeClass::String) {
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Concatenation, std::make_shared<StringScriptType>(false, return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Concatenation,
std::make_shared<StringScriptType>(false,
0), 0),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
} }
@ -275,10 +304,11 @@ BoundExpression* Binder::BindBinaryOperator(const BinaryExpression* expression){
if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()) { if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()) {
return new BoundBinaryExpression(boundLeft, boundRight, return new BoundBinaryExpression(boundLeft, boundRight,
BoundBinaryOperation::Subtraction, BoundBinaryOperation::Subtraction,
std::make_shared<NumericScriptType>(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()), std::make_shared<NumericScriptType>(true,
leftNumeric->IsFloat() ||
rightNumeric->IsFloat()),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
} } else {
else{
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Subtraction, return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Subtraction,
std::make_shared<NumericScriptType>(false, false), std::make_shared<NumericScriptType>(false, false),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
@ -292,10 +322,11 @@ BoundExpression* Binder::BindBinaryOperator(const BinaryExpression* expression){
if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()) { if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()) {
return new BoundBinaryExpression(boundLeft, boundRight, return new BoundBinaryExpression(boundLeft, boundRight,
BoundBinaryOperation::Multiplication, BoundBinaryOperation::Multiplication,
std::make_shared<NumericScriptType>(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()), std::make_shared<NumericScriptType>(true,
leftNumeric->IsFloat() ||
rightNumeric->IsFloat()),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
} } else {
else{
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Multiplication, return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Multiplication,
std::make_shared<NumericScriptType>(false, false), std::make_shared<NumericScriptType>(false, false),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
@ -309,10 +340,11 @@ BoundExpression* Binder::BindBinaryOperator(const BinaryExpression* expression){
if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()) { if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()) {
return new BoundBinaryExpression(boundLeft, boundRight, return new BoundBinaryExpression(boundLeft, boundRight,
BoundBinaryOperation::Division, BoundBinaryOperation::Division,
std::make_shared<NumericScriptType>(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()), std::make_shared<NumericScriptType>(true,
leftNumeric->IsFloat() ||
rightNumeric->IsFloat()),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
} } else {
else{
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Division, return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Division,
std::make_shared<NumericScriptType>(false, false), std::make_shared<NumericScriptType>(false, false),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
@ -320,43 +352,56 @@ BoundExpression* Binder::BindBinaryOperator(const BinaryExpression* expression){
} }
break; break;
case BinaryOperatorKind::Equality: case BinaryOperatorKind::Equality:
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Equality, std::make_shared<ScriptType>(TypeClass::Bool), return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Equality,
std::make_shared<ScriptType>(TypeClass::Bool),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
case BinaryOperatorKind::Inequality: case BinaryOperatorKind::Inequality:
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Inequality, std::make_shared<ScriptType>(TypeClass::Bool), return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Inequality,
std::make_shared<ScriptType>(TypeClass::Bool),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
case BinaryOperatorKind::Less: case BinaryOperatorKind::Less:
if (boundLeft->GetType()->GetClass() == TypeClass::Number && boundRight->GetType()->GetClass() == TypeClass::Number){ if (boundLeft->GetType()->GetClass() == TypeClass::Number &&
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LessThan, std::make_shared<ScriptType>(TypeClass::Bool), boundRight->GetType()->GetClass() == TypeClass::Number) {
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LessThan,
std::make_shared<ScriptType>(TypeClass::Bool),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
} }
case BinaryOperatorKind::LessOrEquals: case BinaryOperatorKind::LessOrEquals:
if (boundLeft->GetType()->GetClass() == TypeClass::Number && boundRight->GetType()->GetClass() == TypeClass::Number){ if (boundLeft->GetType()->GetClass() == TypeClass::Number &&
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LessThanEquals, std::make_shared<ScriptType>(TypeClass::Bool), boundRight->GetType()->GetClass() == TypeClass::Number) {
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LessThanEquals,
std::make_shared<ScriptType>(TypeClass::Bool),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
} }
case BinaryOperatorKind::Greater: case BinaryOperatorKind::Greater:
if (boundLeft->GetType()->GetClass() == TypeClass::Number && boundRight->GetType()->GetClass() == TypeClass::Number){ if (boundLeft->GetType()->GetClass() == TypeClass::Number &&
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::GreaterThan, std::make_shared<ScriptType>(TypeClass::Bool), boundRight->GetType()->GetClass() == TypeClass::Number) {
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::GreaterThan,
std::make_shared<ScriptType>(TypeClass::Bool),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
} }
case BinaryOperatorKind::GreaterOrEquals: case BinaryOperatorKind::GreaterOrEquals:
if (boundLeft->GetType()->GetClass() == TypeClass::Number && boundRight->GetType()->GetClass() == TypeClass::Number){ if (boundLeft->GetType()->GetClass() == TypeClass::Number &&
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::GreaterThanEquals, std::make_shared<ScriptType>(TypeClass::Bool), boundRight->GetType()->GetClass() == TypeClass::Number) {
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::GreaterThanEquals,
std::make_shared<ScriptType>(TypeClass::Bool),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
} }
case BinaryOperatorKind::LogicalAnd: case BinaryOperatorKind::LogicalAnd:
if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool) if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool)
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LogicalAnd, std::make_shared<ScriptType>(TypeClass::Bool), return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LogicalAnd,
std::make_shared<ScriptType>(TypeClass::Bool),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
break; break;
case BinaryOperatorKind::LogicalOr: case BinaryOperatorKind::LogicalOr:
if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool) if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool)
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LogicalOr, std::make_shared<ScriptType>(TypeClass::Bool), return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LogicalOr,
std::make_shared<ScriptType>(TypeClass::Bool),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
break; break;
} }
this -> _scriptData -> Diagnostics->LogError(DiagnosticCode::NoBinaryOperationFound, expression->GetStartPosition(), expression->GetLength()); this->_scriptData->Diagnostics->LogError(DiagnosticCode::NoBinaryOperationFound, expression->GetStartPosition(),
expression->GetLength());
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
} }
@ -374,7 +419,9 @@ BoundExpression* Binder::BindUnaryOperator(const UnaryExpression* expression){
if (operandType->GetClass() == TypeClass::Number) { if (operandType->GetClass() == TypeClass::Number) {
auto innerType = std::dynamic_pointer_cast<NumericScriptType>(operandType); auto innerType = std::dynamic_pointer_cast<NumericScriptType>(operandType);
return new BoundUnaryExpression(operand, BoundUnaryOperation::Negation, return new BoundUnaryExpression(operand, BoundUnaryOperation::Negation,
std::make_shared<NumericScriptType>(innerType.get()->IsAwareOfFloat(), innerType.get()->IsFloat()), std::make_shared<NumericScriptType>(
innerType.get()->IsAwareOfFloat(),
innerType.get()->IsFloat()),
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
} }
break; break;
@ -388,7 +435,8 @@ BoundExpression* Binder::BindUnaryOperator(const UnaryExpression* expression){
default: default:
break; break;
} }
this -> _scriptData -> Diagnostics->LogError(DiagnosticCode::NoUnaryOperationFound, expression->GetStartPosition(), expression->GetLength()); this->_scriptData->Diagnostics->LogError(DiagnosticCode::NoUnaryOperationFound, expression->GetStartPosition(),
expression->GetLength());
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
} }
@ -397,7 +445,8 @@ BoundExpression* Binder::BindFunctionCall(const FunctionCallExpression* expressi
auto functionExpression = BindExpression(expression->GetFunction()); auto functionExpression = BindExpression(expression->GetFunction());
auto type = functionExpression->GetType(); auto type = functionExpression->GetType();
if (type->GetClass() != TypeClass::Function) { if (type->GetClass() != TypeClass::Function) {
this->_scriptData->Diagnostics->LogError(DiagnosticCode::ExpressionIsNotAFunction, expression->GetStartPosition(), this->_scriptData->Diagnostics->LogError(DiagnosticCode::ExpressionIsNotAFunction,
expression->GetStartPosition(),
expression->GetLength()); expression->GetLength());
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
} }
@ -405,7 +454,8 @@ BoundExpression* Binder::BindFunctionCall(const FunctionCallExpression* expressi
auto parameterTypes = functionType->GetParameterTypes(); auto parameterTypes = functionType->GetParameterTypes();
auto givenParameters = expression->GetParameters(); auto givenParameters = expression->GetParameters();
if (parameterTypes.size() != givenParameters->size()) { if (parameterTypes.size() != givenParameters->size()) {
this->_scriptData->Diagnostics->LogError(DiagnosticCode::ParameterCountMismatch, expression->GetStartPosition(), this->_scriptData->Diagnostics->LogError(DiagnosticCode::ParameterCountMismatch,
expression->GetStartPosition(),
expression->GetLength()); expression->GetLength());
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
} }
@ -414,7 +464,8 @@ BoundExpression* Binder::BindFunctionCall(const FunctionCallExpression* expressi
auto parameter = givenParameters->at(i); auto parameter = givenParameters->at(i);
auto boundParameter = this->BindExpression(parameter); auto boundParameter = this->BindExpression(parameter);
if (boundParameter->GetType().get()->operator!=(parameterTypes.at(i).get())) { if (boundParameter->GetType().get()->operator!=(parameterTypes.at(i).get())) {
this->_scriptData->Diagnostics->LogError(DiagnosticCode::ParameterTypeMismatch, parameter->GetStartPosition(), this->_scriptData->Diagnostics->LogError(DiagnosticCode::ParameterTypeMismatch,
parameter->GetStartPosition(),
parameter->GetLength()); parameter->GetLength());
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
} }
@ -437,16 +488,18 @@ BoundExpression *Binder::BindIndexExpression(const IndexExpression *expression,
} }
if (indexerType->GetClass() == TypeClass::UserData) { if (indexerType->GetClass() == TypeClass::UserData) {
auto stringKey = dynamic_pointer_cast<StringScriptType>(index->GetType()); auto stringKey = dynamic_pointer_cast<StringScriptType>(index->GetType());
auto field = dynamic_pointer_cast<UserDataScriptType>(indexerType) -> GetField(stringKey->GetHashValue()); auto field = dynamic_pointer_cast<UserData::UserDataScriptType>(indexerType)->GetField(stringKey->GetHashValue());
if (!setter) { if (!setter) {
if (!field->HasGetter()) { if (!field->HasGetter()) {
this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoGetter, index->GetStartPosition(), this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoGetter,
index->GetStartPosition(),
index->GetLength()); index->GetLength());
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
} }
} else { } else {
if (!field->HasSetter()) { if (!field->HasSetter()) {
this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoSetter, index->GetStartPosition(), this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoSetter,
index->GetStartPosition(),
index->GetLength()); index->GetLength());
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
} }
@ -454,7 +507,8 @@ BoundExpression *Binder::BindIndexExpression(const IndexExpression *expression,
} }
auto resultType = indexer->GetType()->GetIndexedType(index->GetType().get()); auto resultType = indexer->GetType()->GetIndexedType(index->GetType().get());
return new BoundIndexExpression(indexer, index, resultType, expression->GetStartPosition(), expression->GetLength()); return new BoundIndexExpression(indexer, index, resultType, expression->GetStartPosition(),
expression->GetLength());
} }
BoundExpression *Binder::BindPeriodIndexExpression(const PeriodIndexExpression *expression, bool setter) { BoundExpression *Binder::BindPeriodIndexExpression(const PeriodIndexExpression *expression, bool setter) {
@ -467,16 +521,18 @@ BoundExpression* Binder::BindPeriodIndexExpression(const PeriodIndexExpression*
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
} }
if (indexerType->GetClass() == TypeClass::UserData) { if (indexerType->GetClass() == TypeClass::UserData) {
auto field = dynamic_pointer_cast<UserDataScriptType>(indexerType) -> GetField(identifier . GetHash()); auto field = dynamic_pointer_cast<UserData::UserDataScriptType>(indexerType)->GetField(identifier.GetHash());
if (!setter) { if (!setter) {
if (!field->HasGetter()) { if (!field->HasGetter()) {
this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoGetter, expression->GetStartPosition(), this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoGetter,
expression->GetStartPosition(),
expression->GetLength()); expression->GetLength());
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
} }
} else { } else {
if (!field->HasSetter()) { if (!field->HasSetter()) {
this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoSetter, expression->GetStartPosition(), this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoSetter,
expression->GetStartPosition(),
expression->GetLength()); expression->GetLength());
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
} }
@ -484,7 +540,8 @@ BoundExpression* Binder::BindPeriodIndexExpression(const PeriodIndexExpression*
} }
auto resultType = indexer->GetType()->GetIndexedType(identifier.GetHash()); auto resultType = indexer->GetType()->GetIndexedType(identifier.GetHash());
return new BoundPeriodIndexExpression(indexer, identifier, resultType, expression->GetStartPosition(), expression->GetLength()); return new BoundPeriodIndexExpression(indexer, identifier, resultType, expression->GetStartPosition(),
expression->GetLength());
} }
@ -498,7 +555,8 @@ BoundExpression* Binder::BindNumericalTableExpression(const ParsedNumericalTable
for (int i = 1; i < expressions->size(); i++) { for (int i = 1; i < expressions->size(); i++) {
boundExpressions[i] = this->BindExpression(expressions->at(i)); boundExpressions[i] = this->BindExpression(expressions->at(i));
if (boundExpressions[i]->GetType().get()->operator!=(valueType.get())) { if (boundExpressions[i]->GetType().get()->operator!=(valueType.get())) {
this->_scriptData->Diagnostics->LogError(DiagnosticCode::InvalidTableValueType, boundExpressions[i]->GetStartPosition(), this->_scriptData->Diagnostics->LogError(DiagnosticCode::InvalidTableValueType,
boundExpressions[i]->GetStartPosition(),
boundExpressions[i]->GetLength()); boundExpressions[i]->GetLength());
} }
} }
@ -507,7 +565,8 @@ BoundExpression* Binder::BindNumericalTableExpression(const ParsedNumericalTable
valueType = std::make_shared<ScriptType>(TypeClass::Nil); valueType = std::make_shared<ScriptType>(TypeClass::Nil);
} }
auto tableType = std::make_shared<NumericalTableScriptType>(valueType); auto tableType = std::make_shared<NumericalTableScriptType>(valueType);
return new BoundNumericalTableExpression(boundExpressions, tableType, expression->GetStartPosition(), expression->GetLength()); return new BoundNumericalTableExpression(boundExpressions, tableType, expression->GetStartPosition(),
expression->GetLength());
} }
BoundExpression *Binder::BindTableExpression(const ParsedTableExpression *expression) { BoundExpression *Binder::BindTableExpression(const ParsedTableExpression *expression) {
@ -521,6 +580,7 @@ BoundExpression *Binder::BindTableExpression(const ParsedTableExpression *expres
auto tableType = std::make_shared<TableScriptType>(tableScope, innerScope->GetLocalVariableCount()); auto tableType = std::make_shared<TableScriptType>(tableScope, innerScope->GetLocalVariableCount());
delete innerScope; delete innerScope;
return new BoundTableExpression((BoundBlockStatement*)block, tableType, expression->GetStartPosition(), expression->GetLength()); return new BoundTableExpression((BoundBlockStatement *) block, tableType, expression->GetStartPosition(),
expression->GetLength());
}
} }

View File

@ -8,36 +8,54 @@
#include "../Parser/ParsedExpressions/ParsedTableExpression.hpp" #include "../Parser/ParsedExpressions/ParsedTableExpression.hpp"
using namespace std; using namespace std;
using namespace Porygon::Parser;
namespace Porygon::Binder {
class Binder { class Binder {
Script* _scriptData; Porygon::Script *_scriptData;
BoundScope *_scope; BoundScope *_scope;
shared_ptr<FunctionScriptType> _currentFunction; shared_ptr<FunctionScriptType> _currentFunction;
~Binder(); ~Binder();
BoundStatement *BindStatement(const ParsedStatement *statement); BoundStatement *BindStatement(const ParsedStatement *statement);
BoundStatement *BindBlockStatement(const ParsedStatement *statement); BoundStatement *BindBlockStatement(const ParsedStatement *statement);
BoundStatement *BindExpressionStatement(const ParsedStatement *statement); BoundStatement *BindExpressionStatement(const ParsedStatement *statement);
BoundStatement *BindAssignmentStatement(const ParsedStatement *statement); BoundStatement *BindAssignmentStatement(const ParsedStatement *statement);
BoundStatement *BindIndexAssignmentStatement(const ParsedStatement *statement); BoundStatement *BindIndexAssignmentStatement(const ParsedStatement *statement);
BoundStatement *BindFunctionDeclarationStatement(const ParsedStatement *statement); BoundStatement *BindFunctionDeclarationStatement(const ParsedStatement *statement);
BoundStatement *BindReturnStatement(const ParsedStatement *statement); BoundStatement *BindReturnStatement(const ParsedStatement *statement);
BoundStatement *BindConditionalStatement(const ParsedStatement *statement); BoundStatement *BindConditionalStatement(const ParsedStatement *statement);
BoundExpression *BindExpression(const ParsedExpression *expression); BoundExpression *BindExpression(const ParsedExpression *expression);
BoundExpression *BindVariableExpression(const VariableExpression *expression); BoundExpression *BindVariableExpression(const VariableExpression *expression);
BoundExpression *BindBinaryOperator(const BinaryExpression *expression); BoundExpression *BindBinaryOperator(const BinaryExpression *expression);
BoundExpression *BindUnaryOperator(const UnaryExpression *expression); BoundExpression *BindUnaryOperator(const UnaryExpression *expression);
BoundExpression *BindFunctionCall(const FunctionCallExpression *expression); BoundExpression *BindFunctionCall(const FunctionCallExpression *expression);
BoundExpression *BindIndexExpression(const IndexExpression *expression, bool setter); BoundExpression *BindIndexExpression(const IndexExpression *expression, bool setter);
BoundExpression *BindNumericalTableExpression(const ParsedNumericalTableExpression *expression); BoundExpression *BindNumericalTableExpression(const ParsedNumericalTableExpression *expression);
BoundExpression *BindTableExpression(const ParsedTableExpression *expression); BoundExpression *BindTableExpression(const ParsedTableExpression *expression);
public: public:
static BoundScriptStatement* Bind(Script* script, const ParsedScriptStatement* s, BoundScope* scriptScope); static BoundScriptStatement *
Bind(Porygon::Script *script, const ParsedScriptStatement *s, BoundScope *scriptScope);
BoundExpression *BindPeriodIndexExpression(const PeriodIndexExpression *expression, bool setter); BoundExpression *BindPeriodIndexExpression(const PeriodIndexExpression *expression, bool setter);
}; };
}
#endif //PORYGONLANG_BINDER_HPP #endif //PORYGONLANG_BINDER_HPP

View File

@ -10,6 +10,7 @@
using namespace std; using namespace std;
namespace Porygon::Binder {
enum class BoundExpressionKind { enum class BoundExpressionKind {
Bad, Bad,
@ -36,13 +37,13 @@ public:
BoundExpression(unsigned int start, unsigned int length, shared_ptr<ScriptType> type) BoundExpression(unsigned int start, unsigned int length, shared_ptr<ScriptType> type)
: _start(start), : _start(start),
_length(length), _length(length),
_type(std::move(type)) _type(std::move(type)) {
{
} }
virtual ~BoundExpression() = default; virtual ~BoundExpression() = default;
virtual const BoundExpressionKind GetKind() const = 0; virtual const BoundExpressionKind GetKind() const = 0;
virtual const std::shared_ptr<ScriptType> &GetType() const { virtual const std::shared_ptr<ScriptType> &GetType() const {
return _type; return _type;
}; };
@ -50,9 +51,11 @@ public:
const unsigned int GetStartPosition() const { const unsigned int GetStartPosition() const {
return _start; return _start;
} }
const unsigned int GetLength() const { const unsigned int GetLength() const {
return _length; return _length;
} }
const unsigned int GetEndPosition() const { const unsigned int GetEndPosition() const {
return _start + _length - 1; return _start + _length - 1;
} }
@ -60,7 +63,9 @@ public:
class BoundBadExpression : public BoundExpression { class BoundBadExpression : public BoundExpression {
public: public:
BoundBadExpression(unsigned int start, unsigned int length) : BoundExpression(start, length, make_shared<ScriptType>(TypeClass::Error)){} BoundBadExpression(unsigned int start, unsigned int length) : BoundExpression(start, length,
make_shared<ScriptType>(
TypeClass::Error)) {}
const BoundExpressionKind GetKind() const final { const BoundExpressionKind GetKind() const final {
return BoundExpressionKind::Bad; return BoundExpressionKind::Bad;
@ -72,8 +77,7 @@ class BoundLiteralIntegerExpression : public BoundExpression{
public: public:
BoundLiteralIntegerExpression(long value, unsigned int start, unsigned int length) BoundLiteralIntegerExpression(long value, unsigned int start, unsigned int length)
: BoundExpression(start, length, make_shared<NumericScriptType>(true, false)), : BoundExpression(start, length, make_shared<NumericScriptType>(true, false)),
_value(value) _value(value) {
{
} }
const BoundExpressionKind GetKind() const final { const BoundExpressionKind GetKind() const final {
@ -90,8 +94,7 @@ class BoundLiteralFloatExpression : public BoundExpression{
public: public:
BoundLiteralFloatExpression(double value, unsigned int start, unsigned int length) BoundLiteralFloatExpression(double value, unsigned int start, unsigned int length)
: BoundExpression(start, length, make_shared<NumericScriptType>(true, true)), : BoundExpression(start, length, make_shared<NumericScriptType>(true, true)),
_value(value) _value(value) {
{
} }
const BoundExpressionKind GetKind() const final { const BoundExpressionKind GetKind() const final {
@ -107,9 +110,9 @@ class BoundLiteralStringExpression : public BoundExpression{
const u16string _value; const u16string _value;
public: public:
BoundLiteralStringExpression(const u16string &value, unsigned int start, unsigned int length) BoundLiteralStringExpression(const u16string &value, unsigned int start, unsigned int length)
: BoundExpression(start, length, make_shared<StringScriptType>(true, HashedString::ConstHash(value.c_str()))), : BoundExpression(start, length,
_value(value) make_shared<StringScriptType>(true, Utilities::HashedString::ConstHash(value.c_str()))),
{ _value(value) {
} }
const BoundExpressionKind GetKind() const final { const BoundExpressionKind GetKind() const final {
@ -126,8 +129,7 @@ class BoundLiteralBoolExpression : public BoundExpression{
public: public:
BoundLiteralBoolExpression(bool value, unsigned int start, unsigned int length) BoundLiteralBoolExpression(bool value, unsigned int start, unsigned int length)
: BoundExpression(start, length, make_shared<ScriptType>(TypeClass::Bool)), : BoundExpression(start, length, make_shared<ScriptType>(TypeClass::Bool)),
_value(value) _value(value) {
{
} }
const BoundExpressionKind GetKind() const final { const BoundExpressionKind GetKind() const final {
@ -142,10 +144,10 @@ public:
class BoundVariableExpression : public BoundExpression { class BoundVariableExpression : public BoundExpression {
const BoundVariableKey *_key; const BoundVariableKey *_key;
public: public:
BoundVariableExpression(BoundVariableKey* key, shared_ptr<ScriptType> type, unsigned int start, unsigned int length) BoundVariableExpression(BoundVariableKey *key, shared_ptr<ScriptType> type, unsigned int start,
unsigned int length)
: BoundExpression(start, length, std::move(type)), : BoundExpression(start, length, std::move(type)),
_key(key) _key(key) {
{
} }
~BoundVariableExpression() override { ~BoundVariableExpression() override {
@ -166,13 +168,13 @@ class BoundBinaryExpression : public BoundExpression {
const BoundExpression *_right; const BoundExpression *_right;
const BoundBinaryOperation _operation; const BoundBinaryOperation _operation;
public: public:
BoundBinaryExpression(BoundExpression* left, BoundExpression* right, BoundBinaryOperation op, shared_ptr<ScriptType> result, BoundBinaryExpression(BoundExpression *left, BoundExpression *right, BoundBinaryOperation op,
shared_ptr<ScriptType> result,
unsigned int start, unsigned int length) unsigned int start, unsigned int length)
: BoundExpression(start, length, std::move(result)), : BoundExpression(start, length, std::move(result)),
_left(left), _left(left),
_right(right), _right(right),
_operation(op) _operation(op) {
{
} }
~BoundBinaryExpression() final { ~BoundBinaryExpression() final {
@ -201,11 +203,11 @@ class BoundUnaryExpression : public BoundExpression {
const BoundExpression *_operand; const BoundExpression *_operand;
const BoundUnaryOperation _operation; const BoundUnaryOperation _operation;
public: public:
BoundUnaryExpression(BoundExpression* operand, BoundUnaryOperation op, shared_ptr<ScriptType> result, unsigned int start, unsigned int length) BoundUnaryExpression(BoundExpression *operand, BoundUnaryOperation op, shared_ptr<ScriptType> result,
unsigned int start, unsigned int length)
: BoundExpression(start, length, std::move(result)), : BoundExpression(start, length, std::move(result)),
_operand(operand), _operand(operand),
_operation(op) _operation(op) {
{
} }
~BoundUnaryExpression() final { ~BoundUnaryExpression() final {
@ -229,9 +231,11 @@ class BoundFunctionCallExpression : public BoundExpression {
const BoundExpression *_functionExpression; const BoundExpression *_functionExpression;
const vector<BoundExpression *> _parameters; const vector<BoundExpression *> _parameters;
public: public:
BoundFunctionCallExpression(BoundExpression *functionExpression, vector<BoundExpression *> parameters, shared_ptr<ScriptType> result, BoundFunctionCallExpression(BoundExpression *functionExpression, vector<BoundExpression *> parameters,
shared_ptr<ScriptType> result,
unsigned int start, unsigned int length) unsigned int start, unsigned int length)
: BoundExpression(start, length, std::move(result)), _functionExpression(functionExpression), _parameters(std::move(parameters)) {} : BoundExpression(start, length, std::move(result)), _functionExpression(functionExpression),
_parameters(std::move(parameters)) {}
~BoundFunctionCallExpression() final { ~BoundFunctionCallExpression() final {
delete _functionExpression; delete _functionExpression;
@ -257,9 +261,11 @@ class BoundIndexExpression : public BoundExpression {
const BoundExpression *_indexableExpression; const BoundExpression *_indexableExpression;
const BoundExpression *_indexExpression; const BoundExpression *_indexExpression;
public: public:
BoundIndexExpression(BoundExpression* indexableExpression, BoundExpression* indexExpression, shared_ptr<ScriptType> result, BoundIndexExpression(BoundExpression *indexableExpression, BoundExpression *indexExpression,
shared_ptr<ScriptType> result,
unsigned int start, unsigned int length) unsigned int start, unsigned int length)
: BoundExpression(start, length, std::move(result)), _indexableExpression(indexableExpression), _indexExpression(indexExpression) {} : BoundExpression(start, length, std::move(result)), _indexableExpression(indexableExpression),
_indexExpression(indexExpression) {}
~BoundIndexExpression() final { ~BoundIndexExpression() final {
delete _indexableExpression; delete _indexableExpression;
@ -281,11 +287,13 @@ public:
class BoundPeriodIndexExpression : public BoundExpression { class BoundPeriodIndexExpression : public BoundExpression {
const BoundExpression *_indexableExpression; const BoundExpression *_indexableExpression;
const HashedString _index; const Utilities::HashedString _index;
public: public:
BoundPeriodIndexExpression(BoundExpression* indexableExpression, HashedString index, shared_ptr<ScriptType> result, BoundPeriodIndexExpression(BoundExpression *indexableExpression, Utilities::HashedString index,
shared_ptr<ScriptType> result,
unsigned int start, unsigned int length) unsigned int start, unsigned int length)
: BoundExpression(start, length, std::move(result)), _indexableExpression(indexableExpression), _index(index) {} : BoundExpression(start, length, std::move(result)), _indexableExpression(indexableExpression),
_index(index) {}
~BoundPeriodIndexExpression() final { ~BoundPeriodIndexExpression() final {
delete _indexableExpression; delete _indexableExpression;
@ -299,7 +307,7 @@ public:
return _indexableExpression; return _indexableExpression;
} }
const HashedString GetIndex() const{ const Utilities::HashedString GetIndex() const {
return _index; return _index;
} }
}; };
@ -307,10 +315,10 @@ public:
class BoundNumericalTableExpression : public BoundExpression { class BoundNumericalTableExpression : public BoundExpression {
const vector<const BoundExpression *> _expressions; const vector<const BoundExpression *> _expressions;
public: public:
BoundNumericalTableExpression(vector<const BoundExpression*> expressions, shared_ptr<ScriptType> type, unsigned int start, unsigned int length) BoundNumericalTableExpression(vector<const BoundExpression *> expressions, shared_ptr<ScriptType> type,
unsigned int start, unsigned int length)
: BoundExpression(start, length, std::move(type)), : BoundExpression(start, length, std::move(type)),
_expressions(std::move(expressions)) _expressions(std::move(expressions)) {}
{}
~BoundNumericalTableExpression() final { ~BoundNumericalTableExpression() final {
for (auto e: _expressions) { for (auto e: _expressions) {
@ -326,6 +334,6 @@ public:
return &_expressions; return &_expressions;
} }
}; };
}
#endif //PORYGONLANG_BOUNDEXPRESSION_HPP #endif //PORYGONLANG_BOUNDEXPRESSION_HPP

View File

@ -6,10 +6,12 @@
#include "../BoundStatements/BoundStatement.hpp" #include "../BoundStatements/BoundStatement.hpp"
namespace Porygon::Binder {
class BoundTableExpression : public BoundExpression { class BoundTableExpression : public BoundExpression {
const BoundBlockStatement *_block; const BoundBlockStatement *_block;
public: public:
BoundTableExpression(BoundBlockStatement* block, shared_ptr<ScriptType> type, unsigned int start, unsigned int length) BoundTableExpression(BoundBlockStatement *block, shared_ptr<ScriptType> type, unsigned int start,
unsigned int length)
: BoundExpression(start, length, std::move(type)) { : BoundExpression(start, length, std::move(type)) {
_block = block; _block = block;
} }
@ -26,6 +28,7 @@ public:
return _block; return _block;
} }
}; };
}
#include "BoundExpression.hpp" #include "BoundExpression.hpp"

View File

@ -2,6 +2,7 @@
#ifndef PORYGONLANG_BOUNDOPERATORS_HPP #ifndef PORYGONLANG_BOUNDOPERATORS_HPP
#define PORYGONLANG_BOUNDOPERATORS_HPP #define PORYGONLANG_BOUNDOPERATORS_HPP
namespace Porygon::Binder {
enum class BoundBinaryOperation { enum class BoundBinaryOperation {
Addition, Addition,
Subtraction, Subtraction,
@ -23,5 +24,6 @@ enum class BoundUnaryOperation{
Negation, Negation,
LogicalNegation, LogicalNegation,
}; };
}
#endif //PORYGONLANG_BOUNDOPERATORS_HPP #endif //PORYGONLANG_BOUNDOPERATORS_HPP

View File

@ -7,14 +7,15 @@
#include <memory> #include <memory>
#include "BoundStatement.hpp" #include "BoundStatement.hpp"
namespace Porygon::Binder {
class BoundFunctionDeclarationStatement : public BoundStatement { class BoundFunctionDeclarationStatement : public BoundStatement {
const BoundVariableKey *_key; const BoundVariableKey *_key;
const std::shared_ptr<BoundBlockStatement> _block; const std::shared_ptr<BoundBlockStatement> _block;
const std::shared_ptr<FunctionScriptType> _type; const std::shared_ptr<FunctionScriptType> _type;
public: public:
BoundFunctionDeclarationStatement(std::shared_ptr<FunctionScriptType> type, BoundVariableKey* key, BoundBlockStatement* block) BoundFunctionDeclarationStatement(std::shared_ptr<FunctionScriptType> type, BoundVariableKey *key,
:_key(key), _block(block), _type(std::move(type)) BoundBlockStatement *block)
{ : _key(key), _block(block), _type(std::move(type)) {
} }
~BoundFunctionDeclarationStatement() final { ~BoundFunctionDeclarationStatement() final {
@ -37,6 +38,7 @@ public:
return _type; return _type;
} }
}; };
}
#include "BoundStatement.hpp" #include "BoundStatement.hpp"

View File

@ -12,6 +12,7 @@
using namespace std; using namespace std;
namespace Porygon::Binder {
enum class BoundStatementKind { enum class BoundStatementKind {
Bad, Bad,
Script, Script,
@ -27,6 +28,7 @@ enum class BoundStatementKind{
class BoundStatement { class BoundStatement {
public: public:
virtual const BoundStatementKind GetKind() const = 0; virtual const BoundStatementKind GetKind() const = 0;
virtual ~BoundStatement() = default; virtual ~BoundStatement() = default;
}; };
@ -41,9 +43,9 @@ class BoundBlockStatement : public BoundStatement{
const vector<BoundStatement *> _statements; const vector<BoundStatement *> _statements;
public: public:
explicit BoundBlockStatement(vector<BoundStatement *> statements) explicit BoundBlockStatement(vector<BoundStatement *> statements)
: _statements(std::move(statements)) : _statements(std::move(statements)) {
{
} }
~BoundBlockStatement() override { ~BoundBlockStatement() override {
for (auto s : _statements) { for (auto s : _statements) {
delete s; delete s;
@ -64,8 +66,7 @@ class BoundScriptStatement : public BoundBlockStatement{
public: public:
explicit BoundScriptStatement(vector<BoundStatement *> statements, int localVariableCount) explicit BoundScriptStatement(vector<BoundStatement *> statements, int localVariableCount)
: BoundBlockStatement(std::move(statements)), : BoundBlockStatement(std::move(statements)),
_localVariableCount(localVariableCount) _localVariableCount(localVariableCount) {
{
} }
const BoundStatementKind GetKind() const final { const BoundStatementKind GetKind() const final {
@ -81,10 +82,10 @@ class BoundExpressionStatement : public BoundStatement{
const BoundExpression *_expression; const BoundExpression *_expression;
public: public:
explicit BoundExpressionStatement(BoundExpression *expression) explicit BoundExpressionStatement(BoundExpression *expression)
: _expression(expression) : _expression(expression) {
{
_expression = expression; _expression = expression;
} }
~BoundExpressionStatement() final { ~BoundExpressionStatement() final {
delete _expression; delete _expression;
} }
@ -103,8 +104,7 @@ class BoundAssignmentStatement : public BoundStatement{
const BoundExpression *_expression; const BoundExpression *_expression;
public: public:
BoundAssignmentStatement(BoundVariableKey *key, BoundExpression *expression) BoundAssignmentStatement(BoundVariableKey *key, BoundExpression *expression)
: _key(key), _expression(expression) : _key(key), _expression(expression) {
{
} }
~BoundAssignmentStatement() final { ~BoundAssignmentStatement() final {
@ -130,8 +130,7 @@ class BoundIndexAssignmentStatement : public BoundStatement{
const BoundExpression *_valueExpression; const BoundExpression *_valueExpression;
public: public:
BoundIndexAssignmentStatement(const BoundExpression *index, BoundExpression *value) BoundIndexAssignmentStatement(const BoundExpression *index, BoundExpression *value)
: _indexExpression(index), _valueExpression(value) : _indexExpression(index), _valueExpression(value) {
{
} }
~BoundIndexAssignmentStatement() final { ~BoundIndexAssignmentStatement() final {
@ -156,9 +155,9 @@ class BoundReturnStatement : public BoundStatement{
const BoundExpression *_expression; const BoundExpression *_expression;
public: public:
explicit BoundReturnStatement(BoundExpression *expression) explicit BoundReturnStatement(BoundExpression *expression)
: _expression(expression) : _expression(expression) {
{
} }
~BoundReturnStatement() final { ~BoundReturnStatement() final {
delete _expression; delete _expression;
} }
@ -178,8 +177,7 @@ class BoundConditionalStatement : public BoundStatement{
const BoundStatement *_elseStatement; const BoundStatement *_elseStatement;
public: public:
explicit BoundConditionalStatement(BoundExpression *condition, BoundStatement *block, BoundStatement *next) explicit BoundConditionalStatement(BoundExpression *condition, BoundStatement *block, BoundStatement *next)
:_condition(condition), _block(block), _elseStatement(next) : _condition(condition), _block(block), _elseStatement(next) {
{
} }
~BoundConditionalStatement() final { ~BoundConditionalStatement() final {
@ -204,6 +202,7 @@ public:
return _elseStatement; return _elseStatement;
} }
}; };
}
#include "BoundFunctionDeclarationStatement.hpp" #include "BoundFunctionDeclarationStatement.hpp"

View File

@ -3,6 +3,7 @@
#include "BoundScope.hpp" #include "BoundScope.hpp"
namespace Porygon::Binder {
BoundScope::BoundScope(unordered_map<uint32_t, BoundVariable *> *tableScope) { BoundScope::BoundScope(unordered_map<uint32_t, BoundVariable *> *tableScope) {
_tableScope = tableScope; _tableScope = tableScope;
_currentScope = 1; _currentScope = 1;
@ -76,7 +77,8 @@ VariableAssignment BoundScope::CreateExplicitLocal(uint32_t identifier, std::sha
return VariableAssignment(VariableAssignmentResult::ExplicitLocalVariableExists, nullptr); return VariableAssignment(VariableAssignmentResult::ExplicitLocalVariableExists, nullptr);
} }
scope->insert({identifier, new BoundVariable(std::move(type))}); scope->insert({identifier, new BoundVariable(std::move(type))});
return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, this->_currentScope, true)); return VariableAssignment(VariableAssignmentResult::Ok,
new BoundVariableKey(identifier, this->_currentScope, true));
} }
VariableAssignment BoundScope::AssignVariable(uint32_t identifier, const std::shared_ptr<ScriptType> &type) { VariableAssignment BoundScope::AssignVariable(uint32_t identifier, const std::shared_ptr<ScriptType> &type) {
@ -94,6 +96,7 @@ VariableAssignment BoundScope::AssignVariable(uint32_t identifier, const std::sh
return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, exists, false)); return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, exists, false));
} }
} }
}

View File

@ -13,6 +13,7 @@
using namespace std; using namespace std;
namespace Porygon::Binder {
class BoundScope { class BoundScope {
unordered_map<uint32_t, BoundVariable *> *_tableScope; unordered_map<uint32_t, BoundVariable *> *_tableScope;
vector<unordered_map<uint32_t, BoundVariable *> *> _localScope; vector<unordered_map<uint32_t, BoundVariable *> *> _localScope;
@ -20,14 +21,19 @@ class BoundScope {
int _lastCreatedScope; int _lastCreatedScope;
public: public:
explicit BoundScope(unordered_map<uint32_t, BoundVariable *> *tableScope); explicit BoundScope(unordered_map<uint32_t, BoundVariable *> *tableScope);
~BoundScope(); ~BoundScope();
void GoInnerScope(); void GoInnerScope();
void GoOuterScope(); void GoOuterScope();
int Exists(int key); int Exists(int key);
BoundVariable *GetVariable(uint32_t scope, uint32_t identifier); BoundVariable *GetVariable(uint32_t scope, uint32_t identifier);
VariableAssignment CreateExplicitLocal(uint32_t identifier, std::shared_ptr<ScriptType> type); VariableAssignment CreateExplicitLocal(uint32_t identifier, std::shared_ptr<ScriptType> type);
VariableAssignment AssignVariable(uint32_t identifier, const std::shared_ptr<ScriptType> &type); VariableAssignment AssignVariable(uint32_t identifier, const std::shared_ptr<ScriptType> &type);
size_t GetLocalVariableCount() { size_t GetLocalVariableCount() {
@ -38,6 +44,7 @@ public:
return _currentScope; return _currentScope;
} }
}; };
}
#endif //PORYGONLANG_BOUNDSCOPE_HPP #endif //PORYGONLANG_BOUNDSCOPE_HPP

View File

@ -9,6 +9,7 @@
using namespace std; using namespace std;
namespace Porygon::Binder {
class BoundVariable { class BoundVariable {
std::shared_ptr<ScriptType> _type; std::shared_ptr<ScriptType> _type;
public: public:
@ -19,5 +20,6 @@ public:
return _type; return _type;
} }
}; };
}
#endif //PORYGONLANG_BOUNDVARIABLE_HPP #endif //PORYGONLANG_BOUNDVARIABLE_HPP

View File

@ -4,25 +4,25 @@
#include <string> #include <string>
namespace Porygon::Binder {
class BoundVariableKey { class BoundVariableKey {
const int _identifier; const int _identifier;
const unsigned int _scopeId; const unsigned int _scopeId;
const bool _isCreation; const bool _isCreation;
const uint64_t _hash; const uint64_t _hash;
static uint64_t KnuthsHash(unsigned int i1, unsigned int i2) static uint64_t KnuthsHash(unsigned int i1, unsigned int i2) {
{
uint64_t ret = i1; uint64_t ret = i1;
ret *= 2654435761U; ret *= 2654435761U;
return ret ^ i2; return ret ^ i2;
} }
public: public:
BoundVariableKey(int id, unsigned int scope, bool creation) BoundVariableKey(int id, unsigned int scope, bool creation)
: _identifier(id), : _identifier(id),
_scopeId(scope), _scopeId(scope),
_isCreation(creation), _isCreation(creation),
_hash(KnuthsHash(id, scope)) _hash(KnuthsHash(id, scope)) {}
{}
const int GetIdentifier() const { const int GetIdentifier() const {
@ -41,5 +41,6 @@ public:
return _hash; return _hash;
} }
}; };
}
#endif //PORYGONLANG_BOUNDVARIABLEKEY_HPP #endif //PORYGONLANG_BOUNDVARIABLEKEY_HPP

View File

@ -4,6 +4,7 @@
#include "BoundVariableKey.hpp" #include "BoundVariableKey.hpp"
namespace Porygon::Binder {
enum class VariableAssignmentResult { enum class VariableAssignmentResult {
Ok, Ok,
ExplicitLocalVariableExists, ExplicitLocalVariableExists,
@ -27,5 +28,6 @@ public:
return _key; return _key;
} }
}; };
}
#endif //PORYGONLANG_VARIABLEASSIGMENTRESULT_HPP #endif //PORYGONLANG_VARIABLEASSIGMENTRESULT_HPP

View File

@ -5,6 +5,9 @@
#include "EvalValues/NumericEvalValue.hpp" #include "EvalValues/NumericEvalValue.hpp"
#include "EvalValues/StringEvalValue.hpp" #include "EvalValues/StringEvalValue.hpp"
using namespace Porygon::Binder;
namespace Porygon::Evaluation {
const shared_ptr<NumericEvalValue> Evaluator::EvaluateIntegerBinary(const BoundBinaryExpression *expression) { const shared_ptr<NumericEvalValue> Evaluator::EvaluateIntegerBinary(const BoundBinaryExpression *expression) {
auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft()); auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft());
auto rightValue = this->EvaluateIntegerExpression(expression->GetRight()); auto rightValue = this->EvaluateIntegerExpression(expression->GetRight());
@ -25,54 +28,46 @@ const shared_ptr<NumericEvalValue> Evaluator::EvaluateIntegerBinary(const BoundB
const shared_ptr<BooleanEvalValue> Evaluator::EvaluateBooleanBinary(const BoundBinaryExpression *expression) { const shared_ptr<BooleanEvalValue> Evaluator::EvaluateBooleanBinary(const BoundBinaryExpression *expression) {
switch (expression->GetOperation()) { switch (expression->GetOperation()) {
case BoundBinaryOperation::Equality: case BoundBinaryOperation::Equality: {
{
auto leftValue = this->EvaluateExpression(expression->GetLeft()); auto leftValue = this->EvaluateExpression(expression->GetLeft());
auto rightValue = this->EvaluateExpression(expression->GetRight()); auto rightValue = this->EvaluateExpression(expression->GetRight());
bool equals = leftValue.get()->operator==(rightValue.get()); bool equals = leftValue.get()->operator==(rightValue.get());
return make_shared<BooleanEvalValue>(equals); return make_shared<BooleanEvalValue>(equals);
} }
case BoundBinaryOperation::Inequality: case BoundBinaryOperation::Inequality: {
{
auto leftValue = this->EvaluateExpression(expression->GetLeft()); auto leftValue = this->EvaluateExpression(expression->GetLeft());
auto rightValue = this->EvaluateExpression(expression->GetRight()); auto rightValue = this->EvaluateExpression(expression->GetRight());
bool equals = leftValue.get()->operator!=(rightValue.get()); bool equals = leftValue.get()->operator!=(rightValue.get());
return make_shared<BooleanEvalValue>(equals); return make_shared<BooleanEvalValue>(equals);
} }
case BoundBinaryOperation ::LessThan: case BoundBinaryOperation::LessThan: {
{
auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft()); auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft());
auto rightValue = this->EvaluateIntegerExpression(expression->GetRight()); auto rightValue = this->EvaluateIntegerExpression(expression->GetRight());
return leftValue->operator<(rightValue); return leftValue->operator<(rightValue);
} }
case BoundBinaryOperation ::LessThanEquals: case BoundBinaryOperation::LessThanEquals: {
{
auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft()); auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft());
auto rightValue = this->EvaluateIntegerExpression(expression->GetRight()); auto rightValue = this->EvaluateIntegerExpression(expression->GetRight());
return leftValue->operator<=(rightValue); return leftValue->operator<=(rightValue);
} }
case BoundBinaryOperation ::GreaterThan: case BoundBinaryOperation::GreaterThan: {
{
auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft()); auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft());
auto rightValue = this->EvaluateIntegerExpression(expression->GetRight()); auto rightValue = this->EvaluateIntegerExpression(expression->GetRight());
return leftValue->operator>(rightValue); return leftValue->operator>(rightValue);
} }
case BoundBinaryOperation ::GreaterThanEquals: case BoundBinaryOperation::GreaterThanEquals: {
{
auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft()); auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft());
auto rightValue = this->EvaluateIntegerExpression(expression->GetRight()); auto rightValue = this->EvaluateIntegerExpression(expression->GetRight());
return leftValue->operator>=(rightValue); return leftValue->operator>=(rightValue);
} }
case BoundBinaryOperation::LogicalAnd: case BoundBinaryOperation::LogicalAnd: {
{
auto leftValue = this->EvaluateBoolExpression(expression->GetLeft()); auto leftValue = this->EvaluateBoolExpression(expression->GetLeft());
if (!leftValue->EvaluateBool()) return leftValue; if (!leftValue->EvaluateBool()) return leftValue;
auto rightValue = this->EvaluateBoolExpression(expression->GetRight()); auto rightValue = this->EvaluateBoolExpression(expression->GetRight());
return rightValue; return rightValue;
} }
case BoundBinaryOperation::LogicalOr: case BoundBinaryOperation::LogicalOr: {
{
auto leftValue = this->EvaluateBoolExpression(expression->GetLeft()); auto leftValue = this->EvaluateBoolExpression(expression->GetLeft());
if (leftValue->EvaluateBool()) return leftValue; if (leftValue->EvaluateBool()) return leftValue;
auto rightValue = this->EvaluateBoolExpression(expression->GetRight()); auto rightValue = this->EvaluateBoolExpression(expression->GetRight());
@ -93,3 +88,4 @@ const shared_ptr<StringEvalValue> Evaluator::EvaluateStringBinary(const BoundBin
stringStream << *right->EvaluateString(); stringStream << *right->EvaluateString();
return make_shared<StringEvalValue>(stringStream.str()); return make_shared<StringEvalValue>(stringStream.str());
} }
}

View File

@ -3,8 +3,10 @@
#include "StringEvalValue.hpp" #include "StringEvalValue.hpp"
#include <cstring> #include <cstring>
namespace Porygon::Evaluation {
extern "C" { extern "C" {
TypeClass GetEvalValueTypeClass(EvalValue* v){ Porygon::TypeClass GetEvalValueTypeClass(EvalValue *v) {
return v->GetTypeClass(); return v->GetTypeClass();
} }
@ -40,6 +42,7 @@ extern "C" {
return new StringEvalValue(s); return new StringEvalValue(s);
} }
} }
}
#ifdef TESTS_BUILD #ifdef TESTS_BUILD
#include <catch.hpp> #include <catch.hpp>
@ -47,7 +50,7 @@ extern "C" {
TEST_CASE( "Evaluate String", "[integration]" ) { TEST_CASE( "Evaluate String", "[integration]" ) {
auto script = Script::Create(u"\"foo bar\""); auto script = Porygon::Script::Create(u"\"foo bar\"");
REQUIRE(!script->Diagnostics -> HasErrors()); REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate(); script->Evaluate();
auto lastValue = script->GetLastValue(); auto lastValue = script->GetLastValue();

View File

@ -8,10 +8,13 @@
#include <sstream> #include <sstream>
#include <memory> #include <memory>
namespace Porygon::Evaluation {
class EvalValue { class EvalValue {
public: public:
EvalValue() = default; EvalValue() = default;
virtual ~EvalValue() = default; virtual ~EvalValue() = default;
virtual const TypeClass GetTypeClass() const = 0; virtual const TypeClass GetTypeClass() const = 0;
virtual const bool operator==(EvalValue *b) const = 0; virtual const bool operator==(EvalValue *b) const = 0;
@ -25,12 +28,15 @@ public:
virtual const long EvaluateInteger() const { virtual const long EvaluateInteger() const {
throw EvaluationException("Can't evaluate this EvalValue as integer."); throw EvaluationException("Can't evaluate this EvalValue as integer.");
} }
virtual const double EvaluateFloat() const { virtual const double EvaluateFloat() const {
throw EvaluationException("Can't evaluate this EvalValue as float."); throw EvaluationException("Can't evaluate this EvalValue as float.");
} }
virtual const bool EvaluateBool() const { virtual const bool EvaluateBool() const {
throw EvaluationException("Can't evaluate this EvalValue as bool."); throw EvaluationException("Can't evaluate this EvalValue as bool.");
} }
virtual const std::u16string *EvaluateString() const { virtual const std::u16string *EvaluateString() const {
throw EvaluationException("Can't evaluate this EvalValue as string."); throw EvaluationException("Can't evaluate this EvalValue as string.");
} }
@ -54,8 +60,7 @@ class BooleanEvalValue : public EvalValue{
const bool _value; const bool _value;
public: public:
explicit BooleanEvalValue(bool val) explicit BooleanEvalValue(bool val)
: _value(val) : _value(val) {
{
} }
const shared_ptr<EvalValue> Clone() const final { const shared_ptr<EvalValue> Clone() const final {
@ -80,5 +85,6 @@ public:
return _value; return _value;
} }
}; };
}
#endif //PORYGONLANG_EVALVALUE_HPP #endif //PORYGONLANG_EVALVALUE_HPP

View File

@ -1,6 +1,7 @@
#include "NumericEvalValue.hpp" #include "NumericEvalValue.hpp"
namespace Porygon::Evaluation {
const shared_ptr<NumericEvalValue> NumericEvalValue::operator+(const shared_ptr<NumericEvalValue> &b) const { const shared_ptr<NumericEvalValue> NumericEvalValue::operator+(const shared_ptr<NumericEvalValue> &b) const {
if (this->IsFloat()) { if (this->IsFloat()) {
if (b->IsFloat()) { if (b->IsFloat()) {
@ -142,3 +143,4 @@ const shared_ptr<BooleanEvalValue> NumericEvalValue::operator>=(const shared_ptr
} }
} }
} }
}

View File

@ -4,10 +4,11 @@
#include <sstream> #include <sstream>
#include "EvalValue.hpp" #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: public:
@ -18,23 +19,37 @@ public:
} }
const shared_ptr<NumericEvalValue> operator+(const shared_ptr<NumericEvalValue> &b) const; const shared_ptr<NumericEvalValue> operator+(const shared_ptr<NumericEvalValue> &b) const;
const shared_ptr<NumericEvalValue> operator-(const shared_ptr<NumericEvalValue> &b) const; const shared_ptr<NumericEvalValue> operator-(const shared_ptr<NumericEvalValue> &b) const;
const shared_ptr<NumericEvalValue> operator*(const shared_ptr<NumericEvalValue> &b) const; const shared_ptr<NumericEvalValue> operator*(const shared_ptr<NumericEvalValue> &b) const;
const shared_ptr<NumericEvalValue> operator/(const shared_ptr<NumericEvalValue> &b) const; const shared_ptr<NumericEvalValue> operator/(const shared_ptr<NumericEvalValue> &b) const;
const shared_ptr<BooleanEvalValue> operator<(const shared_ptr<NumericEvalValue> &b) const; const shared_ptr<BooleanEvalValue> operator<(const shared_ptr<NumericEvalValue> &b) const;
const shared_ptr<BooleanEvalValue> operator<=(const shared_ptr<NumericEvalValue> &b) const; const shared_ptr<BooleanEvalValue> operator<=(const shared_ptr<NumericEvalValue> &b) const;
const shared_ptr<BooleanEvalValue> operator>(const shared_ptr<NumericEvalValue> &b) const; const shared_ptr<BooleanEvalValue> operator>(const shared_ptr<NumericEvalValue> &b) const;
const shared_ptr<BooleanEvalValue> operator>=(const shared_ptr<NumericEvalValue> &b) const; const shared_ptr<BooleanEvalValue> operator>=(const shared_ptr<NumericEvalValue> &b) const;
const bool operator==(EvalValue *b) const final; const bool operator==(EvalValue *b) const final;
}; };
class IntegerEvalValue : public NumericEvalValue { class IntegerEvalValue : public NumericEvalValue {
const long _value; const long _value;
const long GetIntegerValue() const final { return _value; } const long GetIntegerValue() const final { return _value; }
const double GetFloatValue() const final{ throw EvaluationException("Attempting to retrieve float from int eval value."); }
const double GetFloatValue() const final {
throw EvaluationException("Attempting to retrieve float from int eval value.");
}
public: public:
explicit IntegerEvalValue(long value) : _value(value) { explicit IntegerEvalValue(long value) : _value(value) {
} }
const bool IsFloat() const final { const bool IsFloat() const final {
return false; return false;
} }
@ -54,11 +69,17 @@ public:
class FloatEvalValue : public NumericEvalValue { class FloatEvalValue : public NumericEvalValue {
const double _value; const double _value;
const long GetIntegerValue() const final{ throw EvaluationException("Attempting to retrieve float from int eval value."); }
const long GetIntegerValue() const final {
throw EvaluationException("Attempting to retrieve float from int eval value.");
}
const double GetFloatValue() const final { return _value; } const double GetFloatValue() const final { return _value; }
public: public:
explicit FloatEvalValue(double value) : _value(value) { explicit FloatEvalValue(double value) : _value(value) {
} }
const bool IsFloat() const final { const bool IsFloat() const final {
return true; return true;
} }
@ -75,5 +96,6 @@ public:
return std::hash<double>{}(_value); return std::hash<double>{}(_value);
} }
}; };
}
#endif //PORYGONLANG_NUMERICEVALVALUE_HPP #endif //PORYGONLANG_NUMERICEVALVALUE_HPP

View File

@ -11,29 +11,30 @@
#include "../Evaluator.hpp" #include "../Evaluator.hpp"
#include "../EvaluationScope/EvaluationScope.hpp" #include "../EvaluationScope/EvaluationScope.hpp"
namespace Porygon::Evaluation {
class ScriptFunctionEvalValue : public EvalValue { class ScriptFunctionEvalValue : public EvalValue {
const std::shared_ptr<BoundBlockStatement> _innerBlock; const std::shared_ptr<BoundBlockStatement> _innerBlock;
const std::shared_ptr<FunctionScriptType> _type; const std::shared_ptr<FunctionScriptType> _type;
const std::shared_ptr<EvaluationScope> _scope; const std::shared_ptr<EvaluationScope> _scope;
const std::size_t _hash; const std::size_t _hash;
explicit ScriptFunctionEvalValue(std::shared_ptr<BoundBlockStatement> innerBlock, std::shared_ptr<EvaluationScope> scope,
explicit ScriptFunctionEvalValue(std::shared_ptr<BoundBlockStatement> innerBlock,
std::shared_ptr<EvaluationScope> scope,
std::shared_ptr<FunctionScriptType> type, size_t hash) std::shared_ptr<FunctionScriptType> type, size_t hash)
: _type(std::move(type)), : _type(std::move(type)),
_innerBlock(std::move(innerBlock)), _innerBlock(std::move(innerBlock)),
_scope(std::move(scope)), _scope(std::move(scope)),
_hash(hash) _hash(hash) {
{
} }
public: public:
explicit ScriptFunctionEvalValue(std::shared_ptr<BoundBlockStatement> innerBlock, std::shared_ptr<EvaluationScope> scope, explicit ScriptFunctionEvalValue(std::shared_ptr<BoundBlockStatement> innerBlock,
std::shared_ptr<EvaluationScope> scope,
std::shared_ptr<FunctionScriptType> type) std::shared_ptr<FunctionScriptType> type)
: _type(std::move(type)), : _type(std::move(type)),
_innerBlock(std::move(innerBlock)), _innerBlock(std::move(innerBlock)),
_scope(std::move(scope)), _scope(std::move(scope)),
_hash(rand()) _hash(rand()) {
{
} }
const std::shared_ptr<ScriptType> GetType() const { const std::shared_ptr<ScriptType> GetType() const {
@ -68,6 +69,7 @@ public:
return _scope; return _scope;
} }
}; };
}
#endif //PORYGONLANG_SCRIPTFUNCTIONEVALVALUE_HPP #endif //PORYGONLANG_SCRIPTFUNCTIONEVALVALUE_HPP

View File

@ -8,13 +8,14 @@
using namespace std; using namespace std;
namespace Porygon::Evaluation {
class StringEvalValue : public EvalValue { class StringEvalValue : public EvalValue {
u16string _value; u16string _value;
size_t _hash; size_t _hash;
public: public:
explicit StringEvalValue(u16string s) { explicit StringEvalValue(u16string s) {
_value = move(s); _value = move(s);
_hash = HashedString::ConstHash (_value.c_str()); _hash = Utilities::HashedString::ConstHash(_value.c_str());
} }
const TypeClass GetTypeClass() const final { const TypeClass GetTypeClass() const final {
@ -45,6 +46,6 @@ public:
return _hash; return _hash;
} }
}; };
}
#endif //PORYGONLANG_STRINGEVALVALUE_HPP #endif //PORYGONLANG_STRINGEVALVALUE_HPP

View File

@ -6,6 +6,7 @@
using namespace std; using namespace std;
namespace Porygon::Evaluation {
class TableEvalValue : public EvalValue { class TableEvalValue : public EvalValue {
shared_ptr<unordered_map<uint32_t, shared_ptr<EvalValue>>> _table; shared_ptr<unordered_map<uint32_t, shared_ptr<EvalValue>>> _table;
size_t _hash; size_t _hash;
@ -14,6 +15,7 @@ class TableEvalValue : public EvalValue {
_table = std::move(table); _table = std::move(table);
_hash = hash; _hash = hash;
} }
public: public:
explicit TableEvalValue(shared_ptr<unordered_map<uint32_t, shared_ptr<EvalValue>>> table) { explicit TableEvalValue(shared_ptr<unordered_map<uint32_t, shared_ptr<EvalValue>>> table) {
_table = std::move(table); _table = std::move(table);
@ -46,7 +48,7 @@ public:
} }
const shared_ptr<EvalValue> IndexValue(const char *val) const { const shared_ptr<EvalValue> IndexValue(const char *val) const {
auto hash = HashedString::ConstHash(val); auto hash = Utilities::HashedString::ConstHash(val);
return this->_table->at(hash); return this->_table->at(hash);
} }
@ -55,6 +57,6 @@ public:
this->_table->at(hash) = value; this->_table->at(hash) = value;
} }
}; };
}
#endif //PORYGONLANG_TABLEEVALVALUE_HPP #endif //PORYGONLANG_TABLEEVALVALUE_HPP

View File

@ -7,6 +7,7 @@
#include <string> #include <string>
using namespace std; using namespace std;
namespace Porygon::Evaluation {
class EvaluationException : public std::exception { class EvaluationException : public std::exception {
string _message; string _message;
public: public:
@ -15,10 +16,11 @@ public:
} }
const string defaultErrorText = "An evaluation exception occurred: "; const string defaultErrorText = "An evaluation exception occurred: ";
const char *what() const noexcept final { const char *what() const noexcept final {
return (defaultErrorText + _message).c_str(); return (defaultErrorText + _message).c_str();
} }
}; };
}
#endif //PORYGONLANG_EVALUATIONEXCEPTION_HPP #endif //PORYGONLANG_EVALUATIONEXCEPTION_HPP

View File

@ -2,7 +2,9 @@
#include "EvaluationScope.hpp" #include "EvaluationScope.hpp"
#include <memory> #include <memory>
EvaluationScope::EvaluationScope(unordered_map<uint32_t, shared_ptr<EvalValue>> *scriptVariables, int localVariableCount) { namespace Porygon::Evaluation {
EvaluationScope::EvaluationScope(unordered_map<uint32_t, shared_ptr<EvalValue>> *scriptVariables,
int localVariableCount) {
_scriptScope = scriptVariables; _scriptScope = scriptVariables;
_localScope = unordered_map<uint64_t, shared_ptr<EvalValue>>(localVariableCount); _localScope = unordered_map<uint64_t, shared_ptr<EvalValue>>(localVariableCount);
} }
@ -33,3 +35,4 @@ shared_ptr<EvalValue> EvaluationScope::GetVariable(const BoundVariableKey* key)
return _localScope[key->GetHash()]; return _localScope[key->GetHash()];
} }
} }
}

View File

@ -5,18 +5,24 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "../EvalValues/EvalValue.hpp" #include "../EvalValues/EvalValue.hpp"
using namespace Porygon::Binder;
namespace Porygon::Evaluation {
class EvaluationScope { class EvaluationScope {
unordered_map<uint32_t, shared_ptr<EvalValue>> *_scriptScope; unordered_map<uint32_t, shared_ptr<EvalValue>> *_scriptScope;
unordered_map<uint64_t, shared_ptr<EvalValue>> _localScope; unordered_map<uint64_t, shared_ptr<EvalValue>> _localScope;
public: public:
explicit EvaluationScope(unordered_map<uint32_t, shared_ptr<EvalValue>> *scriptVariables, int deepestScope); explicit EvaluationScope(unordered_map<uint32_t, shared_ptr<EvalValue>> *scriptVariables, int deepestScope);
~EvaluationScope() = default; ~EvaluationScope() = default;
void CreateVariable(const BoundVariableKey *key, const shared_ptr<EvalValue> &value); void CreateVariable(const BoundVariableKey *key, const shared_ptr<EvalValue> &value);
void SetVariable(const BoundVariableKey *key, const shared_ptr<EvalValue> &value); void SetVariable(const BoundVariableKey *key, const shared_ptr<EvalValue> &value);
shared_ptr<EvalValue> GetVariable(const BoundVariableKey *key); shared_ptr<EvalValue> GetVariable(const BoundVariableKey *key);
}; };
}
#endif //PORYGONLANG_EVALUATIONSCOPE_HPP #endif //PORYGONLANG_EVALUATIONSCOPE_HPP

View File

@ -11,9 +11,12 @@
#include "../TableScriptType.hpp" #include "../TableScriptType.hpp"
using namespace std; using namespace std;
using namespace Porygon::Binder;
namespace Porygon::Evaluation {
EvalValue *Evaluator::Evaluate(const BoundScriptStatement *statement) { EvalValue *Evaluator::Evaluate(const BoundScriptStatement *statement) {
this->_evaluationScope = make_shared<EvaluationScope>(this->_scriptData->_scriptVariables, statement->GetLocalVariableCount()); this->_evaluationScope = make_shared<EvaluationScope>(this->_scriptVariables,
statement->GetLocalVariableCount());
EvaluateBlockStatement(statement); EvaluateBlockStatement(statement);
return this->_returnValue.get(); return this->_returnValue.get();
} }
@ -22,15 +25,22 @@ void Evaluator::EvaluateStatement(const BoundStatement *statement) {
if (this->_hasReturned) if (this->_hasReturned)
return; return;
switch (statement->GetKind()) { switch (statement->GetKind()) {
case BoundStatementKind ::Script: throw; // Should never happen case BoundStatementKind::Script:
case BoundStatementKind ::Block: return this->EvaluateBlockStatement((BoundBlockStatement *) statement); throw; // Should never happen
case BoundStatementKind ::Expression: return this -> EvaluateExpressionStatement((BoundExpressionStatement*)statement); case BoundStatementKind::Block:
case BoundStatementKind ::Assignment: return this -> EvaluateAssignmentStatement((BoundAssignmentStatement*)statement); return this->EvaluateBlockStatement((BoundBlockStatement *) statement);
case BoundStatementKind::Expression:
return this->EvaluateExpressionStatement((BoundExpressionStatement *) statement);
case BoundStatementKind::Assignment:
return this->EvaluateAssignmentStatement((BoundAssignmentStatement *) statement);
case BoundStatementKind::IndexAssignment: case BoundStatementKind::IndexAssignment:
return this->EvaluateIndexAssignmentStatement((BoundIndexAssignmentStatement *) statement); return this->EvaluateIndexAssignmentStatement((BoundIndexAssignmentStatement *) statement);
case BoundStatementKind ::FunctionDeclaration: return this->EvaluateFunctionDeclarationStatement((BoundFunctionDeclarationStatement*)statement); case BoundStatementKind::FunctionDeclaration:
case BoundStatementKind::Return: return this -> EvaluateReturnStatement((BoundReturnStatement*)statement); return this->EvaluateFunctionDeclarationStatement((BoundFunctionDeclarationStatement *) statement);
case BoundStatementKind::Conditional: return this -> EvaluateConditionalStatement((BoundConditionalStatement*)statement); case BoundStatementKind::Return:
return this->EvaluateReturnStatement((BoundReturnStatement *) statement);
case BoundStatementKind::Conditional:
return this->EvaluateConditionalStatement((BoundConditionalStatement *) statement);
case BoundStatementKind::Bad: case BoundStatementKind::Bad:
throw; throw;
@ -107,14 +117,22 @@ void Evaluator::EvaluateConditionalStatement(const BoundConditionalStatement *st
const shared_ptr<EvalValue> Evaluator::EvaluateExpression(const BoundExpression *expression) { const shared_ptr<EvalValue> Evaluator::EvaluateExpression(const BoundExpression *expression) {
auto type = expression->GetType(); auto type = expression->GetType();
switch (type->GetClass()) { switch (type->GetClass()) {
case TypeClass ::Number: return this -> EvaluateIntegerExpression(expression); case TypeClass::Number:
case TypeClass ::Bool: return this -> EvaluateBoolExpression(expression); return this->EvaluateIntegerExpression(expression);
case TypeClass ::String: return this -> EvaluateStringExpression(expression); case TypeClass::Bool:
case TypeClass ::Function: return this->EvaluateFunctionExpression(expression); return this->EvaluateBoolExpression(expression);
case TypeClass ::Nil: return this->EvaluateNilExpression(expression); case TypeClass::String:
case TypeClass ::Table: return this-> EvaluateTableExpression(expression); return this->EvaluateStringExpression(expression);
case TypeClass ::UserData: return this -> EvaluateUserDataExpression(expression); case TypeClass::Function:
default: throw; 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;
} }
} }
@ -128,14 +146,23 @@ const shared_ptr<EvalValue> Evaluator::GetVariable(const BoundVariableExpression
const shared_ptr<NumericEvalValue> Evaluator::EvaluateIntegerExpression(const BoundExpression *expression) { const shared_ptr<NumericEvalValue> Evaluator::EvaluateIntegerExpression(const BoundExpression *expression) {
switch (expression->GetKind()) { switch (expression->GetKind()) {
case BoundExpressionKind ::LiteralInteger: return make_shared<IntegerEvalValue>(((BoundLiteralIntegerExpression*)expression)->GetValue()); case BoundExpressionKind::LiteralInteger:
case BoundExpressionKind ::LiteralFloat: return make_shared<FloatEvalValue>(((BoundLiteralFloatExpression*)expression)->GetValue()); return make_shared<IntegerEvalValue>(((BoundLiteralIntegerExpression *) expression)->GetValue());
case BoundExpressionKind::Unary: return this -> EvaluateIntegerUnary((BoundUnaryExpression*)expression); case BoundExpressionKind::LiteralFloat:
case BoundExpressionKind ::Binary: return this -> EvaluateIntegerBinary((BoundBinaryExpression*)expression); return make_shared<FloatEvalValue>(((BoundLiteralFloatExpression *) expression)->GetValue());
case BoundExpressionKind::Variable: return dynamic_pointer_cast<NumericEvalValue>(this->GetVariable((BoundVariableExpression*)expression)); case BoundExpressionKind::Unary:
case BoundExpressionKind ::FunctionCall: return dynamic_pointer_cast<NumericEvalValue>(this->EvaluateFunctionCallExpression(expression)); return this->EvaluateIntegerUnary((BoundUnaryExpression *) expression);
case BoundExpressionKind ::Index: return dynamic_pointer_cast<NumericEvalValue>(this->EvaluateIndexExpression(expression)); case BoundExpressionKind::Binary:
case BoundExpressionKind ::PeriodIndex: return dynamic_pointer_cast<NumericEvalValue>(this->EvaluatePeriodIndexExpression(expression)); return this->EvaluateIntegerBinary((BoundBinaryExpression *) expression);
case BoundExpressionKind::Variable:
return dynamic_pointer_cast<NumericEvalValue>(
this->GetVariable((BoundVariableExpression *) expression));
case BoundExpressionKind::FunctionCall:
return dynamic_pointer_cast<NumericEvalValue>(this->EvaluateFunctionCallExpression(expression));
case BoundExpressionKind::Index:
return dynamic_pointer_cast<NumericEvalValue>(this->EvaluateIndexExpression(expression));
case BoundExpressionKind::PeriodIndex:
return dynamic_pointer_cast<NumericEvalValue>(this->EvaluatePeriodIndexExpression(expression));
case BoundExpressionKind::LiteralString: case BoundExpressionKind::LiteralString:
case BoundExpressionKind::LiteralBool: case BoundExpressionKind::LiteralBool:
@ -148,13 +175,21 @@ const shared_ptr<NumericEvalValue> Evaluator::EvaluateIntegerExpression(const Bo
const shared_ptr<BooleanEvalValue> Evaluator::EvaluateBoolExpression(const BoundExpression *expression) { const shared_ptr<BooleanEvalValue> Evaluator::EvaluateBoolExpression(const BoundExpression *expression) {
switch (expression->GetKind()) { switch (expression->GetKind()) {
case BoundExpressionKind ::LiteralBool: return make_shared<BooleanEvalValue>(((BoundLiteralBoolExpression*)expression)->GetValue()); case BoundExpressionKind::LiteralBool:
case BoundExpressionKind::Unary: return this -> EvaluateBooleanUnary((BoundUnaryExpression*)expression); return make_shared<BooleanEvalValue>(((BoundLiteralBoolExpression *) expression)->GetValue());
case BoundExpressionKind::Binary: return this -> EvaluateBooleanBinary((BoundBinaryExpression*)expression); case BoundExpressionKind::Unary:
case BoundExpressionKind::Variable: return dynamic_pointer_cast<BooleanEvalValue>(this->GetVariable((BoundVariableExpression*)expression)); return this->EvaluateBooleanUnary((BoundUnaryExpression *) expression);
case BoundExpressionKind ::FunctionCall: return dynamic_pointer_cast<BooleanEvalValue>(this->EvaluateFunctionCallExpression(expression)); case BoundExpressionKind::Binary:
case BoundExpressionKind ::Index: return dynamic_pointer_cast<BooleanEvalValue>(this->EvaluateIndexExpression(expression)); return this->EvaluateBooleanBinary((BoundBinaryExpression *) expression);
case BoundExpressionKind ::PeriodIndex: return dynamic_pointer_cast<BooleanEvalValue>(this->EvaluatePeriodIndexExpression(expression)); case BoundExpressionKind::Variable:
return dynamic_pointer_cast<BooleanEvalValue>(
this->GetVariable((BoundVariableExpression *) expression));
case BoundExpressionKind::FunctionCall:
return dynamic_pointer_cast<BooleanEvalValue>(this->EvaluateFunctionCallExpression(expression));
case BoundExpressionKind::Index:
return dynamic_pointer_cast<BooleanEvalValue>(this->EvaluateIndexExpression(expression));
case BoundExpressionKind::PeriodIndex:
return dynamic_pointer_cast<BooleanEvalValue>(this->EvaluatePeriodIndexExpression(expression));
case BoundExpressionKind::Bad: case BoundExpressionKind::Bad:
case BoundExpressionKind::LiteralInteger: case BoundExpressionKind::LiteralInteger:
@ -173,10 +208,14 @@ const shared_ptr<StringEvalValue> Evaluator::EvaluateStringExpression(const Boun
return make_shared<StringEvalValue>(((BoundLiteralStringExpression *) expression)->GetValue()); return make_shared<StringEvalValue>(((BoundLiteralStringExpression *) expression)->GetValue());
case BoundExpressionKind::Binary: case BoundExpressionKind::Binary:
return this->EvaluateStringBinary((BoundBinaryExpression *) expression); return this->EvaluateStringBinary((BoundBinaryExpression *) expression);
case BoundExpressionKind::Variable: return dynamic_pointer_cast<StringEvalValue>(this->GetVariable((BoundVariableExpression*)expression)); case BoundExpressionKind::Variable:
case BoundExpressionKind ::FunctionCall: return dynamic_pointer_cast<StringEvalValue>(this->EvaluateFunctionCallExpression(expression)); return dynamic_pointer_cast<StringEvalValue>(this->GetVariable((BoundVariableExpression *) expression));
case BoundExpressionKind ::Index: return dynamic_pointer_cast<StringEvalValue>(this->EvaluateIndexExpression(expression)); case BoundExpressionKind::FunctionCall:
case BoundExpressionKind ::PeriodIndex: return dynamic_pointer_cast<StringEvalValue>(this->EvaluatePeriodIndexExpression(expression)); return dynamic_pointer_cast<StringEvalValue>(this->EvaluateFunctionCallExpression(expression));
case BoundExpressionKind::Index:
return dynamic_pointer_cast<StringEvalValue>(this->EvaluateIndexExpression(expression));
case BoundExpressionKind::PeriodIndex:
return dynamic_pointer_cast<StringEvalValue>(this->EvaluatePeriodIndexExpression(expression));
case BoundExpressionKind::Bad: case BoundExpressionKind::Bad:
case BoundExpressionKind::LiteralInteger: case BoundExpressionKind::LiteralInteger:
@ -192,12 +231,17 @@ const shared_ptr<StringEvalValue> Evaluator::EvaluateStringExpression(const Boun
const shared_ptr<EvalValue> Evaluator::EvaluateFunctionExpression(const BoundExpression *expression) { const shared_ptr<EvalValue> Evaluator::EvaluateFunctionExpression(const BoundExpression *expression) {
switch (expression->GetKind()) { switch (expression->GetKind()) {
case BoundExpressionKind ::Variable: return this->GetVariable((BoundVariableExpression*)expression); case BoundExpressionKind::Variable:
case BoundExpressionKind ::Index: return this->EvaluateIndexExpression(expression); return this->GetVariable((BoundVariableExpression *) expression);
case BoundExpressionKind ::PeriodIndex: return this->EvaluatePeriodIndexExpression(expression); case BoundExpressionKind::Index:
default: throw; return this->EvaluateIndexExpression(expression);
case BoundExpressionKind::PeriodIndex:
return this->EvaluatePeriodIndexExpression(expression);
default:
throw;
} }
} }
const shared_ptr<EvalValue> Evaluator::EvaluateNilExpression(const BoundExpression *expression) { const shared_ptr<EvalValue> Evaluator::EvaluateNilExpression(const BoundExpression *expression) {
switch (expression->GetKind()) { switch (expression->GetKind()) {
case BoundExpressionKind::FunctionCall: case BoundExpressionKind::FunctionCall:
@ -206,26 +250,31 @@ const shared_ptr<EvalValue> Evaluator::EvaluateNilExpression(const BoundExpressi
return nullptr; return nullptr;
} }
} }
const shared_ptr<EvalValue> Evaluator::EvaluateTableExpression(const BoundExpression *expression) { const shared_ptr<EvalValue> Evaluator::EvaluateTableExpression(const BoundExpression *expression) {
switch (expression->GetKind()) { switch (expression->GetKind()) {
case BoundExpressionKind::FunctionCall: case BoundExpressionKind::FunctionCall:
return this->EvaluateFunctionCallExpression(expression); return this->EvaluateFunctionCallExpression(expression);
case BoundExpressionKind ::Variable: return this->GetVariable((BoundVariableExpression*)expression); case BoundExpressionKind::Variable:
case BoundExpressionKind ::Index: return this->EvaluateIndexExpression(expression); return this->GetVariable((BoundVariableExpression *) expression);
case BoundExpressionKind ::NumericalTable: return this-> EvaluateNumericTableExpression(expression); case BoundExpressionKind::Index:
case BoundExpressionKind ::Table: return this -> EvaluateComplexTableExpression(expression); return this->EvaluateIndexExpression(expression);
case BoundExpressionKind ::PeriodIndex: return this->EvaluatePeriodIndexExpression(expression); case BoundExpressionKind::NumericalTable:
return this->EvaluateNumericTableExpression(expression);
case BoundExpressionKind::Table:
return this->EvaluateComplexTableExpression(expression);
case BoundExpressionKind::PeriodIndex:
return this->EvaluatePeriodIndexExpression(expression);
default: default:
throw; throw;
} }
} }
const shared_ptr<EvalValue> Evaluator::EvaluateFunctionCallExpression(const BoundExpression *expression) { const shared_ptr<EvalValue> Evaluator::EvaluateFunctionCallExpression(const BoundExpression *expression) {
auto functionCall = (BoundFunctionCallExpression *) expression; auto functionCall = (BoundFunctionCallExpression *) expression;
auto function = dynamic_pointer_cast<ScriptFunctionEvalValue>(this->EvaluateExpression(functionCall->GetFunctionExpression())); auto function = dynamic_pointer_cast<ScriptFunctionEvalValue>(
this->EvaluateExpression(functionCall->GetFunctionExpression()));
auto boundParameters = functionCall->GetParameters(); auto boundParameters = functionCall->GetParameters();
auto parameters = vector<shared_ptr<EvalValue>>(boundParameters->size()); auto parameters = vector<shared_ptr<EvalValue>>(boundParameters->size());
@ -319,9 +368,12 @@ const shared_ptr<EvalValue> Evaluator::EvaluateComplexTableExpression(const Boun
const shared_ptr<EvalValue> Evaluator::EvaluateUserDataExpression(const BoundExpression *expression) { const shared_ptr<EvalValue> Evaluator::EvaluateUserDataExpression(const BoundExpression *expression) {
switch (expression->GetKind()) { switch (expression->GetKind()) {
case BoundExpressionKind ::Variable: return this->GetVariable((BoundVariableExpression*)expression); case BoundExpressionKind::Variable:
case BoundExpressionKind ::Index: return this -> EvaluateIndexExpression(expression); return this->GetVariable((BoundVariableExpression *) expression);
default: throw; case BoundExpressionKind::Index:
return this->EvaluateIndexExpression(expression);
default:
throw;
}
} }
} }

View File

@ -4,7 +4,6 @@
#include <string> #include <string>
#include "../Binder/BoundStatements/BoundStatement.hpp" #include "../Binder/BoundStatements/BoundStatement.hpp"
#include "../Script.hpp"
#include "EvalValues/EvalValue.hpp" #include "EvalValues/EvalValue.hpp"
#include "EvalValues/NumericEvalValue.hpp" #include "EvalValues/NumericEvalValue.hpp"
#include "EvalValues/StringEvalValue.hpp" #include "EvalValues/StringEvalValue.hpp"
@ -14,12 +13,14 @@
using namespace std; using namespace std;
namespace Porygon::Evaluation{
class Evaluator { class Evaluator {
shared_ptr<EvalValue> _returnValue; shared_ptr<EvalValue> _returnValue;
unordered_map<uint32_t, shared_ptr<EvalValue>>* _scriptVariables;
bool _hasReturned; bool _hasReturned;
shared_ptr<EvalValue> _lastValue; shared_ptr<EvalValue> _lastValue;
Script* _scriptData; //Porygon::Script* _scriptData;
shared_ptr<EvaluationScope> _evaluationScope; shared_ptr<EvaluationScope> _evaluationScope;
void EvaluateStatement(const BoundStatement* statement); void EvaluateStatement(const BoundStatement* statement);
@ -54,8 +55,8 @@ class Evaluator {
const shared_ptr<EvalValue> GetVariable(const BoundVariableExpression *expression); const shared_ptr<EvalValue> GetVariable(const BoundVariableExpression *expression);
public: public:
explicit Evaluator(Script* script){ explicit Evaluator(unordered_map<uint32_t, shared_ptr<EvalValue>>* scriptVariables){
_scriptData = script; _scriptVariables = scriptVariables;
_hasReturned = false; _hasReturned = false;
_returnValue = nullptr; _returnValue = nullptr;
_evaluationScope = nullptr; _evaluationScope = nullptr;
@ -70,6 +71,7 @@ public:
} }
}; };
}

View File

@ -4,10 +4,10 @@
#include "EvaluationException.hpp" #include "EvaluationException.hpp"
#include "../Script.hpp" #include "../Script.hpp"
namespace Porygon::Evaluation {
const shared_ptr<NumericEvalValue> Evaluator::EvaluateIntegerUnary(const BoundUnaryExpression *expression) { const shared_ptr<NumericEvalValue> Evaluator::EvaluateIntegerUnary(const BoundUnaryExpression *expression) {
switch (expression->GetOperation()) { switch (expression->GetOperation()) {
case BoundUnaryOperation::Negation: case BoundUnaryOperation::Negation: {
{
auto operandValue = EvaluateIntegerExpression(expression->GetOperand()); auto operandValue = EvaluateIntegerExpression(expression->GetOperand());
if (operandValue->IsFloat()) { if (operandValue->IsFloat()) {
double f = operandValue->EvaluateFloat(); double f = operandValue->EvaluateFloat();
@ -24,8 +24,7 @@ const shared_ptr<NumericEvalValue> Evaluator::EvaluateIntegerUnary(const BoundUn
const shared_ptr<BooleanEvalValue> Evaluator::EvaluateBooleanUnary(const BoundUnaryExpression *expression) { const shared_ptr<BooleanEvalValue> Evaluator::EvaluateBooleanUnary(const BoundUnaryExpression *expression) {
switch (expression->GetOperation()) { switch (expression->GetOperation()) {
case BoundUnaryOperation::LogicalNegation: case BoundUnaryOperation::LogicalNegation: {
{
auto val = EvaluateBoolExpression(expression->GetOperand()); auto val = EvaluateBoolExpression(expression->GetOperand());
bool b = val->EvaluateBool(); bool b = val->EvaluateBool();
return make_shared<BooleanEvalValue>(!b); return make_shared<BooleanEvalValue>(!b);
@ -34,3 +33,4 @@ const shared_ptr<BooleanEvalValue> Evaluator::EvaluateBooleanUnary(const BoundUn
throw; throw;
} }
} }
}

View File

@ -1,6 +1,8 @@
#ifndef PORYGONLANG_BINARYOPERATORKIND_HPP #ifndef PORYGONLANG_BINARYOPERATORKIND_HPP
#define PORYGONLANG_BINARYOPERATORKIND_HPP #define PORYGONLANG_BINARYOPERATORKIND_HPP
namespace Porygon::Parser {
enum class BinaryOperatorKind { enum class BinaryOperatorKind {
// Math // Math
Addition, Addition,
@ -20,4 +22,5 @@ enum class BinaryOperatorKind{
LogicalAnd, LogicalAnd,
LogicalOr, LogicalOr,
}; };
}
#endif //PORYGONLANG_BINARYOPERATORKIND_HPP #endif //PORYGONLANG_BINARYOPERATORKIND_HPP

View File

@ -5,9 +5,9 @@
#include "Lexer.hpp" #include "Lexer.hpp"
Lexer::Lexer(const u16string& scriptString, class Script* script) namespace Porygon::Parser {
: _scriptString(scriptString) Lexer::Lexer(const u16string &scriptString, Porygon::Script *script)
{ : _scriptString(scriptString) {
this->_scriptSize = scriptString.size(); this->_scriptSize = scriptString.size();
this->ScriptData = script; this->ScriptData = script;
this->_position = 0; this->_position = 0;
@ -45,7 +45,12 @@ IToken* Lexer::LexNext(char16_t c){
switch (c) { switch (c) {
case '\0': case '\0':
return new SimpleToken(TokenKind::EndOfFile, this->_position - 1, 1); return new SimpleToken(TokenKind::EndOfFile, this->_position - 1, 1);
case ' ': case '\t': case '\n': case '\r': case '\v': case '\f': case ' ':
case '\t':
case '\n':
case '\r':
case '\v':
case '\f':
return new SimpleToken(TokenKind::WhiteSpace, this->_position - 1, 1); return new SimpleToken(TokenKind::WhiteSpace, this->_position - 1, 1);
case '+': case '+':
return new SimpleToken(TokenKind::PlusToken, this->_position - 1, 1); return new SimpleToken(TokenKind::PlusToken, this->_position - 1, 1);
@ -96,7 +101,16 @@ IToken* Lexer::LexNext(char16_t c){
} }
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedCharacter, this->_position - 1, 1); this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedCharacter, this->_position - 1, 1);
return new SimpleToken(TokenKind::BadToken, 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': case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return LexNumber(c); return LexNumber(c);
case '"': case '"':
return LexString(c); return LexString(c);
@ -115,17 +129,28 @@ IToken* Lexer::LexNext(char16_t c){
int CharToInt(char16_t c) { int CharToInt(char16_t c) {
switch (c) { switch (c) {
case '0': return 0; case '0':
case '1': return 1; return 0;
case '2': return 2; case '1':
case '3': return 3; return 1;
case '4': return 4; case '2':
case '5': return 5; return 2;
case '6': return 6; case '3':
case '7': return 7; return 3;
case '8': return 8; case '4':
case '9': return 9; return 4;
default: return -1; case '5':
return 5;
case '6':
return 6;
case '7':
return 7;
case '8':
return 8;
case '9':
return 9;
default:
return -1;
} }
} }
@ -157,15 +182,13 @@ IToken* Lexer::LexNumber(char16_t c){
is_searching = false; is_searching = false;
continue; continue;
} }
} } else {
else{
this->Next(); this->Next();
length++; length++;
if (has_point) { if (has_point) {
decimal_index++; decimal_index++;
float_value += next_val / pow(10, decimal_index); float_value += next_val / pow(10, decimal_index);
} } else {
else {
int_value *= 10; int_value *= 10;
int_value += next_val; int_value += next_val;
} }
@ -173,8 +196,7 @@ IToken* Lexer::LexNumber(char16_t c){
} }
if (has_point) { if (has_point) {
return new FloatToken(float_value, start, length); return new FloatToken(float_value, start, length);
} } else {
else{
return new IntegerToken(int_value, start, length); return new IntegerToken(int_value, start, length);
} }
} }
@ -188,34 +210,53 @@ IToken * Lexer::LexIdentifierOrKeyword() {
if (isalpha(next) || next == '_' || next > 255) { if (isalpha(next) || next == '_' || next > 255) {
this->Next(); this->Next();
end++; end++;
} } else {
else{
break; break;
} }
} }
u16string s = this->_scriptString.substr(start, end - start + 1); u16string s = this->_scriptString.substr(start, end - start + 1);
switch (HashedString::ConstHash(s.c_str())) { switch (HashedString::ConstHash(s.c_str())) {
case HashedString::ConstHash("and"): return new SimpleToken(TokenKind::AndKeyword, start, 3); case HashedString::ConstHash("and"):
case HashedString::ConstHash("break"): return new SimpleToken(TokenKind::BreakKeyword, start, 5); return new SimpleToken(TokenKind::AndKeyword, start, 3);
case HashedString::ConstHash("do"): return new SimpleToken(TokenKind::DoKeyword, start, 2); case HashedString::ConstHash("break"):
case HashedString::ConstHash("else"): return new SimpleToken(TokenKind::ElseKeyword, start, 4); return new SimpleToken(TokenKind::BreakKeyword, start, 5);
case HashedString::ConstHash("elseif"): return new SimpleToken(TokenKind::ElseIfKeyword, start, 6); case HashedString::ConstHash("do"):
case HashedString::ConstHash("end"): return new SimpleToken(TokenKind::EndKeyword, start, 3); return new SimpleToken(TokenKind::DoKeyword, start, 2);
case HashedString::ConstHash("false"): return new SimpleToken(TokenKind::FalseKeyword, start, 5); case HashedString::ConstHash("else"):
case HashedString::ConstHash("for"): return new SimpleToken(TokenKind::ForKeyword, start, 3); return new SimpleToken(TokenKind::ElseKeyword, start, 4);
case HashedString::ConstHash("function"): return new SimpleToken(TokenKind::FunctionKeyword, start, 8); case HashedString::ConstHash("elseif"):
case HashedString::ConstHash("if"): return new SimpleToken(TokenKind::IfKeyword, start, 2); return new SimpleToken(TokenKind::ElseIfKeyword, start, 6);
case HashedString::ConstHash("in"): return new SimpleToken(TokenKind::InKeyword, start, 2); case HashedString::ConstHash("end"):
case HashedString::ConstHash("local"): return new SimpleToken(TokenKind::LocalKeyword, start, 5); return new SimpleToken(TokenKind::EndKeyword, start, 3);
case HashedString::ConstHash("nil"): return new SimpleToken(TokenKind::NilKeyword, start, 3); case HashedString::ConstHash("false"):
case HashedString::ConstHash("not"): return new SimpleToken(TokenKind::NotKeyword, start, 3); return new SimpleToken(TokenKind::FalseKeyword, start, 5);
case HashedString::ConstHash("or"): return new SimpleToken(TokenKind::OrKeyword, start, 2); case HashedString::ConstHash("for"):
case HashedString::ConstHash("return"): return new SimpleToken(TokenKind::ReturnKeyword, start, 6); return new SimpleToken(TokenKind::ForKeyword, start, 3);
case HashedString::ConstHash("then"): return new SimpleToken(TokenKind::ThenKeyword, start, 4); case HashedString::ConstHash("function"):
case HashedString::ConstHash("true"): return new SimpleToken(TokenKind::TrueKeyword, start, 4); return new SimpleToken(TokenKind::FunctionKeyword, start, 8);
case HashedString::ConstHash("while"): return new SimpleToken(TokenKind::WhileKeyword, start, 5); case HashedString::ConstHash("if"):
default: return new IdentifierToken(HashedString(s), start, s.length()); 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());
} }
} }
@ -262,7 +303,8 @@ IToken* Lexer::LexString(char16_t c){
if (ControlCharacters.find(c) != ControlCharacters.end()) { if (ControlCharacters.find(c) != ControlCharacters.end()) {
stream << ControlCharacters.at(c); stream << ControlCharacters.at(c);
} else { } else {
this -> ScriptData->Diagnostics->LogError(DiagnosticCode::InvalidStringControlCharacter, start + 1 + i, 1); this->ScriptData->Diagnostics->LogError(DiagnosticCode::InvalidStringControlCharacter,
start + 1 + i, 1);
stream << c; stream << c;
} }
} else { } else {
@ -272,3 +314,4 @@ IToken* Lexer::LexString(char16_t c){
return new StringToken(stream.str(), start, end - start); return new StringToken(stream.str(), start, end - start);
} }
}

View File

@ -7,6 +7,7 @@
using namespace std; using namespace std;
namespace Porygon::Parser{
class Lexer { class Lexer {
const u16string& _scriptString; const u16string& _scriptString;
#ifdef TESTS_BUILD #ifdef TESTS_BUILD
@ -21,12 +22,13 @@ public:
IToken* LexIdentifierOrKeyword(); IToken* LexIdentifierOrKeyword();
IToken* LexString(char16_t c); IToken* LexString(char16_t c);
public: public:
Script* ScriptData; Porygon::Script* ScriptData;
vector<const IToken*> Lex(); vector<const IToken*> Lex();
explicit Lexer(const u16string& scriptString, class Script* script); explicit Lexer(const u16string& scriptString, Porygon::Script* script);
}; };
}
#endif //PORYGONLANG_LEXER_HPP #endif //PORYGONLANG_LEXER_HPP

View File

@ -11,6 +11,7 @@
#include "../BinaryOperatorKind.hpp" #include "../BinaryOperatorKind.hpp"
#include "../../Utilities/HashedString.hpp" #include "../../Utilities/HashedString.hpp"
namespace Porygon::Parser {
enum class ParsedExpressionKind { enum class ParsedExpressionKind {
Bad, Bad,
@ -36,8 +37,7 @@ class ParsedExpression {
public: public:
ParsedExpression(unsigned int position, unsigned int length) ParsedExpression(unsigned int position, unsigned int length)
: _position(position), : _position(position),
_length(length) _length(length) {
{
} }
virtual ~ParsedExpression() = default; virtual ~ParsedExpression() = default;
@ -72,10 +72,10 @@ public:
const ParsedExpressionKind GetKind() const final { const ParsedExpressionKind GetKind() const final {
return ParsedExpressionKind::LiteralInteger; return ParsedExpressionKind::LiteralInteger;
} }
explicit LiteralIntegerExpression(IntegerToken *token) explicit LiteralIntegerExpression(IntegerToken *token)
: ParsedExpression(token->GetStartPosition(), token->GetLength()), : ParsedExpression(token->GetStartPosition(), token->GetLength()),
_value(token -> GetValue()) _value(token->GetValue()) {
{
} }
const long GetValue() const { const long GetValue() const {
@ -89,10 +89,10 @@ public:
const ParsedExpressionKind GetKind() const final { const ParsedExpressionKind GetKind() const final {
return ParsedExpressionKind::LiteralFloat; return ParsedExpressionKind::LiteralFloat;
} }
explicit LiteralFloatExpression(FloatToken *token) explicit LiteralFloatExpression(FloatToken *token)
: ParsedExpression(token->GetStartPosition(), token->GetLength()), : ParsedExpression(token->GetStartPosition(), token->GetLength()),
_value(token -> GetValue()) _value(token->GetValue()) {
{
} }
const double GetValue() const { const double GetValue() const {
@ -106,10 +106,10 @@ public:
const ParsedExpressionKind GetKind() const final { const ParsedExpressionKind GetKind() const final {
return ParsedExpressionKind::LiteralString; return ParsedExpressionKind::LiteralString;
} }
explicit LiteralStringExpression(StringToken *token) explicit LiteralStringExpression(StringToken *token)
: ParsedExpression(token->GetStartPosition(), token->GetLength()), : ParsedExpression(token->GetStartPosition(), token->GetLength()),
_value(std::move(token -> GetValue())) _value(std::move(token->GetValue())) {
{
} }
const u16string &GetValue() const { const u16string &GetValue() const {
@ -123,10 +123,10 @@ public:
const ParsedExpressionKind GetKind() const final { const ParsedExpressionKind GetKind() const final {
return ParsedExpressionKind::LiteralBool; return ParsedExpressionKind::LiteralBool;
} }
explicit LiteralBoolExpression(const IToken *token) explicit LiteralBoolExpression(const IToken *token)
: ParsedExpression(token->GetStartPosition(), token->GetLength()), : ParsedExpression(token->GetStartPosition(), token->GetLength()),
_value(token -> GetKind() == TokenKind::TrueKeyword) _value(token->GetKind() == TokenKind::TrueKeyword) {
{
} }
const bool GetValue() const { const bool GetValue() const {
@ -140,9 +140,10 @@ public:
const ParsedExpressionKind GetKind() const final { const ParsedExpressionKind GetKind() const final {
return ParsedExpressionKind::Variable; return ParsedExpressionKind::Variable;
} }
explicit VariableExpression(IdentifierToken* token) : ParsedExpression(token -> GetStartPosition(), token -> GetLength())
, _value(HashedString(token -> GetValue())) explicit VariableExpression(IdentifierToken *token) : ParsedExpression(token->GetStartPosition(),
{ token->GetLength()),
_value(HashedString(token->GetValue())) {
} }
const HashedString GetValue() const { const HashedString GetValue() const {
@ -185,8 +186,7 @@ public:
UnaryExpression(UnaryOperatorKind kind, ParsedExpression *operand, unsigned int start, unsigned int length) UnaryExpression(UnaryOperatorKind kind, ParsedExpression *operand, unsigned int start, unsigned int length)
: ParsedExpression(start, length), : ParsedExpression(start, length),
_kind(kind), _operand(operand) _kind(kind), _operand(operand) {
{
} }
const UnaryOperatorKind GetOperatorKind() const { const UnaryOperatorKind GetOperatorKind() const {
@ -215,8 +215,7 @@ public:
BinaryExpression(BinaryOperatorKind kind, ParsedExpression *left, ParsedExpression *right, unsigned int start, BinaryExpression(BinaryOperatorKind kind, ParsedExpression *left, ParsedExpression *right, unsigned int start,
unsigned int length) unsigned int length)
: ParsedExpression(start, length), : ParsedExpression(start, length),
_kind(kind), _left(left), _right(right) _kind(kind), _left(left), _right(right) {
{
} }
const BinaryOperatorKind GetOperatorKind() const { const BinaryOperatorKind GetOperatorKind() const {
@ -236,10 +235,10 @@ class FunctionCallExpression : public ParsedExpression{
const std::unique_ptr<ParsedExpression> _function; const std::unique_ptr<ParsedExpression> _function;
const vector<const ParsedExpression *> _parameters; const vector<const ParsedExpression *> _parameters;
public: public:
FunctionCallExpression(ParsedExpression* function, vector<const ParsedExpression*> parameters, unsigned int start, unsigned int length) FunctionCallExpression(ParsedExpression *function, vector<const ParsedExpression *> parameters,
unsigned int start, unsigned int length)
: ParsedExpression(start, length), : ParsedExpression(start, length),
_function(function), _parameters(std::move(parameters)) _function(function), _parameters(std::move(parameters)) {
{
} }
~FunctionCallExpression() final { ~FunctionCallExpression() final {
@ -255,6 +254,7 @@ public:
const ParsedExpression *GetFunction() const { const ParsedExpression *GetFunction() const {
return _function.get(); return _function.get();
} }
const vector<const ParsedExpression *> *GetParameters() const { const vector<const ParsedExpression *> *GetParameters() const {
return &_parameters; return &_parameters;
} }
@ -266,8 +266,7 @@ class IndexExpression : public ParsedExpression{
public: public:
IndexExpression(ParsedExpression *indexer, ParsedExpression *index, unsigned int start, unsigned int length) IndexExpression(ParsedExpression *indexer, ParsedExpression *index, unsigned int start, unsigned int length)
: ParsedExpression(start, length), : ParsedExpression(start, length),
_indexerExpression(indexer), _indexExpression(index) _indexerExpression(indexer), _indexExpression(index) {
{
} }
~IndexExpression() final { ~IndexExpression() final {
@ -294,8 +293,7 @@ class PeriodIndexExpression : public ParsedExpression{
public: public:
PeriodIndexExpression(ParsedExpression *indexer, HashedString index, unsigned int start, unsigned int length) PeriodIndexExpression(ParsedExpression *indexer, HashedString index, unsigned int start, unsigned int length)
: ParsedExpression(start, length), : ParsedExpression(start, length),
_indexerExpression(indexer), _index(index) _indexerExpression(indexer), _index(index) {
{
} }
~PeriodIndexExpression() final { ~PeriodIndexExpression() final {
@ -319,7 +317,8 @@ public:
class ParsedNumericalTableExpression : public ParsedExpression { class ParsedNumericalTableExpression : public ParsedExpression {
vector<const ParsedExpression *> _expressions; vector<const ParsedExpression *> _expressions;
public: public:
ParsedNumericalTableExpression(vector<const ParsedExpression*> expressions, unsigned int start, unsigned int length) ParsedNumericalTableExpression(vector<const ParsedExpression *> expressions, unsigned int start,
unsigned int length)
: ParsedExpression(start, length) { : ParsedExpression(start, length) {
_expressions = std::move(expressions); _expressions = std::move(expressions);
} }
@ -338,6 +337,6 @@ public:
return ParsedExpressionKind::NumericalTable; return ParsedExpressionKind::NumericalTable;
} }
}; };
}
#endif //PORYGONLANG_PARSEDEXPRESSION_HPP #endif //PORYGONLANG_PARSEDEXPRESSION_HPP

View File

@ -5,12 +5,12 @@
#include "ParsedExpression.hpp" #include "ParsedExpression.hpp"
#include "../ParsedStatements/ParsedStatement.hpp" #include "../ParsedStatements/ParsedStatement.hpp"
namespace Porygon::Parser {
class ParsedTableExpression : public ParsedExpression { class ParsedTableExpression : public ParsedExpression {
const ParsedBlockStatement *_block; const ParsedBlockStatement *_block;
public: public:
ParsedTableExpression(ParsedBlockStatement *block, unsigned int start, unsigned int length) ParsedTableExpression(ParsedBlockStatement *block, unsigned int start, unsigned int length)
: ParsedExpression(start, length), _block(block) : ParsedExpression(start, length), _block(block) {
{
} }
~ParsedTableExpression() final { ~ParsedTableExpression() final {
@ -25,7 +25,7 @@ public:
return ParsedExpressionKind::Table; return ParsedExpressionKind::Table;
} }
}; };
}
#include "ParsedExpression.hpp" #include "ParsedExpression.hpp"
#endif //PORYGONLANG_PARSEDTABLEEXPRESSION_HPP #endif //PORYGONLANG_PARSEDTABLEEXPRESSION_HPP

View File

@ -13,6 +13,7 @@
#include "../../Utilities/HashedString.hpp" #include "../../Utilities/HashedString.hpp"
#include "../TypedVariableIdentifier.hpp" #include "../TypedVariableIdentifier.hpp"
namespace Porygon::Parser {
enum class ParsedStatementKind { enum class ParsedStatementKind {
Bad, Bad,
Script, Script,
@ -30,10 +31,11 @@ class ParsedStatement {
const unsigned int _length; const unsigned int _length;
public: public:
ParsedStatement(unsigned int start, unsigned int length) ParsedStatement(unsigned int start, unsigned int length)
:_start(start), _length(length) : _start(start), _length(length) {
{
} }
virtual ~ParsedStatement() = default; virtual ~ParsedStatement() = default;
virtual const ParsedStatementKind GetKind() const = 0; virtual const ParsedStatementKind GetKind() const = 0;
const unsigned int GetStartPosition() const { const unsigned int GetStartPosition() const {
@ -52,6 +54,7 @@ public:
class ParsedBadStatement : public ParsedStatement { class ParsedBadStatement : public ParsedStatement {
public: public:
ParsedBadStatement(unsigned int start, unsigned int length) : ParsedStatement(start, length) {}; ParsedBadStatement(unsigned int start, unsigned int length) : ParsedStatement(start, length) {};
const ParsedStatementKind GetKind() const final { const ParsedStatementKind GetKind() const final {
return ParsedStatementKind::Bad; return ParsedStatementKind::Bad;
} }
@ -61,13 +64,15 @@ class ParsedBlockStatement : public ParsedStatement{
const std::vector<const ParsedStatement *> _statements; const std::vector<const ParsedStatement *> _statements;
public: public:
explicit ParsedBlockStatement(std::vector<const ParsedStatement *> statements) explicit ParsedBlockStatement(std::vector<const ParsedStatement *> statements)
: ParsedStatement(statements.front()->GetStartPosition(), statements.back()->GetEndPosition() - statements.front()->GetStartPosition()), : ParsedStatement(statements.front()->GetStartPosition(),
_statements(statements) statements.back()->GetEndPosition() - statements.front()->GetStartPosition()),
{} _statements(statements) {}
ParsedBlockStatement(std::vector<const ParsedStatement*> statements, unsigned int start) : ParsedStatement(start, 0), ParsedBlockStatement(std::vector<const ParsedStatement *> statements, unsigned int start) : ParsedStatement(
_statements(std::move(statements)) start, 0),
{ _statements(
std::move(
statements)) {
} }
@ -88,7 +93,8 @@ public:
class ParsedScriptStatement : public ParsedBlockStatement { class ParsedScriptStatement : public ParsedBlockStatement {
public: public:
explicit ParsedScriptStatement(vector<const ParsedStatement*> statements) : ParsedBlockStatement(move(statements)){} explicit ParsedScriptStatement(vector<const ParsedStatement *> statements) : ParsedBlockStatement(
move(statements)) {}
const ParsedStatementKind GetKind() const final { const ParsedStatementKind GetKind() const final {
return ParsedStatementKind::Script; return ParsedStatementKind::Script;
@ -100,8 +106,7 @@ class ParsedExpressionStatement : public ParsedStatement{
public: public:
explicit ParsedExpressionStatement(ParsedExpression *expression) explicit ParsedExpressionStatement(ParsedExpression *expression)
: ParsedStatement(expression->GetStartPosition(), expression->GetLength()), : ParsedStatement(expression->GetStartPosition(), expression->GetLength()),
_expression(expression) _expression(expression) {
{
} }
~ParsedExpressionStatement() override { ~ParsedExpressionStatement() override {
@ -122,9 +127,11 @@ class ParsedFunctionDeclarationStatement : public ParsedStatement{
const vector<TypedVariableIdentifier *> _parameters; const vector<TypedVariableIdentifier *> _parameters;
const ParsedBlockStatement *_block; const ParsedBlockStatement *_block;
public: public:
ParsedFunctionDeclarationStatement(HashedString identifier, vector<TypedVariableIdentifier*> parameters, ParsedBlockStatement* block, ParsedFunctionDeclarationStatement(HashedString identifier, vector<TypedVariableIdentifier *> parameters,
ParsedBlockStatement *block,
unsigned int start, unsigned int length) unsigned int start, unsigned int length)
: ParsedStatement(start, length), _identifier(identifier), _parameters(std::move(parameters)), _block(block){}; : ParsedStatement(start, length), _identifier(identifier), _parameters(std::move(parameters)),
_block(block) {};
~ParsedFunctionDeclarationStatement() override { ~ParsedFunctionDeclarationStatement() override {
for (auto v : _parameters) { for (auto v : _parameters) {
@ -155,9 +162,9 @@ class ParsedAssignmentStatement : public ParsedStatement{
const HashedString _identifier; const HashedString _identifier;
const ParsedExpression *_expression; const ParsedExpression *_expression;
public: public:
ParsedAssignmentStatement(bool local, const HashedString identifier, ParsedExpression* expression, unsigned int start, unsigned int length) ParsedAssignmentStatement(bool local, const HashedString identifier, ParsedExpression *expression,
: ParsedStatement(start, length), _local(local), _identifier(identifier), _expression(expression) unsigned int start, unsigned int length)
{ : ParsedStatement(start, length), _local(local), _identifier(identifier), _expression(expression) {
} }
~ParsedAssignmentStatement() final { ~ParsedAssignmentStatement() final {
@ -185,7 +192,8 @@ class ParsedIndexAssignmentStatement : public ParsedStatement{
const ParsedExpression *_indexExpression; const ParsedExpression *_indexExpression;
const ParsedExpression *_valueExpression; const ParsedExpression *_valueExpression;
public: public:
ParsedIndexAssignmentStatement(ParsedExpression* indexExpression, ParsedExpression* valueExpression, unsigned int start, ParsedIndexAssignmentStatement(ParsedExpression *indexExpression, ParsedExpression *valueExpression,
unsigned int start,
unsigned int length) unsigned int length)
: ParsedStatement(start, length), : ParsedStatement(start, length),
_indexExpression(indexExpression), _valueExpression(valueExpression) {} _indexExpression(indexExpression), _valueExpression(valueExpression) {}
@ -213,8 +221,7 @@ class ParsedReturnStatement : public ParsedStatement{
public: public:
ParsedReturnStatement(ParsedExpression *expression, unsigned int start, unsigned int length) ParsedReturnStatement(ParsedExpression *expression, unsigned int start, unsigned int length)
: ParsedStatement(start, length), : ParsedStatement(start, length),
_expression(expression) _expression(expression) {
{
} }
~ParsedReturnStatement() final { ~ParsedReturnStatement() final {
@ -236,14 +243,14 @@ class ParsedConditionalStatement : public ParsedStatement{
// This can be either else if or else // This can be either else if or else
const ParsedStatement *_elseStatement; const ParsedStatement *_elseStatement;
public: public:
ParsedConditionalStatement(ParsedExpression* condition, ParsedStatement* block, unsigned int start, unsigned int length) ParsedConditionalStatement(ParsedExpression *condition, ParsedStatement *block, unsigned int start,
: ParsedStatement(start, length), _condition(condition), _block(block), _elseStatement(nullptr) 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) ParsedConditionalStatement(ParsedExpression *condition, ParsedStatement *block, ParsedStatement *nextStatement,
: ParsedStatement(start, length), _condition(condition), _block(block), _elseStatement(nextStatement) unsigned int start, unsigned int length)
{ : ParsedStatement(start, length), _condition(condition), _block(block), _elseStatement(nextStatement) {
_condition = condition; _condition = condition;
_block = block; _block = block;
_elseStatement = nextStatement; _elseStatement = nextStatement;
@ -271,5 +278,5 @@ public:
return _elseStatement; return _elseStatement;
} }
}; };
}
#endif //PORYGONLANG_PARSEDSTATEMENT_HPP #endif //PORYGONLANG_PARSEDSTATEMENT_HPP

View File

@ -7,7 +7,7 @@
#include "TypedVariableIdentifier.hpp" #include "TypedVariableIdentifier.hpp"
#include "ParsedExpressions/ParsedTableExpression.hpp" #include "ParsedExpressions/ParsedTableExpression.hpp"
namespace Porygon::Parser {
ParsedScriptStatement *Parser::Parse() { ParsedScriptStatement *Parser::Parse() {
vector<const ParsedStatement *> statements; vector<const ParsedStatement *> statements;
while (this->_position < this->_tokens.size()) { while (this->_position < this->_tokens.size()) {
@ -36,11 +36,16 @@ const IToken *Parser::Next() {
ParsedStatement *Parser::ParseStatement(const IToken *current) { ParsedStatement *Parser::ParseStatement(const IToken *current) {
auto currentKind = current->GetKind(); auto currentKind = current->GetKind();
switch (currentKind) { switch (currentKind) {
case TokenKind ::LocalKeyword: return this->ParseVariableAssignment(current); case TokenKind::LocalKeyword:
case TokenKind ::FunctionKeyword: return this -> ParseFunctionDeclaration(current); return this->ParseVariableAssignment(current);
case TokenKind ::ReturnKeyword: return this->ParseReturnStatement(current); case TokenKind::FunctionKeyword:
case TokenKind ::IfKeyword: return this -> ParseIfStatement(current); return this->ParseFunctionDeclaration(current);
default: break; case TokenKind::ReturnKeyword:
return this->ParseReturnStatement(current);
case TokenKind::IfKeyword:
return this->ParseIfStatement(current);
default:
break;
} }
if (this->Peek()->GetKind() == TokenKind::AssignmentToken) { if (this->Peek()->GetKind() == TokenKind::AssignmentToken) {
return ParseVariableAssignment(current); return ParseVariableAssignment(current);
@ -67,27 +72,32 @@ ParsedStatement *Parser::ParseVariableAssignment(const IToken *current) {
auto expression = this->ParseExpression(this->Next()); auto expression = this->ParseExpression(this->Next());
if (identifier->GetKind() != TokenKind::Identifier) { if (identifier->GetKind() != TokenKind::Identifier) {
this -> ScriptData -> Diagnostics -> LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(), identifier->GetLength()); this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(),
identifier->GetLength());
return new ParsedBadStatement(identifier->GetStartPosition(), identifier->GetLength()); return new ParsedBadStatement(identifier->GetStartPosition(), identifier->GetLength());
} }
if (assignmentToken->GetKind() != TokenKind::AssignmentToken) { if (assignmentToken->GetKind() != TokenKind::AssignmentToken) {
this -> ScriptData -> Diagnostics -> LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(), identifier->GetLength()); this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(),
identifier->GetLength());
return new ParsedBadStatement(identifier->GetStartPosition(), identifier->GetLength()); return new ParsedBadStatement(identifier->GetStartPosition(), identifier->GetLength());
} }
auto start = current->GetStartPosition(); auto start = current->GetStartPosition();
return new ParsedAssignmentStatement(isLocal, ((IdentifierToken*)identifier) -> GetValue(), expression, start, expression->GetEndPosition() - start); return new ParsedAssignmentStatement(isLocal, ((IdentifierToken *) identifier)->GetValue(), expression, start,
expression->GetEndPosition() - start);
} }
ParsedStatement *Parser::ParseIndexAssignment(ParsedExpression *indexer) { ParsedStatement *Parser::ParseIndexAssignment(ParsedExpression *indexer) {
this->Next(); // Consume assignment token this->Next(); // Consume assignment token
auto valueExpression = this->ParseExpression(this->Next()); auto valueExpression = this->ParseExpression(this->Next());
auto start = indexer->GetStartPosition(); auto start = indexer->GetStartPosition();
return new ParsedIndexAssignmentStatement(indexer, valueExpression, start, valueExpression->GetEndPosition() - start); return new ParsedIndexAssignmentStatement(indexer, valueExpression, start,
valueExpression->GetEndPosition() - start);
} }
ParsedStatement *Parser::ParseBlock(const vector<TokenKind>& endTokens, const vector<const ParsedStatement*>& openStatements) { ParsedStatement *
Parser::ParseBlock(const vector<TokenKind> &endTokens, const vector<const ParsedStatement *> &openStatements) {
auto statements = openStatements; auto statements = openStatements;
auto start = this->_position; auto start = this->_position;
while (this->_position < this->_tokens.size()) { while (this->_position < this->_tokens.size()) {
@ -97,7 +107,8 @@ ParsedStatement *Parser::ParseBlock(const vector<TokenKind>& endTokens, const ve
break; break;
} }
if (nextKind == TokenKind::EndOfFile) { if (nextKind == TokenKind::EndOfFile) {
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, next->GetStartPosition(), next->GetLength()); this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, next->GetStartPosition(),
next->GetLength());
break; break;
} }
statements.push_back(this->ParseStatement(next)); statements.push_back(this->ParseStatement(next));
@ -114,11 +125,14 @@ ParsedStatement *Parser::ParseFunctionDeclaration(const IToken *current) {
vector<TypedVariableIdentifier *> parameters; vector<TypedVariableIdentifier *> parameters;
bool hasErrors = false; bool hasErrors = false;
if (functionIdentifierToken->GetKind() != TokenKind::Identifier) { if (functionIdentifierToken->GetKind() != TokenKind::Identifier) {
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, functionIdentifierToken->GetStartPosition(), functionIdentifierToken->GetLength()); this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken,
functionIdentifierToken->GetStartPosition(),
functionIdentifierToken->GetLength());
hasErrors = true; hasErrors = true;
} }
if (openParenthesis->GetKind() != TokenKind::OpenParenthesis && !hasErrors) { if (openParenthesis->GetKind() != TokenKind::OpenParenthesis && !hasErrors) {
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, openParenthesis->GetStartPosition(), openParenthesis->GetLength()); this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken,
openParenthesis->GetStartPosition(), openParenthesis->GetLength());
hasErrors = true; hasErrors = true;
} }
@ -130,18 +144,21 @@ ParsedStatement *Parser::ParseFunctionDeclaration(const IToken *current) {
auto identifier = this->Next(); auto identifier = this->Next();
auto next = this->Next(); auto next = this->Next();
if (type->GetKind() != TokenKind::Identifier && !hasErrors) { if (type->GetKind() != TokenKind::Identifier && !hasErrors) {
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, type->GetStartPosition(), type->GetLength()); this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, type->GetStartPosition(),
type->GetLength());
hasErrors = true; hasErrors = true;
continue; continue;
} }
if (identifier->GetKind() != TokenKind::Identifier && !hasErrors) { if (identifier->GetKind() != TokenKind::Identifier && !hasErrors) {
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(), identifier->GetLength()); this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(),
identifier->GetLength());
hasErrors = true; hasErrors = true;
continue; continue;
} }
if (type->GetKind() != TokenKind::Identifier || identifier->GetKind() != TokenKind::Identifier) { if (type->GetKind() != TokenKind::Identifier || identifier->GetKind() != TokenKind::Identifier) {
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, type->GetStartPosition(), type->GetLength()); this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, type->GetStartPosition(),
type->GetLength());
hasErrors = true; hasErrors = true;
continue; continue;
} }
@ -153,7 +170,8 @@ ParsedStatement *Parser::ParseFunctionDeclaration(const IToken *current) {
if (nextKind == TokenKind::CloseParenthesis || nextKind == TokenKind::EndOfFile) { if (nextKind == TokenKind::CloseParenthesis || nextKind == TokenKind::EndOfFile) {
break; break;
} else if (nextKind != TokenKind::CommaToken && !hasErrors) { } else if (nextKind != TokenKind::CommaToken && !hasErrors) {
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, next->GetStartPosition(), next->GetLength()); this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, next->GetStartPosition(),
next->GetLength());
hasErrors = true; hasErrors = true;
} }
} }
@ -167,7 +185,9 @@ ParsedStatement *Parser::ParseFunctionDeclaration(const IToken *current) {
return new ParsedBadStatement(start, block->GetEndPosition() - start); return new ParsedBadStatement(start, block->GetEndPosition() - start);
} }
auto functionIdentifier = ((IdentifierToken *) functionIdentifierToken)->GetValue(); auto functionIdentifier = ((IdentifierToken *) functionIdentifierToken)->GetValue();
return new ParsedFunctionDeclarationStatement(HashedString(functionIdentifier), parameters, (ParsedBlockStatement*)block, start, block->GetEndPosition() - start); return new ParsedFunctionDeclarationStatement(HashedString(functionIdentifier), parameters,
(ParsedBlockStatement *) block, start,
block->GetEndPosition() - start);
} }
ParsedStatement *Parser::ParseReturnStatement(const IToken *current) { ParsedStatement *Parser::ParseReturnStatement(const IToken *current) {
@ -181,7 +201,8 @@ ParsedStatement* Parser::ParseIfStatement(const IToken* current){
auto condition = this->ParseExpression(this->Next()); auto condition = this->ParseExpression(this->Next());
auto next = this->Next(); auto next = this->Next();
if (next->GetKind() != TokenKind::ThenKeyword) { if (next->GetKind() != TokenKind::ThenKeyword) {
this -> ScriptData -> Diagnostics -> LogError(DiagnosticCode::UnexpectedToken, next->GetStartPosition(), next->GetLength()); this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, next->GetStartPosition(),
next->GetLength());
return new ParsedBadStatement(next->GetStartPosition(), next->GetLength()); return new ParsedBadStatement(next->GetStartPosition(), next->GetLength());
} }
auto block = this->ParseBlock({TokenKind::EndKeyword, TokenKind::ElseKeyword, TokenKind::ElseIfKeyword}); auto block = this->ParseBlock({TokenKind::EndKeyword, TokenKind::ElseKeyword, TokenKind::ElseIfKeyword});
@ -189,10 +210,12 @@ ParsedStatement* Parser::ParseIfStatement(const IToken* current){
auto start = current->GetStartPosition(); auto start = current->GetStartPosition();
if (closeToken->GetKind() == TokenKind::ElseIfKeyword) { if (closeToken->GetKind() == TokenKind::ElseIfKeyword) {
auto elseIfStatement = this->ParseIfStatement(closeToken); auto elseIfStatement = this->ParseIfStatement(closeToken);
return new ParsedConditionalStatement(condition, block, elseIfStatement, start, elseIfStatement->GetEndPosition() - start); return new ParsedConditionalStatement(condition, block, elseIfStatement, start,
elseIfStatement->GetEndPosition() - start);
} else if (closeToken->GetKind() == TokenKind::ElseKeyword) { } else if (closeToken->GetKind() == TokenKind::ElseKeyword) {
auto elseStatement = this->ParseBlock({TokenKind::EndKeyword}); auto elseStatement = this->ParseBlock({TokenKind::EndKeyword});
return new ParsedConditionalStatement(condition, block, elseStatement, start, elseStatement->GetEndPosition() - start); return new ParsedConditionalStatement(condition, block, elseStatement, start,
elseStatement->GetEndPosition() - start);
} }
return new ParsedConditionalStatement(condition, block, start, block->GetEndPosition() - start); return new ParsedConditionalStatement(condition, block, start, block->GetEndPosition() - start);
} }
@ -230,9 +253,12 @@ OperatorPrecedence GetUnaryPrecedence(TokenKind kind){
UnaryOperatorKind GetUnaryOperatorKind(TokenKind kind) { UnaryOperatorKind GetUnaryOperatorKind(TokenKind kind) {
switch (kind) { switch (kind) {
case TokenKind::PlusToken: return UnaryOperatorKind::Identity; case TokenKind::PlusToken:
case TokenKind::MinusToken: return UnaryOperatorKind::Negation; return UnaryOperatorKind::Identity;
case TokenKind::NotKeyword: return UnaryOperatorKind::LogicalNegation; case TokenKind::MinusToken:
return UnaryOperatorKind::Negation;
case TokenKind::NotKeyword:
return UnaryOperatorKind::LogicalNegation;
default: // This should never trigger, so throw. default: // This should never trigger, so throw.
throw; throw;
} }
@ -241,22 +267,34 @@ UnaryOperatorKind GetUnaryOperatorKind(TokenKind kind){
BinaryOperatorKind GetBinaryOperatorKind(TokenKind kind) { BinaryOperatorKind GetBinaryOperatorKind(TokenKind kind) {
switch (kind) { switch (kind) {
// Math operators // Math operators
case TokenKind::PlusToken: return BinaryOperatorKind ::Addition; case TokenKind::PlusToken:
case TokenKind::MinusToken: return BinaryOperatorKind ::Subtraction; return BinaryOperatorKind::Addition;
case TokenKind::StarToken: return BinaryOperatorKind ::Multiplication; case TokenKind::MinusToken:
case TokenKind::SlashToken: return BinaryOperatorKind ::Division; return BinaryOperatorKind::Subtraction;
case TokenKind::StarToken:
return BinaryOperatorKind::Multiplication;
case TokenKind::SlashToken:
return BinaryOperatorKind::Division;
// Equality operators // Equality operators
case TokenKind::EqualityToken: return BinaryOperatorKind ::Equality; case TokenKind::EqualityToken:
case TokenKind::InequalityToken: return BinaryOperatorKind ::Inequality; return BinaryOperatorKind::Equality;
case TokenKind ::Less: return BinaryOperatorKind ::Less; case TokenKind::InequalityToken:
case TokenKind ::LessEquals: return BinaryOperatorKind ::LessOrEquals; return BinaryOperatorKind::Inequality;
case TokenKind ::Greater: return BinaryOperatorKind ::Greater; case TokenKind::Less:
case TokenKind ::GreaterEquals: return BinaryOperatorKind ::GreaterOrEquals; return BinaryOperatorKind::Less;
case TokenKind::LessEquals:
return BinaryOperatorKind::LessOrEquals;
case TokenKind::Greater:
return BinaryOperatorKind::Greater;
case TokenKind::GreaterEquals:
return BinaryOperatorKind::GreaterOrEquals;
// logical operators // logical operators
case TokenKind::AndKeyword: return BinaryOperatorKind ::LogicalAnd; case TokenKind::AndKeyword:
case TokenKind::OrKeyword: return BinaryOperatorKind ::LogicalOr; return BinaryOperatorKind::LogicalAnd;
case TokenKind::OrKeyword:
return BinaryOperatorKind::LogicalOr;
default: // This should never trigger, so throw. default: // This should never trigger, so throw.
throw; throw;
} }
@ -265,22 +303,34 @@ BinaryOperatorKind GetBinaryOperatorKind(TokenKind kind){
OperatorPrecedence GetBinaryPrecedence(TokenKind kind) { OperatorPrecedence GetBinaryPrecedence(TokenKind kind) {
switch (kind) { switch (kind) {
// Math // Math
case TokenKind::PlusToken: return OperatorPrecedence ::Additive; case TokenKind::PlusToken:
case TokenKind::MinusToken: return OperatorPrecedence ::Additive; return OperatorPrecedence::Additive;
case TokenKind::StarToken: return OperatorPrecedence ::Multiplication; case TokenKind::MinusToken:
case TokenKind::SlashToken: return OperatorPrecedence ::Multiplication; return OperatorPrecedence::Additive;
case TokenKind::StarToken:
return OperatorPrecedence::Multiplication;
case TokenKind::SlashToken:
return OperatorPrecedence::Multiplication;
// Equality // Equality
case TokenKind::EqualityToken: return OperatorPrecedence ::Equality; case TokenKind::EqualityToken:
case TokenKind::InequalityToken: return OperatorPrecedence ::Equality; return OperatorPrecedence::Equality;
case TokenKind ::Less: return OperatorPrecedence ::Equality; case TokenKind::InequalityToken:
case TokenKind ::LessEquals: return OperatorPrecedence ::Equality; return OperatorPrecedence::Equality;
case TokenKind ::Greater: return OperatorPrecedence ::Equality; case TokenKind::Less:
case TokenKind ::GreaterEquals: return OperatorPrecedence ::Equality; return OperatorPrecedence::Equality;
case TokenKind::LessEquals:
return OperatorPrecedence::Equality;
case TokenKind::Greater:
return OperatorPrecedence::Equality;
case TokenKind::GreaterEquals:
return OperatorPrecedence::Equality;
// Logical // Logical
case TokenKind::AndKeyword: return OperatorPrecedence ::LogicalAnd; case TokenKind::AndKeyword:
case TokenKind::OrKeyword: return OperatorPrecedence ::LogicalOr; return OperatorPrecedence::LogicalAnd;
case TokenKind::OrKeyword:
return OperatorPrecedence::LogicalOr;
default: default:
return OperatorPrecedence::No; return OperatorPrecedence::No;
} }
@ -315,18 +365,28 @@ ParsedExpression* Parser::ParseBinaryExpression(const IToken* current, OperatorP
ParsedExpression *Parser::ParsePrimaryExpression(const IToken *current) { ParsedExpression *Parser::ParsePrimaryExpression(const IToken *current) {
switch (current->GetKind()) { switch (current->GetKind()) {
case TokenKind ::Integer: return new LiteralIntegerExpression((IntegerToken*)current); case TokenKind::Integer:
case TokenKind ::Float: return new LiteralFloatExpression((FloatToken*)current); return new LiteralIntegerExpression((IntegerToken *) current);
case TokenKind ::String: return new LiteralStringExpression((StringToken*)current); case TokenKind::Float:
case TokenKind ::TrueKeyword: return new LiteralBoolExpression(current); return new LiteralFloatExpression((FloatToken *) current);
case TokenKind ::FalseKeyword: return new LiteralBoolExpression(current); case TokenKind::String:
case TokenKind ::Identifier: return new VariableExpression((IdentifierToken*)current); return new LiteralStringExpression((StringToken *) current);
case TokenKind ::OpenParenthesis: return this -> ParseParenthesizedExpression(current); case TokenKind::TrueKeyword:
case TokenKind ::OpenCurlyBracket: return this -> ParseTableExpression(current); 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. // 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()); case TokenKind::BadToken:
return new BadExpression(current->GetStartPosition(), current->GetLength());
default: default:
this -> ScriptData -> Diagnostics -> LogError(DiagnosticCode::UnexpectedToken, current->GetStartPosition(), current->GetLength()); this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, current->GetStartPosition(),
current->GetLength());
return new BadExpression(current->GetStartPosition(), current->GetLength()); return new BadExpression(current->GetStartPosition(), current->GetLength());
} }
} }
@ -336,7 +396,8 @@ ParsedExpression *Parser::ParseParenthesizedExpression(const IToken *current) {
auto expression = this->ParseExpression(next); auto expression = this->ParseExpression(next);
auto closeToken = this->Next(); auto closeToken = this->Next();
if (closeToken->GetKind() != TokenKind::CloseParenthesis) { if (closeToken->GetKind() != TokenKind::CloseParenthesis) {
this -> ScriptData -> Diagnostics -> LogError(DiagnosticCode::UnexpectedToken, closeToken->GetStartPosition(), closeToken->GetLength()); this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, closeToken->GetStartPosition(),
closeToken->GetLength());
return new BadExpression(closeToken->GetStartPosition(), closeToken->GetLength()); return new BadExpression(closeToken->GetStartPosition(), closeToken->GetLength());
} }
auto start = current->GetStartPosition(); auto start = current->GetStartPosition();
@ -353,14 +414,16 @@ ParsedExpression *Parser::ParseFunctionCallExpression(ParsedExpression* function
} else { } else {
while (peekedKind != TokenKind::CloseParenthesis) { while (peekedKind != TokenKind::CloseParenthesis) {
if (peekedKind == TokenKind::EndOfFile) { if (peekedKind == TokenKind::EndOfFile) {
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, peeked->GetStartPosition(), peeked->GetLength()); this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, peeked->GetStartPosition(),
peeked->GetLength());
return new BadExpression(peeked->GetStartPosition(), peeked->GetLength()); return new BadExpression(peeked->GetStartPosition(), peeked->GetLength());
} }
parameters.push_back(this->ParseExpression(this->Next())); parameters.push_back(this->ParseExpression(this->Next()));
peeked = this->Next(); peeked = this->Next();
peekedKind = peeked->GetKind(); peekedKind = peeked->GetKind();
if (peekedKind != TokenKind::CloseParenthesis && peekedKind != TokenKind::CommaToken) { if (peekedKind != TokenKind::CloseParenthesis && peekedKind != TokenKind::CommaToken) {
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, peeked->GetStartPosition(), peeked->GetLength()); this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, peeked->GetStartPosition(),
peeked->GetLength());
return new BadExpression(peeked->GetStartPosition(), peeked->GetLength()); return new BadExpression(peeked->GetStartPosition(), peeked->GetLength());
} }
} }
@ -374,7 +437,8 @@ ParsedExpression* Parser::ParseIndexExpression(ParsedExpression* indexingExpress
auto indexExpression = this->ParseExpression(this->Next()); auto indexExpression = this->ParseExpression(this->Next());
auto closeBracket = this->Next(); auto closeBracket = this->Next();
if (closeBracket->GetKind() != TokenKind::CloseSquareBracket) { if (closeBracket->GetKind() != TokenKind::CloseSquareBracket) {
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, closeBracket->GetStartPosition(), closeBracket->GetLength()); this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, closeBracket->GetStartPosition(),
closeBracket->GetLength());
return new BadExpression(closeBracket->GetStartPosition(), closeBracket->GetLength()); return new BadExpression(closeBracket->GetStartPosition(), closeBracket->GetLength());
} }
auto start = indexingExpression->GetStartPosition(); auto start = indexingExpression->GetStartPosition();
@ -385,11 +449,14 @@ ParsedExpression* Parser::ParsePeriodIndexExpression(ParsedExpression* indexingE
this->Next(); // consume '.' token this->Next(); // consume '.' token
auto identifier = this->Next(); auto identifier = this->Next();
if (identifier->GetKind() != TokenKind::Identifier) { if (identifier->GetKind() != TokenKind::Identifier) {
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(), identifier->GetLength()); this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(),
return new BadExpression(indexingExpression->GetStartPosition(), identifier->GetEndPosition() - indexingExpression->GetStartPosition()); identifier->GetLength());
return new BadExpression(indexingExpression->GetStartPosition(),
identifier->GetEndPosition() - indexingExpression->GetStartPosition());
} }
auto start = indexingExpression->GetStartPosition(); auto start = indexingExpression->GetStartPosition();
return new PeriodIndexExpression(indexingExpression, ((IdentifierToken*)identifier)->GetValue(), start, identifier->GetEndPosition() - start); return new PeriodIndexExpression(indexingExpression, ((IdentifierToken *) identifier)->GetValue(), start,
identifier->GetEndPosition() - start);
} }
@ -412,8 +479,10 @@ ParsedExpression* Parser::ParseTableExpression(const IToken* current){
auto expression = this->ParseExpression(this->Next()); auto expression = this->ParseExpression(this->Next());
expressions.push_back(expression); expressions.push_back(expression);
n = this->Next(); n = this->Next();
if (n->GetKind() != TokenKind::CommaToken && n->GetKind() != TokenKind ::CloseCurlyBracket && !hasErrors){ if (n->GetKind() != TokenKind::CommaToken && n->GetKind() != TokenKind::CloseCurlyBracket &&
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, n->GetStartPosition(), n->GetLength()); !hasErrors) {
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, n->GetStartPosition(),
n->GetLength());
hasErrors = true; hasErrors = true;
} }
} }
@ -430,3 +499,4 @@ ParsedExpression* Parser::ParseTableExpression(const IToken* current){
} }
} }
}

View File

@ -7,6 +7,7 @@
#include "ParsedStatements/ParsedStatement.hpp" #include "ParsedStatements/ParsedStatement.hpp"
#include "../Script.hpp" #include "../Script.hpp"
namespace Porygon::Parser {
enum class OperatorPrecedence { enum class OperatorPrecedence {
No, No,
LogicalOr, LogicalOr,
@ -20,38 +21,55 @@ enum class OperatorPrecedence {
class Parser { class Parser {
vector<const IToken *> _tokens; vector<const IToken *> _tokens;
unsigned int _position; unsigned int _position;
Script* ScriptData; Porygon::Script *ScriptData;
const IToken *Peek(); const IToken *Peek();
const IToken *PeekAt(int offset); const IToken *PeekAt(int offset);
const IToken *Next(); const IToken *Next();
ParsedStatement *ParseStatement(const IToken *current); ParsedStatement *ParseStatement(const IToken *current);
ParsedStatement *ParseVariableAssignment(const IToken *current); ParsedStatement *ParseVariableAssignment(const IToken *current);
ParsedStatement *ParseIndexAssignment(ParsedExpression *indexer); ParsedStatement *ParseIndexAssignment(ParsedExpression *indexer);
ParsedStatement *ParseBlock(const vector<TokenKind>& endTokens, const vector<const ParsedStatement*>& openStatements = {});
ParsedStatement *
ParseBlock(const vector<TokenKind> &endTokens, const vector<const ParsedStatement *> &openStatements = {});
ParsedStatement *ParseFunctionDeclaration(const IToken *current); ParsedStatement *ParseFunctionDeclaration(const IToken *current);
ParsedStatement *ParseReturnStatement(const IToken *current); ParsedStatement *ParseReturnStatement(const IToken *current);
ParsedStatement *ParseIfStatement(const IToken *current); ParsedStatement *ParseIfStatement(const IToken *current);
ParsedExpression *ParseExpression(const IToken *current); ParsedExpression *ParseExpression(const IToken *current);
ParsedExpression *ParseBinaryExpression(const IToken *current, OperatorPrecedence parentPrecedence); ParsedExpression *ParseBinaryExpression(const IToken *current, OperatorPrecedence parentPrecedence);
ParsedExpression *ParsePrimaryExpression(const IToken *current); ParsedExpression *ParsePrimaryExpression(const IToken *current);
ParsedExpression *ParseParenthesizedExpression(const IToken *current); ParsedExpression *ParseParenthesizedExpression(const IToken *current);
ParsedExpression *ParseFunctionCallExpression(ParsedExpression *functionExpression); ParsedExpression *ParseFunctionCallExpression(ParsedExpression *functionExpression);
ParsedExpression *ParseIndexExpression(ParsedExpression *indexingExpression); ParsedExpression *ParseIndexExpression(ParsedExpression *indexingExpression);
ParsedExpression *ParsePeriodIndexExpression(ParsedExpression *indexingExpression); ParsedExpression *ParsePeriodIndexExpression(ParsedExpression *indexingExpression);
ParsedExpression *ParseTableExpression(const IToken *current); ParsedExpression *ParseTableExpression(const IToken *current);
public: public:
ParsedScriptStatement *Parse(); ParsedScriptStatement *Parse();
explicit Parser(const vector<const IToken*>& tokens, Script* scriptData){
explicit Parser(const vector<const IToken *> &tokens, Porygon::Script *scriptData) {
_tokens = tokens; _tokens = tokens;
_position = 0; _position = 0;
ScriptData = scriptData; ScriptData = scriptData;
} }
}; };
}
#endif //PORYGONLANG_PARSER_HPP #endif //PORYGONLANG_PARSER_HPP

View File

@ -10,7 +10,9 @@
#include "../Utilities/HashedString.hpp" #include "../Utilities/HashedString.hpp"
using namespace std; using namespace std;
using namespace Porygon::Utilities;
namespace Porygon::Parser {
class IToken { class IToken {
const unsigned int _position; const unsigned int _position;
const unsigned int _length; const unsigned int _length;
@ -18,8 +20,7 @@ public:
virtual const TokenKind GetKind() const = 0; virtual const TokenKind GetKind() const = 0;
IToken(unsigned int position, unsigned int length) IToken(unsigned int position, unsigned int length)
: _position(position), _length(length) : _position(position), _length(length) {
{
} }
const unsigned int GetStartPosition() const { const unsigned int GetStartPosition() const {
@ -43,8 +44,7 @@ public:
explicit SimpleToken(TokenKind kind, unsigned int position, unsigned int length) explicit SimpleToken(TokenKind kind, unsigned int position, unsigned int length)
: IToken(position, length), : IToken(position, length),
_kind(kind) _kind(kind) {
{
} }
const TokenKind GetKind() const final { const TokenKind GetKind() const final {
@ -58,8 +58,7 @@ public:
explicit IntegerToken(long value, unsigned int position, unsigned int length) explicit IntegerToken(long value, unsigned int position, unsigned int length)
: IToken(position, length), : IToken(position, length),
_value(value) _value(value) {
{
} }
const TokenKind GetKind() const final { const TokenKind GetKind() const final {
@ -77,8 +76,7 @@ public:
explicit FloatToken(double value, unsigned int position, unsigned int length) explicit FloatToken(double value, unsigned int position, unsigned int length)
: IToken(position, length), : IToken(position, length),
_value(value) _value(value) {
{
} }
const TokenKind GetKind() const final { const TokenKind GetKind() const final {
@ -96,8 +94,7 @@ public:
explicit StringToken(u16string value, unsigned int position, unsigned int length) explicit StringToken(u16string value, unsigned int position, unsigned int length)
: IToken(position, length), : IToken(position, length),
_value(std::move(value)) _value(std::move(value)) {
{
} }
const TokenKind GetKind() const final { const TokenKind GetKind() const final {
@ -110,13 +107,12 @@ public:
}; };
class IdentifierToken : public IToken { class IdentifierToken : public IToken {
const HashedString _value; const Utilities::HashedString _value;
public: public:
explicit IdentifierToken(const HashedString value, unsigned int position, unsigned int length) explicit IdentifierToken(const HashedString value, unsigned int position, unsigned int length)
: IToken(position, length), : IToken(position, length),
_value(value) _value(value) {
{
} }
const TokenKind GetKind() const final { const TokenKind GetKind() const final {
@ -127,5 +123,6 @@ public:
return _value; return _value;
} }
}; };
}
#endif //PORYGONLANG_TOKEN_HPP #endif //PORYGONLANG_TOKEN_HPP

View File

@ -1,6 +1,7 @@
#ifndef PORYGONLANG_TOKENKIND_HPP #ifndef PORYGONLANG_TOKENKIND_HPP
#define PORYGONLANG_TOKENKIND_HPP #define PORYGONLANG_TOKENKIND_HPP
namespace Porygon::Parser {
enum class TokenKind { enum class TokenKind {
EndOfFile, EndOfFile,
BadToken, BadToken,
@ -54,6 +55,6 @@ enum class TokenKind{
TrueKeyword, TrueKeyword,
WhileKeyword, WhileKeyword,
}; };
}
#endif //PORYGONLANG_TOKENKIND_HPP #endif //PORYGONLANG_TOKENKIND_HPP

View File

@ -4,13 +4,13 @@
#include "../Utilities/HashedString.hpp" #include "../Utilities/HashedString.hpp"
namespace Porygon::Parser {
class TypedVariableIdentifier { class TypedVariableIdentifier {
HashedString _type; HashedString _type;
HashedString _identifier; HashedString _identifier;
public: public:
TypedVariableIdentifier(HashedString type, HashedString identifier) TypedVariableIdentifier(HashedString type, HashedString identifier)
: _type(type), _identifier(identifier) : _type(type), _identifier(identifier) {
{
} }
HashedString GetType() { HashedString GetType() {
@ -21,5 +21,6 @@ public:
return _identifier; return _identifier;
} }
}; };
}
#endif //PORYGONLANG_TYPEDVARIABLEIDENTIFIER_HPP #endif //PORYGONLANG_TYPEDVARIABLEIDENTIFIER_HPP

View File

@ -2,9 +2,11 @@
#ifndef PORYGONLANG_UNARYOPERATORKIND_HPP #ifndef PORYGONLANG_UNARYOPERATORKIND_HPP
#define PORYGONLANG_UNARYOPERATORKIND_HPP #define PORYGONLANG_UNARYOPERATORKIND_HPP
namespace Porygon::Parser {
enum class UnaryOperatorKind { enum class UnaryOperatorKind {
Identity, Identity,
Negation, Negation,
LogicalNegation, LogicalNegation,
}; };
}
#endif //PORYGONLANG_UNARYOPERATORKIND_HPP #endif //PORYGONLANG_UNARYOPERATORKIND_HPP

View File

@ -9,7 +9,7 @@
#include "Parser/Parser.hpp" #include "Parser/Parser.hpp"
#include "Binder/Binder.hpp" #include "Binder/Binder.hpp"
Script* Script::Create(const u16string& script) { Porygon::Script* Porygon::Script::Create(const u16string& script) {
auto s = new Script(); auto s = new Script();
s -> Parse(script); s -> Parse(script);
return s; return s;
@ -20,22 +20,22 @@ std::u16string To_UTF16(const string &s)
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> conv; std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> conv;
return conv.from_bytes(s); 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)); return Script::Create(To_UTF16(script));
} }
Script::Script() { Porygon::Script::Script() {
Diagnostics = new DiagnosticsHolder(); Diagnostics = new DiagnosticsHolder();
_evaluator = new Evaluator(this);
_boundScript = nullptr; _boundScript = nullptr;
_scriptVariables = new unordered_map<uint32_t, shared_ptr<EvalValue>>(0); _scriptVariables = new unordered_map<uint32_t, shared_ptr<EvalValue>>(0);
_evaluator = new Evaluator(this -> _scriptVariables);
} }
EvalValue* Script::Evaluate() { EvalValue* Porygon::Script::Evaluate() {
return _evaluator->Evaluate(_boundScript); return _evaluator->Evaluate(_boundScript);
} }
Script::~Script() { Porygon::Script::~Script() {
delete this -> Diagnostics; delete this -> Diagnostics;
delete this -> _boundScript; delete this -> _boundScript;
delete this -> _evaluator; delete this -> _evaluator;
@ -43,10 +43,10 @@ Script::~Script() {
delete this->_scriptVariables; delete this->_scriptVariables;
} }
void Script::Parse(const u16string& script) { void Porygon::Script::Parse(const u16string& script) {
auto lexer = Lexer(script, this); auto lexer = Lexer(script, this);
auto lexResult = lexer.Lex(); auto lexResult = lexer.Lex();
auto parser = Parser(lexResult, this); auto parser = Parser::Parser(lexResult, this);
auto parseResult = parser.Parse(); auto parseResult = parser.Parse();
for (auto token : lexResult){ for (auto token : lexResult){
delete token; delete token;
@ -55,7 +55,7 @@ void Script::Parse(const u16string& script) {
if (!Diagnostics->HasErrors()){ if (!Diagnostics->HasErrors()){
unordered_map<uint32_t, BoundVariable*> scriptScope; unordered_map<uint32_t, BoundVariable*> scriptScope;
auto bindScope = new BoundScope(&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){ for (const auto& v : scriptScope){
this->_scriptVariables -> insert({v.first, nullptr}); this->_scriptVariables -> insert({v.first, nullptr});
delete v.second; delete v.second;
@ -65,59 +65,57 @@ void Script::Parse(const u16string& script) {
delete parseResult; delete parseResult;
} }
EvalValue *Script::GetVariable(const u16string &key) { EvalValue *Porygon::Script::GetVariable(const u16string &key) {
return _scriptVariables -> at(HashedString(key).GetHash()).get(); 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()); auto f = _scriptVariables->find(HashedString(key).GetHash());
return f != _scriptVariables->end(); return f != _scriptVariables->end();
} }
EvalValue *Script::GetLastValue() { EvalValue *Porygon::Script::GetLastValue() {
return _evaluator->GetLastValue(); return _evaluator->GetLastValue();
} }
bool Script::HasFunction(const u16string &key) { bool Porygon::Script::HasFunction(const u16string &key) {
auto f = _scriptVariables->find(HashedString(key).GetHash()); auto f = _scriptVariables->find(HashedString(key).GetHash());
return f != _scriptVariables->end() && f.operator->()->second->GetTypeClass() == TypeClass ::Function; return f != _scriptVariables->end() && f.operator->()->second->GetTypeClass() == TypeClass ::Function;
} }
shared_ptr<EvalValue> Script::CallFunction(const u16string &key, const vector<EvalValue *>& variables) { shared_ptr<EvalValue> Porygon::Script::CallFunction(const u16string &key, const vector<EvalValue *>& variables) {
auto var = (ScriptFunctionEvalValue*)GetVariable(key); auto var = (ScriptFunctionEvalValue*)GetVariable(key);
return this->_evaluator->EvaluateFunction(var, variables); return this->_evaluator->EvaluateFunction(var, variables);
} }
extern "C" { extern "C" {
Script* CreateScript(char16_t * s){ Porygon::Script* CreateScript(char16_t * s){
return Script::Create(s); return Porygon::Script::Create(s);
} }
void EvaluateScript(Script* script){ void EvaluateScript(Porygon::Script* script){
script->Evaluate(); script->Evaluate();
} }
EvalValue* GetLastValue(Script* script){ EvalValue* GetLastValue(Porygon::Script* script){
return script->GetLastValue(); return script->GetLastValue();
} }
bool HasVariable(Script* script, const char16_t* key){ bool HasVariable(Porygon::Script* script, const char16_t* key){
return script->HasVariable(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); 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); 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<EvalValue*> v(parameters, parameters + parameterCount); std::vector<EvalValue*> v(parameters, parameters + parameterCount);
return script->CallFunction(key, v).get(); return script->CallFunction(key, v).get();
} }
} }

View File

@ -1,3 +1,5 @@
#include <utility>
#ifndef PORYGONLANG_SCRIPT_HPP #ifndef PORYGONLANG_SCRIPT_HPP
#define PORYGONLANG_SCRIPT_HPP #define PORYGONLANG_SCRIPT_HPP
@ -6,20 +8,18 @@
#include <unordered_map> #include <unordered_map>
#include "Diagnostics/DiagnosticsHolder.hpp" #include "Diagnostics/DiagnosticsHolder.hpp"
#include "Binder/BoundStatements/BoundStatement.hpp" #include "Binder/BoundStatements/BoundStatement.hpp"
class Script;
class Evaluator;
#include "Evaluator/Evaluator.hpp" #include "Evaluator/Evaluator.hpp"
#include "Evaluator/EvalValues/EvalValue.hpp" #include "Evaluator/EvalValues/EvalValue.hpp"
#include "Utilities/HashedString.hpp" #include "Utilities/HashedString.hpp"
using namespace std; using namespace std;
using namespace Porygon::Evaluation;
namespace Porygon{
class Script { class Script {
friend class Evaluator;
Evaluator* _evaluator; Evaluator* _evaluator;
unordered_map<uint32_t, shared_ptr<EvalValue>>* _scriptVariables; unordered_map<uint32_t, shared_ptr<EvalValue>>* _scriptVariables;
BoundScriptStatement* _boundScript; Binder::BoundScriptStatement* _boundScript;
shared_ptr<ScriptType> _returnType; shared_ptr<ScriptType> _returnType;
explicit Script(); explicit Script();
@ -36,7 +36,7 @@ public:
} }
void SetReturnType(shared_ptr<ScriptType> t){ void SetReturnType(shared_ptr<ScriptType> t){
_returnType = t; _returnType = std::move(t);
} }
EvalValue* Evaluate(); EvalValue* Evaluate();
@ -50,5 +50,7 @@ public:
bool HasFunction(const u16string& key); bool HasFunction(const u16string& key);
}; };
}
#endif //PORYGONLANG_SCRIPT_HPP #endif //PORYGONLANG_SCRIPT_HPP

View File

@ -1,5 +1,6 @@
#include "Script.hpp" #include "Script.hpp"
namespace Porygon{
const bool ScriptType::CanBeIndexedWith(ScriptType *indexer) const{ const bool ScriptType::CanBeIndexedWith(ScriptType *indexer) const{
// String type is the only simple script type we want to // String type is the only simple script type we want to
return _class == TypeClass::String && indexer->_class == TypeClass::Number && !((NumericScriptType*)indexer)->IsFloat(); return _class == TypeClass::String && indexer->_class == TypeClass::Number && !((NumericScriptType*)indexer)->IsFloat();
@ -13,7 +14,7 @@ const shared_ptr<ScriptType> ScriptType::GetIndexedType(ScriptType *indexer) con
} }
extern "C"{ extern "C"{
ScriptType* CreateScriptType(TypeClass t){ ScriptType* CreateScriptType(Porygon::TypeClass t){
return new ScriptType(t); return new ScriptType(t);
} }
@ -25,3 +26,5 @@ extern "C"{
return new StringScriptType(knownAtBind, hash); return new StringScriptType(knownAtBind, hash);
} }
} }
}

View File

@ -12,6 +12,7 @@
using namespace std; using namespace std;
namespace Porygon{
enum class TypeClass{ enum class TypeClass{
Error, Error,
Nil, Nil,
@ -103,11 +104,11 @@ public:
class FunctionScriptType : public ScriptType{ class FunctionScriptType : public ScriptType{
shared_ptr<ScriptType> _returnType; shared_ptr<ScriptType> _returnType;
vector<shared_ptr<ScriptType>> _parameterTypes; vector<shared_ptr<ScriptType>> _parameterTypes;
vector<shared_ptr<BoundVariableKey>> _parameterKeys; vector<shared_ptr<Binder::BoundVariableKey>> _parameterKeys;
int _scopeIndex; int _scopeIndex;
public: public:
FunctionScriptType(std::shared_ptr<ScriptType> returnType, vector<shared_ptr<ScriptType>> parameterTypes, FunctionScriptType(std::shared_ptr<ScriptType> returnType, vector<shared_ptr<ScriptType>> parameterTypes,
vector<shared_ptr<BoundVariableKey>> parameterKeys, int scopeIndex) vector<shared_ptr<Binder::BoundVariableKey>> parameterKeys, int scopeIndex)
: ScriptType(TypeClass::Function){ : ScriptType(TypeClass::Function){
_returnType = std::move(returnType); _returnType = std::move(returnType);
_parameterTypes = std::move(parameterTypes); _parameterTypes = std::move(parameterTypes);
@ -126,7 +127,7 @@ public:
return _parameterTypes; return _parameterTypes;
} }
const vector<shared_ptr<BoundVariableKey>> GetParameterKeys() const{ const vector<shared_ptr<Binder::BoundVariableKey>> GetParameterKeys() const{
return _parameterKeys; return _parameterKeys;
} }
@ -151,6 +152,7 @@ public:
return _valueType; return _valueType;
} }
}; };
}
#endif //PORYGONLANG_SCRIPTTYPE_HPP #endif //PORYGONLANG_SCRIPTTYPE_HPP

View File

@ -4,6 +4,7 @@
#include <unordered_map> #include <unordered_map>
#include "Binder/BoundVariables/BoundVariable.hpp" #include "Binder/BoundVariables/BoundVariable.hpp"
namespace Porygon{
class TableScriptType : public ScriptType{ class TableScriptType : public ScriptType{
const unordered_map<uint32_t, BoundVariable*>* _values; const unordered_map<uint32_t, BoundVariable*>* _values;
const int _localVariableCount; const int _localVariableCount;
@ -50,6 +51,7 @@ public:
} }
}; };
}
#include "ScriptType.hpp" #include "ScriptType.hpp"

View File

@ -2,6 +2,7 @@
#include "UserData.hpp" #include "UserData.hpp"
#include "UserDataStorage.hpp" #include "UserDataStorage.hpp"
namespace Porygon::UserData {
extern "C" { extern "C" {
void RegisterUserDataType(uint32_t id) { void RegisterUserDataType(uint32_t id) {
auto ud = new UserData({}); auto ud = new UserData({});
@ -18,3 +19,4 @@ extern "C"{
return ud->GetFieldCount(); return ud->GetFieldCount();
} }
} }
}

View File

@ -5,6 +5,7 @@
#include <unordered_map> #include <unordered_map>
#include "UserDataField.hpp" #include "UserDataField.hpp"
namespace Porygon::UserData {
class UserData { class UserData {
std::unordered_map<uint32_t, UserDataField *> _fields; std::unordered_map<uint32_t, UserDataField *> _fields;
public: public:
@ -28,6 +29,7 @@ public:
return _fields.size(); return _fields.size();
} }
}; };
}
#endif //PORYGONLANG_USERDATA_HPP #endif //PORYGONLANG_USERDATA_HPP

View File

@ -1,8 +1,11 @@
#include "UserDataField.hpp" #include "UserDataField.hpp"
namespace Porygon::UserData {
extern "C" { extern "C" {
UserDataField* CreateUserDataField(ScriptType* type, EvalValue* (*getter)(void* obj), void (*setter)(void* obj, EvalValue* val)){ UserDataField *
CreateUserDataField(ScriptType *type, Evaluation::EvalValue *(*getter)(void *obj), void (*setter)(void *obj, Evaluation::EvalValue *val)) {
return new UserDataField(type, getter, setter); return new UserDataField(type, getter, setter);
} }
} }
}

View File

@ -6,12 +6,13 @@
#include "../Evaluator/EvalValues/EvalValue.hpp" #include "../Evaluator/EvalValues/EvalValue.hpp"
#include "../Evaluator/EvalValues/NumericEvalValue.hpp" #include "../Evaluator/EvalValues/NumericEvalValue.hpp"
namespace Porygon::UserData{
class UserDataField { class UserDataField {
shared_ptr<ScriptType> _type; shared_ptr<ScriptType> _type;
EvalValue* (*_get)(void* obj); Evaluation::EvalValue* (*_get)(void* obj);
void (*_set)(void* obj, EvalValue* val); void (*_set)(void* obj, Evaluation::EvalValue* val);
public: public:
UserDataField(ScriptType* type, EvalValue* (*getter)(void* obj), void (*setter)(void* obj, EvalValue* val)){ UserDataField(ScriptType* type, Evaluation::EvalValue* (*getter)(void* obj), void (*setter)(void* obj, Evaluation::EvalValue* val)){
_type = shared_ptr<ScriptType>(type); _type = shared_ptr<ScriptType>(type);
_get = getter; _get = getter;
_set = setter; _set = setter;
@ -25,7 +26,7 @@ public:
return _get != nullptr; return _get != nullptr;
} }
EvalValue* Get(void* obj){ Evaluation::EvalValue* Get(void* obj){
return this ->_get(obj); return this ->_get(obj);
} }
@ -33,10 +34,11 @@ public:
return _set != nullptr; return _set != nullptr;
} }
void Set(void* obj, EvalValue* val){ void Set(void* obj, Evaluation::EvalValue* val){
this->_set(obj, val); this->_set(obj, val);
} }
}; };
}
#endif //PORYGONLANG_USERDATAFIELD_HPP #endif //PORYGONLANG_USERDATAFIELD_HPP

View File

@ -8,12 +8,14 @@
#include "UserData.hpp" #include "UserData.hpp"
#include "UserDataStorage.hpp" #include "UserDataStorage.hpp"
namespace Porygon::UserData {
class UserDataScriptType : public ScriptType { class UserDataScriptType : public ScriptType {
shared_ptr<UserData> _userData; shared_ptr<UserData> _userData;
public: public:
explicit UserDataScriptType(uint32_t id) : ScriptType(TypeClass::UserData) { explicit UserDataScriptType(uint32_t id) : ScriptType(TypeClass::UserData) {
_userData = UserDataStorage::GetUserDataType(id); _userData = UserDataStorage::GetUserDataType(id);
} }
explicit UserDataScriptType(shared_ptr<UserData> ud) : ScriptType(TypeClass::UserData) { explicit UserDataScriptType(shared_ptr<UserData> ud) : ScriptType(TypeClass::UserData) {
_userData = std::move(ud); _userData = std::move(ud);
} }
@ -48,6 +50,7 @@ public:
return _userData->GetField(hash)->GetType(); return _userData->GetField(hash)->GetType();
} }
}; };
}
#endif //PORYGONLANG_USERDATASCRIPTTYPE_HPP #endif //PORYGONLANG_USERDATASCRIPTTYPE_HPP

View File

@ -1,4 +1,6 @@
#include "UserDataStorage.hpp" #include "UserDataStorage.hpp"
namespace Porygon::UserData {
UserDataStorage::_internalDataStorage UserDataStorage::_internal = UserDataStorage::_internalDataStorage(); UserDataStorage::_internalDataStorage UserDataStorage::_internal = UserDataStorage::_internalDataStorage();
}

View File

@ -5,11 +5,13 @@
#include <unordered_map> #include <unordered_map>
#include "UserData.hpp" #include "UserData.hpp"
namespace Porygon::UserData {
class UserDataStorage { class UserDataStorage {
class _internalDataStorage { class _internalDataStorage {
public: public:
std::unordered_map<uint32_t, shared_ptr<UserData>> _userData; std::unordered_map<uint32_t, shared_ptr<UserData>> _userData;
}; };
static _internalDataStorage _internal; static _internalDataStorage _internal;
public: public:
@ -25,6 +27,6 @@ public:
return UserDataStorage::_internal._userData[i]; return UserDataStorage::_internal._userData[i];
} }
}; };
}
#endif //PORYGONLANG_USERDATASTORAGE_HPP #endif //PORYGONLANG_USERDATASTORAGE_HPP

View File

@ -1,8 +1,10 @@
#include "UserDataValue.hpp" #include "UserDataValue.hpp"
namespace Porygon::UserData {
extern "C" { extern "C" {
UserDataValue *CreateUserDataEvalValue(uint32_t typeHash, void *obj) { UserDataValue *CreateUserDataEvalValue(uint32_t typeHash, void *obj) {
return new UserDataValue(typeHash, obj); return new UserDataValue(typeHash, obj);
} }
} }
}

View File

@ -7,19 +7,18 @@
#include "UserData.hpp" #include "UserData.hpp"
#include "UserDataStorage.hpp" #include "UserDataStorage.hpp"
class UserDataValue : public EvalValue{ namespace Porygon::UserData {
class UserDataValue : public Evaluation::EvalValue {
const shared_ptr<UserData> _userData; const shared_ptr<UserData> _userData;
void *_obj; void *_obj;
public: public:
UserDataValue(shared_ptr<UserData> userData, void *obj) UserDataValue(shared_ptr<UserData> userData, void *obj)
: _userData(std::move(userData)) : _userData(std::move(userData)) {
{
_obj = obj; _obj = obj;
} }
UserDataValue(uint32_t userDataId, void *obj) UserDataValue(uint32_t userDataId, void *obj)
: _userData(UserDataStorage::GetUserDataType(userDataId)) : _userData(UserDataStorage::GetUserDataType(userDataId)) {
{
_obj = obj; _obj = obj;
} }
@ -58,6 +57,6 @@ public:
field->Set(_obj, value.get()); field->Set(_obj, value.get());
} }
}; };
}
#endif //PORYGONLANG_USERDATAVALUE_HPP #endif //PORYGONLANG_USERDATAVALUE_HPP

View File

@ -4,6 +4,7 @@
#include <string> #include <string>
namespace Porygon::Utilities{
class HashedString{ class HashedString{
const uint32_t _hash; const uint32_t _hash;
public: public:
@ -40,5 +41,6 @@ public:
return _hash != b._hash; return _hash != b._hash;
} }
}; };
}
#endif //PORYGONLANG_HASHEDSTRING_HPP #endif //PORYGONLANG_HASHEDSTRING_HPP

View File

@ -2,6 +2,8 @@
#include <catch.hpp> #include <catch.hpp>
#include "../src/Script.hpp" #include "../src/Script.hpp"
using namespace Porygon;
TEST_CASE( "Basic conditional", "[integration]" ) { TEST_CASE( "Basic conditional", "[integration]" ) {
Script* script = Script::Create("if true then foo = true end"); Script* script = Script::Create("if true then foo = true end");
REQUIRE(!script->Diagnostics -> HasErrors()); REQUIRE(!script->Diagnostics -> HasErrors());

View File

@ -3,6 +3,7 @@
#include <catch.hpp> #include <catch.hpp>
#include "../src/Script.hpp" #include "../src/Script.hpp"
using namespace Porygon;
TEST_CASE( "Diagnostic invalid character", "[integration]" ) { TEST_CASE( "Diagnostic invalid character", "[integration]" ) {
auto script = Script::Create("1 + 1 @"); auto script = Script::Create("1 + 1 @");
REQUIRE(script->Diagnostics -> HasErrors()); REQUIRE(script->Diagnostics -> HasErrors());

View File

@ -3,6 +3,7 @@
#include <catch.hpp> #include <catch.hpp>
#include "../src/Script.hpp" #include "../src/Script.hpp"
using namespace Porygon;
TEST_CASE( "True Equals True", "[integration]" ) { TEST_CASE( "True Equals True", "[integration]" ) {
auto script = Script::Create("true == true"); auto script = Script::Create("true == true");
REQUIRE(!script->Diagnostics -> HasErrors()); REQUIRE(!script->Diagnostics -> HasErrors());

View File

@ -2,6 +2,8 @@
#include <catch.hpp> #include <catch.hpp>
#include "../src/Script.hpp" #include "../src/Script.hpp"
using namespace Porygon;
TEST_CASE( "Define script function", "[integration]" ) { TEST_CASE( "Define script function", "[integration]" ) {
Script* script = Script::Create("function add(number a, number b) a + b end"); Script* script = Script::Create("function add(number a, number b) a + b end");
REQUIRE(!script->Diagnostics -> HasErrors()); REQUIRE(!script->Diagnostics -> HasErrors());

View File

@ -1,6 +1,7 @@
#ifdef TESTS_BUILD #ifdef TESTS_BUILD
#include <catch.hpp> #include <catch.hpp>
#include "../src/Script.hpp" #include "../src/Script.hpp"
using namespace Porygon;
TEST_CASE( "String indexing", "[integration]" ) { TEST_CASE( "String indexing", "[integration]" ) {
auto script = Script::Create("'foobar'[4]"); auto script = Script::Create("'foobar'[4]");

View File

@ -1,6 +1,7 @@
#ifdef TESTS_BUILD #ifdef TESTS_BUILD
#include <catch.hpp> #include <catch.hpp>
#include "../src/Script.hpp" #include "../src/Script.hpp"
using namespace Porygon;
TEST_CASE( "Basic True", "[integration]" ) { TEST_CASE( "Basic True", "[integration]" ) {
auto script = Script::Create("true"); auto script = Script::Create("true");

View File

@ -1,6 +1,7 @@
#ifdef TESTS_BUILD #ifdef TESTS_BUILD
#include <catch.hpp> #include <catch.hpp>
#include "../src/Script.hpp" #include "../src/Script.hpp"
using namespace Porygon;
TEST_CASE( "Integer Negation", "[integration]" ) { TEST_CASE( "Integer Negation", "[integration]" ) {
auto script = Script::Create("-60"); auto script = Script::Create("-60");

View File

@ -3,6 +3,7 @@
#include <catch.hpp> #include <catch.hpp>
#include "../src/Script.hpp" #include "../src/Script.hpp"
using namespace Porygon;
TEST_CASE( "Simple String", "[integration]" ) { TEST_CASE( "Simple String", "[integration]" ) {
auto script = Script::Create("\"foo bar\""); auto script = Script::Create("\"foo bar\"");

View File

@ -2,6 +2,7 @@
#include <catch.hpp> #include <catch.hpp>
#include "../src/Script.hpp" #include "../src/Script.hpp"
#include "../../src/Evaluator/EvalValues/TableEvalValue.hpp" #include "../../src/Evaluator/EvalValues/TableEvalValue.hpp"
using namespace Porygon;
TEST_CASE( "Create empty table", "[integration]" ) { TEST_CASE( "Create empty table", "[integration]" ) {
Script* script = Script::Create("table = {}"); Script* script = Script::Create("table = {}");

View File

@ -5,6 +5,9 @@
#include "../../src/UserData/UserData.hpp" #include "../../src/UserData/UserData.hpp"
#include "../../src/UserData/UserDataStorage.hpp" #include "../../src/UserData/UserDataStorage.hpp"
#include "../../src/UserData/UserDataValue.hpp" #include "../../src/UserData/UserDataValue.hpp"
using namespace Porygon;
using namespace Porygon::UserData;
using namespace Porygon::Utilities;
class UserDataTestObject{ class UserDataTestObject{
public: public:
@ -18,8 +21,8 @@ public:
((UserDataTestObject*)obj)->foo = val->EvaluateInteger(); ((UserDataTestObject*)obj)->foo = val->EvaluateInteger();
} }
static UserData* CreateData(){ static Porygon::UserData::UserData* CreateData(){
return new UserData({ return new Porygon::UserData::UserData({
{ {
HashedString::ConstHash("foo"), HashedString::ConstHash("foo"),
new UserDataField(new NumericScriptType(true, false), GetFoo, SetFoo) new UserDataField(new NumericScriptType(true, false), GetFoo, SetFoo)

View File

@ -1,6 +1,7 @@
#ifdef TESTS_BUILD #ifdef TESTS_BUILD
#include <catch.hpp> #include <catch.hpp>
#include "../src/Script.hpp" #include "../src/Script.hpp"
using namespace Porygon;
TEST_CASE( "Create script variable", "[integration]" ) { TEST_CASE( "Create script variable", "[integration]" ) {
Script* script = Script::Create("foo = true"); Script* script = Script::Create("foo = true");

View File

@ -3,6 +3,7 @@
#include <codecvt> #include <codecvt>
#include <locale> #include <locale>
#include "../../src/Parser/Lexer.hpp" #include "../../src/Parser/Lexer.hpp"
using namespace Porygon::Parser;
TEST_CASE( "When at end of script return terminator", "[lexer]" ) { TEST_CASE( "When at end of script return terminator", "[lexer]" ) {
Lexer lexer = Lexer(u"", nullptr); Lexer lexer = Lexer(u"", nullptr);

View File

@ -3,6 +3,7 @@
#ifdef TESTS_BUILD #ifdef TESTS_BUILD
#include <catch.hpp> #include <catch.hpp>
#include "../../src/Parser/Parser.hpp" #include "../../src/Parser/Parser.hpp"
using namespace Porygon::Parser;
TEST_CASE( "Parse single true keyword", "[parser]" ) { TEST_CASE( "Parse single true keyword", "[parser]" ) {
vector<const IToken*> v {new SimpleToken(TokenKind::TrueKeyword,0,0), new SimpleToken(TokenKind::EndOfFile,0,0)}; vector<const IToken*> v {new SimpleToken(TokenKind::TrueKeyword,0,0), new SimpleToken(TokenKind::EndOfFile,0,0)};