Initial support for require statements
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is failing
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	continuous-integration/drone/push Build is failing
				
			This commit is contained in:
		| @@ -4,6 +4,7 @@ | |||||||
| #include "../ScriptTypes/TableScriptType.hpp" | #include "../ScriptTypes/TableScriptType.hpp" | ||||||
| #include "BoundExpressions/BoundTableExpression.hpp" | #include "BoundExpressions/BoundTableExpression.hpp" | ||||||
| #include "BoundExpressions/BoundFunctionCallExpression.hpp" | #include "BoundExpressions/BoundFunctionCallExpression.hpp" | ||||||
|  | #include "BoundExpressions/BoundRequireExpression.hpp" | ||||||
| #include "../UserData/UserDataScriptType.hpp" | #include "../UserData/UserDataScriptType.hpp" | ||||||
|  |  | ||||||
| using namespace Porygon::Parser; | using namespace Porygon::Parser; | ||||||
| @@ -16,7 +17,7 @@ namespace Porygon::Binder { | |||||||
|         binder._scope = scriptScope; |         binder._scope = scriptScope; | ||||||
|         auto statements = s->GetStatements(); |         auto statements = s->GetStatements(); | ||||||
|         vector<const BoundStatement *> boundStatements(statements->size()); |         vector<const BoundStatement *> boundStatements(statements->size()); | ||||||
|         for (int i = 0; i < statements->size(); i++) { |         for (size_t i = 0; i < statements->size(); i++) { | ||||||
|             boundStatements[i] = binder.BindStatement(statements->at(i)); |             boundStatements[i] = binder.BindStatement(statements->at(i)); | ||||||
|         } |         } | ||||||
|         return new BoundScriptStatement(boundStatements, scriptScope->GetLocalVariableCount()); |         return new BoundScriptStatement(boundStatements, scriptScope->GetLocalVariableCount()); | ||||||
| @@ -63,7 +64,7 @@ namespace Porygon::Binder { | |||||||
|         auto statements = ((ParsedBlockStatement *) statement)->GetStatements(); |         auto statements = ((ParsedBlockStatement *) statement)->GetStatements(); | ||||||
|         vector<const BoundStatement *> boundStatements(statements->size()); |         vector<const BoundStatement *> boundStatements(statements->size()); | ||||||
|         this->_scope->GoInnerScope(); |         this->_scope->GoInnerScope(); | ||||||
|         for (int i = 0; i < statements->size(); i++) { |         for (size_t i = 0; i < statements->size(); i++) { | ||||||
|             boundStatements[i] = this->BindStatement(statements->at(i)); |             boundStatements[i] = this->BindStatement(statements->at(i)); | ||||||
|         } |         } | ||||||
|         this->_scope->GoOuterScope(); |         this->_scope->GoOuterScope(); | ||||||
| @@ -137,7 +138,7 @@ namespace Porygon::Binder { | |||||||
|         auto parameterKeys = vector<shared_ptr<const BoundVariableKey>>(parameters->size()); |         auto parameterKeys = vector<shared_ptr<const BoundVariableKey>>(parameters->size()); | ||||||
|  |  | ||||||
|         this->_scope->GoInnerScope(); |         this->_scope->GoInnerScope(); | ||||||
|         for (long i = 0; i < parameters->size(); i++) { |         for (size_t i = 0; i < parameters->size(); i++) { | ||||||
|             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) { | ||||||
| @@ -567,7 +568,14 @@ namespace Porygon::Binder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     BoundExpression *Binder::BindFunctionCall(const FunctionCallExpression *expression) { |     BoundExpression *Binder::BindFunctionCall(const FunctionCallExpression *expression) { | ||||||
|         auto functionExpression = BindExpression(expression->GetFunction()); |         auto func = expression->GetFunction(); | ||||||
|  |         if (func->GetKind() == ParsedExpressionKind::Variable){ | ||||||
|  |             auto variable = dynamic_cast<const VariableExpression*>(func); | ||||||
|  |             if (variable->GetValue().GetHash() == HashedString::ConstHash("require")){ | ||||||
|  |                 return this->BindRequire(expression); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         auto functionExpression = BindExpression(func); | ||||||
|         auto type = functionExpression->GetType(); |         auto type = functionExpression->GetType(); | ||||||
|         if (type->GetClass() != TypeClass::Function) { |         if (type->GetClass() != TypeClass::Function) { | ||||||
|             this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::ExpressionIsNotAFunction, |             this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::ExpressionIsNotAFunction, | ||||||
| @@ -579,7 +587,7 @@ namespace Porygon::Binder { | |||||||
|         auto givenParameters = expression->GetParameters(); |         auto givenParameters = expression->GetParameters(); | ||||||
|         auto givenParameterTypes = vector<shared_ptr<const ScriptType>>(givenParameters->size()); |         auto givenParameterTypes = vector<shared_ptr<const ScriptType>>(givenParameters->size()); | ||||||
|         vector<BoundExpression *> boundParameters = vector<BoundExpression *>(givenParameters->size()); |         vector<BoundExpression *> boundParameters = vector<BoundExpression *>(givenParameters->size()); | ||||||
|         for (long i = 0; i < givenParameters->size(); i++){ |         for (size_t i = 0; i < givenParameters->size(); i++){ | ||||||
|             boundParameters[i] = this -> BindExpression(givenParameters->at(i)); |             boundParameters[i] = this -> BindExpression(givenParameters->at(i)); | ||||||
|             givenParameterTypes[i] = boundParameters[i]->GetType(); |             givenParameterTypes[i] = boundParameters[i]->GetType(); | ||||||
|         } |         } | ||||||
| @@ -596,6 +604,44 @@ namespace Porygon::Binder { | |||||||
|                                                expression->GetStartPosition(), expression->GetLength()); |                                                expression->GetStartPosition(), expression->GetLength()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     BoundExpression *Binder::BindRequire(const FunctionCallExpression* exp){ | ||||||
|  |         auto parameters = exp->GetParameters(); | ||||||
|  |         if (parameters->size() != 1){ | ||||||
|  |             this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidFunctionParameters, | ||||||
|  |                                                      exp->GetStartPosition(), | ||||||
|  |                                                      exp->GetLength()); | ||||||
|  |             return new BoundBadExpression(exp->GetStartPosition(), exp ->GetLength()); | ||||||
|  |         } | ||||||
|  |         auto parameter = parameters->at(0); | ||||||
|  |         auto boundParameter = this -> BindExpression(parameter); | ||||||
|  |         if (boundParameter->GetKind() != BoundExpressionKind::LiteralString){ | ||||||
|  |             this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidFunctionParameters, | ||||||
|  |                                                      exp->GetStartPosition(), | ||||||
|  |                                                      exp->GetLength()); | ||||||
|  |             return new BoundBadExpression(exp->GetStartPosition(), exp ->GetLength()); | ||||||
|  |         } | ||||||
|  |         auto key = *dynamic_cast<BoundLiteralStringExpression*>(boundParameter)->GetValue(); | ||||||
|  |         auto opt = this->_scriptData->GetScriptOptions(); | ||||||
|  |         auto transformedKey = Utilities::StringUtils::FromUTF8(key); | ||||||
|  |         delete boundParameter; | ||||||
|  |         if (!opt->DoesModuleExist(transformedKey)){ | ||||||
|  |             this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::ModuleDoesntExist, | ||||||
|  |                                                      exp->GetStartPosition(), | ||||||
|  |                                                      exp->GetLength()); | ||||||
|  |             return new BoundBadExpression(exp->GetStartPosition(), exp ->GetLength()); | ||||||
|  |         } | ||||||
|  |         auto module = opt->ResolveModule(transformedKey); | ||||||
|  |         if (module -> GetReturnType() == nullptr){ | ||||||
|  |             for (const auto& v: *module->GetScriptVariables()){ | ||||||
|  |                 //TODO: Currently a hack, will always make all variables nil | ||||||
|  |                 auto type = make_shared<const ScriptType>(TypeClass::Nil); | ||||||
|  |                 this -> _scope -> AssignVariable(v.first, type); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |         return new BoundRequireExpression(module, exp->GetStartPosition(), exp ->GetLength()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     BoundExpression *Binder::BindIndexExpression(const IndexExpression *expression, bool setter) { |     BoundExpression *Binder::BindIndexExpression(const IndexExpression *expression, bool setter) { | ||||||
|         auto indexer = this->BindExpression(expression->GetIndexer()); |         auto indexer = this->BindExpression(expression->GetIndexer()); | ||||||
|         auto index = this->BindExpression(expression->GetIndex()); |         auto index = this->BindExpression(expression->GetIndex()); | ||||||
| @@ -672,7 +718,7 @@ namespace Porygon::Binder { | |||||||
|         if (!boundExpressions.empty()) { |         if (!boundExpressions.empty()) { | ||||||
|             boundExpressions[0] = this->BindExpression(expressions->at(0)); |             boundExpressions[0] = this->BindExpression(expressions->at(0)); | ||||||
|             valueType = boundExpressions[0]->GetType(); |             valueType = boundExpressions[0]->GetType(); | ||||||
|             for (long i = 1; i < expressions->size(); i++) { |             for (size_t 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(Diagnostics::DiagnosticCode::InvalidTableValueType, |                     this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidTableValueType, | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ | |||||||
| #include "BoundVariables/BoundScope.hpp" | #include "BoundVariables/BoundScope.hpp" | ||||||
| #include "../Parser/ParsedExpressions/ParsedTableExpression.hpp" | #include "../Parser/ParsedExpressions/ParsedTableExpression.hpp" | ||||||
| #include "../ScriptTypes/FunctionScriptType.hpp" | #include "../ScriptTypes/FunctionScriptType.hpp" | ||||||
|  | #include "BoundExpressions/BoundFunctionCallExpression.hpp" | ||||||
|  |  | ||||||
| using namespace std; | using namespace std; | ||||||
| using namespace Porygon::Parser; | using namespace Porygon::Parser; | ||||||
| @@ -40,6 +41,7 @@ namespace Porygon::Binder { | |||||||
|         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 *BindRequire(const FunctionCallExpression *exp); | ||||||
|         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); | ||||||
|   | |||||||
| @@ -28,6 +28,7 @@ namespace Porygon::Binder { | |||||||
|         PeriodIndex, |         PeriodIndex, | ||||||
|         NumericalTable, |         NumericalTable, | ||||||
|         Table, |         Table, | ||||||
|  |         Require, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     class BoundExpression { |     class BoundExpression { | ||||||
| @@ -331,6 +332,7 @@ namespace Porygon::Binder { | |||||||
|             return &_expressions; |             return &_expressions; | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif //PORYGONLANG_BOUNDEXPRESSION_HPP | #endif //PORYGONLANG_BOUNDEXPRESSION_HPP | ||||||
|   | |||||||
							
								
								
									
										32
									
								
								src/Binder/BoundExpressions/BoundRequireExpression.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/Binder/BoundExpressions/BoundRequireExpression.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | #ifndef PORYGONLANG_BOUNDREQUIREEXPRESSION_HPP | ||||||
|  | #define PORYGONLANG_BOUNDREQUIREEXPRESSION_HPP | ||||||
|  |  | ||||||
|  | #include "BoundExpression.hpp" | ||||||
|  | #include "../../Script.hpp" | ||||||
|  |  | ||||||
|  | namespace Porygon::Binder { | ||||||
|  |     class BoundRequireExpression : public BoundExpression { | ||||||
|  |         Script* _module; | ||||||
|  |     public: | ||||||
|  |         BoundRequireExpression(Script* script, unsigned int start, | ||||||
|  |                                unsigned int length) | ||||||
|  |                                : BoundExpression(start, length, script->GetReturnType()), | ||||||
|  |                                _module(script){} | ||||||
|  |  | ||||||
|  |         ~BoundRequireExpression() final{ | ||||||
|  |             delete _module; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [[nodiscard]] | ||||||
|  |         inline Script* GetModule() const{ | ||||||
|  |             return _module; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [[nodiscard]] | ||||||
|  |         inline BoundExpressionKind GetKind() const final { | ||||||
|  |             return BoundExpressionKind::Require; | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif //PORYGONLANG_BOUNDREQUIREEXPRESSION_HPP | ||||||
| @@ -26,7 +26,8 @@ namespace Porygon::Diagnostics { | |||||||
|         UserDataFieldNoSetter, |         UserDataFieldNoSetter, | ||||||
|         NumericalForArgumentNotANumber, |         NumericalForArgumentNotANumber, | ||||||
|         CantIterateExpression, |         CantIterateExpression, | ||||||
|         InvalidFunctionParameters |         InvalidFunctionParameters, | ||||||
|  |         ModuleDoesntExist | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| #endif //PORYGONLANG_DIAGNOSTICCODE_HPP | #endif //PORYGONLANG_DIAGNOSTICCODE_HPP | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ | |||||||
| #include "EvalValues/TableEvalValue.hpp" | #include "EvalValues/TableEvalValue.hpp" | ||||||
| #include "../Binder/BoundExpressions/BoundTableExpression.hpp" | #include "../Binder/BoundExpressions/BoundTableExpression.hpp" | ||||||
| #include "../Binder/BoundExpressions/BoundFunctionCallExpression.hpp" | #include "../Binder/BoundExpressions/BoundFunctionCallExpression.hpp" | ||||||
|  | #include "../Binder/BoundExpressions/BoundRequireExpression.hpp" | ||||||
| #include "../ScriptTypes/TableScriptType.hpp" | #include "../ScriptTypes/TableScriptType.hpp" | ||||||
| #include "../UserData/UserDataFunction.hpp" | #include "../UserData/UserDataFunction.hpp" | ||||||
| #include "EvalValues/NumericalTableEvalValue.hpp" | #include "EvalValues/NumericalTableEvalValue.hpp" | ||||||
| @@ -254,6 +255,8 @@ namespace Porygon::Evaluation { | |||||||
|                 return this->EvaluateNumericTableExpression(expression); |                 return this->EvaluateNumericTableExpression(expression); | ||||||
|             case BoundExpressionKind::Table: |             case BoundExpressionKind::Table: | ||||||
|                 return this->EvaluateComplexTableExpression(expression); |                 return this->EvaluateComplexTableExpression(expression); | ||||||
|  |             case BoundExpressionKind::Require: | ||||||
|  |                 return this -> EvaluateRequireExpression(expression); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -396,4 +399,16 @@ namespace Porygon::Evaluation { | |||||||
|         this->_evaluationScope = currentEvaluator; |         this->_evaluationScope = currentEvaluator; | ||||||
|         return new TableEvalValue(variables); |         return new TableEvalValue(variables); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     EvalValuePointer Evaluator::EvaluateRequireExpression(const BoundExpression* expression) { | ||||||
|  |         auto module = dynamic_cast<const BoundRequireExpression*>(expression)->GetModule(); | ||||||
|  |         if (module ->GetReturnType() == nullptr){ | ||||||
|  |             for (const auto& v: *module->GetScriptVariables()){ | ||||||
|  |                 this->_scriptVariables->insert({v.first, v.second.Clone()}); | ||||||
|  |             } | ||||||
|  |             return nullptr; | ||||||
|  |         } else{ | ||||||
|  |             return module -> Evaluate().Take(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| @@ -47,6 +47,8 @@ namespace Porygon::Evaluation{ | |||||||
|         EvalValuePointer EvaluateNumericTableExpression(const BoundExpression *expression); |         EvalValuePointer EvaluateNumericTableExpression(const BoundExpression *expression); | ||||||
|         EvalValuePointer EvaluateComplexTableExpression(const BoundExpression *expression); |         EvalValuePointer EvaluateComplexTableExpression(const BoundExpression *expression); | ||||||
|  |  | ||||||
|  |         EvalValuePointer EvaluateRequireExpression(const BoundExpression* expression); | ||||||
|  |  | ||||||
|         EvalValuePointer GetVariable(const BoundVariableExpression *expression); |         EvalValuePointer GetVariable(const BoundVariableExpression *expression); | ||||||
|     public: |     public: | ||||||
|         explicit Evaluator(map<Utilities::HashedString, EvalValuePointer>* scriptVariables, const ScriptOptions* options) |         explicit Evaluator(map<Utilities::HashedString, EvalValuePointer>* scriptVariables, const ScriptOptions* options) | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ namespace Porygon{ | |||||||
|         Evaluator* _evaluator; |         Evaluator* _evaluator; | ||||||
|         map<Utilities::HashedString, EvalValuePointer>* _scriptVariables; |         map<Utilities::HashedString, EvalValuePointer>* _scriptVariables; | ||||||
|         shared_ptr<Binder::BoundScriptStatement> _boundScript; |         shared_ptr<Binder::BoundScriptStatement> _boundScript; | ||||||
|         shared_ptr<const ScriptType> _returnType; |         shared_ptr<const ScriptType> _returnType = nullptr; | ||||||
|         ScriptOptions* _scriptOptions; |         ScriptOptions* _scriptOptions; | ||||||
|  |  | ||||||
|         explicit Script(const u16string&); |         explicit Script(const u16string&); | ||||||
| @@ -57,6 +57,10 @@ namespace Porygon{ | |||||||
|  |  | ||||||
|         const EvalValue* CallFunction(const u16string& key, const vector<EvalValue*>& variables); |         const EvalValue* CallFunction(const u16string& key, const vector<EvalValue*>& variables); | ||||||
|         bool HasFunction(const u16string& key); |         bool HasFunction(const u16string& key); | ||||||
|  |  | ||||||
|  |         const map<Utilities::HashedString, EvalValuePointer>* GetScriptVariables(){ | ||||||
|  |             return _scriptVariables; | ||||||
|  |         } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,18 +1,30 @@ | |||||||
| #include <iostream> | #include <iostream> | ||||||
|  | #include <filesystem> | ||||||
|  | #include <fstream> | ||||||
| #include "ScriptOptions.hpp" | #include "ScriptOptions.hpp" | ||||||
| #include "Utilities/StringUtils.hpp" | #include "Utilities/StringUtils.hpp" | ||||||
|  | #include "Script.hpp" | ||||||
|  |  | ||||||
| Porygon::ScriptOptions Porygon::ScriptOptions::DefaultScriptOptions; | Porygon::ScriptOptions Porygon::ScriptOptions::DefaultScriptOptions; | ||||||
|  |  | ||||||
| std::streambuf* Porygon::ScriptOptions::_printBuffer = std::cout.rdbuf(); | std::streambuf* Porygon::ScriptOptions::_printBuffer = std::cout.rdbuf(); | ||||||
| std::ostream* Porygon::ScriptOptions::_printStream = new std::ostream(Porygon::ScriptOptions::_printBuffer); | std::ostream* Porygon::ScriptOptions::_printStream = new std::ostream(Porygon::ScriptOptions::_printBuffer); | ||||||
|  |  | ||||||
| static void DefaultPrint(const char16_t* s){ | void Porygon::ScriptOptions::DefaultPrint(const char16_t *s) { | ||||||
|     Porygon::ScriptOptions::GetDefaultScriptOptions()->GetPrintStream() << Porygon::Utilities::StringUtils::FromUTF8(s) << std::endl; |     Porygon::ScriptOptions::GetDefaultScriptOptions()->GetPrintStream() << Porygon::Utilities::StringUtils::FromUTF8(s) << std::endl; | ||||||
| } | } | ||||||
|  |  | ||||||
| void (*Porygon::ScriptOptions::_print)(const char16_t*) = DefaultPrint; | bool Porygon::ScriptOptions::DefaultModuleExists(const std::string& moduleName) { | ||||||
|  |     return std::filesystem::exists(moduleName); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Porygon::Script *Porygon::ScriptOptions::DefaultResolveModule(const std::string& moduleName) { | ||||||
|  |     auto stream = std::ifstream(moduleName); | ||||||
|  |     std::basic_stringstream<char16_t> stringStream; | ||||||
|  |     stringStream << stream.rdbuf(); | ||||||
|  |     auto str = std::u16string(stringStream.str()); | ||||||
|  |     return Porygon::Script::Create(str); | ||||||
|  | } | ||||||
|  |  | ||||||
| extern "C"{ | extern "C"{ | ||||||
|     void SetDefaultPrintFunc(void (*func)(const char16_t*)){ |     void SetDefaultPrintFunc(void (*func)(const char16_t*)){ | ||||||
|   | |||||||
| @@ -2,28 +2,54 @@ | |||||||
| #define PORYGONLANG_SCRIPTOPTIONS_HPP | #define PORYGONLANG_SCRIPTOPTIONS_HPP | ||||||
|  |  | ||||||
| #include <string> | #include <string> | ||||||
|  | #include <utility> | ||||||
| namespace Porygon{ | namespace Porygon{ | ||||||
|  |     class Script; | ||||||
|  |  | ||||||
|     class ScriptOptions{ |     class ScriptOptions{ | ||||||
|         static Porygon::ScriptOptions DefaultScriptOptions; |         static Porygon::ScriptOptions DefaultScriptOptions; | ||||||
|         static void (*_print)(const char16_t* s); |         static void DefaultPrint(const char16_t* s); | ||||||
|  |         static bool DefaultModuleExists(const std::string& moduleName); | ||||||
|  |         static Script* DefaultResolveModule(const std::string& moduleName); | ||||||
|  |  | ||||||
|  |         void (*_print)(const char16_t* s) = DefaultPrint; | ||||||
|  |         bool (*_doesModuleExist)(const std::string& moduleName) = DefaultModuleExists; | ||||||
|  |         Script* (*_resolveModule)(const std::string& moduleName) = DefaultResolveModule; | ||||||
|         static std::streambuf* _printBuffer; |         static std::streambuf* _printBuffer; | ||||||
|         static std::ostream* _printStream; |         static std::ostream* _printStream; | ||||||
|  |  | ||||||
|     public: |     public: | ||||||
|         static Porygon::ScriptOptions* GetDefaultScriptOptions(){ |         static Porygon::ScriptOptions* GetDefaultScriptOptions(){ | ||||||
|             return &DefaultScriptOptions; |             return &DefaultScriptOptions; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|         inline void Print(const char16_t* s) const{ |         inline void Print(const char16_t* s) const{ | ||||||
|             ScriptOptions::_print(s); |             this -> _print(s); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         inline bool DoesModuleExist(std::string moduleName) const{ | ||||||
|  |             return _doesModuleExist(std::move(moduleName)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         inline Script* ResolveModule(std::string moduleName) const{ | ||||||
|  |             return _resolveModule(std::move(moduleName)); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         void SetPrintFunc(void (*print)(const char16_t *)){ |         void SetPrintFunc(void (*print)(const char16_t *)){ | ||||||
|             ScriptOptions::_print = print; |             this -> _print = print; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         void SetModuleExistsFunc(bool (*doesModuleExist)(const std::string& moduleName)){ | ||||||
|  |             this ->_doesModuleExist = doesModuleExist; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         void SetResolveModuleFunc(Script* (*resolveModule)(const std::string& moduleName)){ | ||||||
|  |             this ->_resolveModule = resolveModule; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         std::ostream& GetPrintStream(){ |         std::ostream& GetPrintStream(){ | ||||||
|             return *ScriptOptions::_printStream; |             return *Porygon::ScriptOptions::_printStream; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         void SetPrintStream(std::ostream* stream){ |         void SetPrintStream(std::ostream* stream){ | ||||||
|   | |||||||
							
								
								
									
										45
									
								
								tests/integration/ModuleTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								tests/integration/ModuleTests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | |||||||
|  | #ifdef TESTS_BUILD | ||||||
|  | #include <catch.hpp> | ||||||
|  | #include "../src/Script.hpp" | ||||||
|  | using namespace Porygon; | ||||||
|  |  | ||||||
|  | class ModuleHandler{ | ||||||
|  |     static unordered_map<string, Script*> MODULES; | ||||||
|  |  | ||||||
|  |     ~ModuleHandler(){ | ||||||
|  |         for (auto v: MODULES){ | ||||||
|  |             delete v.second; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline static bool DoesModuleExist(const string& moduleName){ | ||||||
|  |         return MODULES.find(moduleName) != MODULES.end(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline static Script* ResolveModule(const string& moduleName){ | ||||||
|  |         return MODULES[moduleName]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |     static void Initialize(){ | ||||||
|  |         ScriptOptions::GetDefaultScriptOptions()->SetModuleExistsFunc(DoesModuleExist); | ||||||
|  |         ScriptOptions::GetDefaultScriptOptions()->SetResolveModuleFunc(ResolveModule); | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | unordered_map<string, Script*> ModuleHandler::MODULES = unordered_map<string, Script*>{ | ||||||
|  |         {"simple_return", Script::Create(u"return 500")} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | TEST_CASE( "Require simple return script", "[integration]" ) { | ||||||
|  |     ModuleHandler::Initialize(); | ||||||
|  |     auto script = Script::Create(uR"( | ||||||
|  | return require("simple_return") | ||||||
|  | )"); | ||||||
|  |     REQUIRE(!script->Diagnostics -> HasErrors()); | ||||||
|  |     auto var = script->Evaluate(); | ||||||
|  |     REQUIRE(var->EvaluateInteger() == 500); | ||||||
|  |     delete script; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif | ||||||
		Reference in New Issue
	
	Block a user