Implements support for functions with the same name, but different parameters
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
24c560b52d
commit
db2d731b06
|
@ -3,8 +3,9 @@
|
||||||
#include "Binder.hpp"
|
#include "Binder.hpp"
|
||||||
#include "../TableScriptType.hpp"
|
#include "../TableScriptType.hpp"
|
||||||
#include "BoundExpressions/BoundTableExpression.hpp"
|
#include "BoundExpressions/BoundTableExpression.hpp"
|
||||||
|
#include "BoundExpressions/BoundFunctionCallExpression.hpp"
|
||||||
#include "../UserData/UserDataScriptType.hpp"
|
#include "../UserData/UserDataScriptType.hpp"
|
||||||
#include <memory>
|
#include "../FunctionScriptType.hpp"
|
||||||
|
|
||||||
using namespace Porygon::Parser;
|
using namespace Porygon::Parser;
|
||||||
|
|
||||||
|
@ -158,19 +159,38 @@ namespace Porygon::Binder {
|
||||||
|
|
||||||
auto identifier = functionStatement->GetIdentifier();
|
auto identifier = functionStatement->GetIdentifier();
|
||||||
auto returnType = make_shared<ScriptType>(TypeClass::Nil);
|
auto returnType = make_shared<ScriptType>(TypeClass::Nil);
|
||||||
auto type = make_shared<FunctionScriptType>(returnType, parameterTypes, parameterKeys, scopeIndex);
|
auto option = new ScriptFunctionOption(returnType, parameterTypes, parameterKeys);
|
||||||
this->_currentFunction = type;
|
this->_currentFunction = option;
|
||||||
|
|
||||||
|
shared_ptr<GenericFunctionScriptType> type;
|
||||||
|
auto scope = this -> _scope -> Exists(identifier);
|
||||||
|
BoundVariableKey* assignmentKey;
|
||||||
|
if (scope >= 0){
|
||||||
|
auto var = this -> _scope -> GetVariable(scope, identifier);
|
||||||
|
auto varType =var->GetType();
|
||||||
|
if (varType->GetClass() != TypeClass::Function){
|
||||||
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(),
|
||||||
|
statement->GetLength());
|
||||||
|
}
|
||||||
|
type = dynamic_pointer_cast<GenericFunctionScriptType>(varType);
|
||||||
|
type->RegisterFunctionOption(option);
|
||||||
|
assignmentKey = new BoundVariableKey(identifier, scope, false);
|
||||||
|
} else{
|
||||||
|
type = make_shared<GenericFunctionScriptType>();
|
||||||
|
type->RegisterFunctionOption(option);
|
||||||
auto assignment = this->_scope->AssignVariable(identifier, type);
|
auto assignment = this->_scope->AssignVariable(identifier, type);
|
||||||
if (assignment.GetResult() != VariableAssignmentResult::Ok) {
|
if (assignment.GetResult() != VariableAssignmentResult::Ok) {
|
||||||
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(),
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(),
|
||||||
statement->GetLength());
|
statement->GetLength());
|
||||||
return new BoundBadStatement();
|
return new BoundBadStatement();
|
||||||
}
|
}
|
||||||
|
assignmentKey = assignment.GetKey();
|
||||||
|
}
|
||||||
|
|
||||||
auto boundBlock = this->BindBlockStatement(functionStatement->GetBlock());
|
auto boundBlock = this->BindBlockStatement(functionStatement->GetBlock());
|
||||||
this->_scope->GoOuterScope();
|
this->_scope->GoOuterScope();
|
||||||
this->_currentFunction = nullptr;
|
this->_currentFunction = nullptr;
|
||||||
return new BoundFunctionDeclarationStatement(type, assignment.GetKey(), (BoundBlockStatement *) boundBlock);
|
return new BoundFunctionDeclarationStatement(type, assignmentKey, (BoundBlockStatement *) boundBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundStatement *Binder::BindReturnStatement(const ParsedStatement *statement) {
|
BoundStatement *Binder::BindReturnStatement(const ParsedStatement *statement) {
|
||||||
|
@ -558,28 +578,23 @@ namespace Porygon::Binder {
|
||||||
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
|
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
|
||||||
}
|
}
|
||||||
auto functionType = std::dynamic_pointer_cast<GenericFunctionScriptType>(type);
|
auto functionType = std::dynamic_pointer_cast<GenericFunctionScriptType>(type);
|
||||||
auto parameterTypes = functionType->GetParameterTypes();
|
|
||||||
auto givenParameters = expression->GetParameters();
|
auto givenParameters = expression->GetParameters();
|
||||||
if (parameterTypes.size() != givenParameters->size()) {
|
auto givenParameterTypes = vector<shared_ptr<ScriptType>>(givenParameters->size());
|
||||||
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::ParameterCountMismatch,
|
vector<BoundExpression *> boundParameters = vector<BoundExpression *>(givenParameters->size());
|
||||||
|
for (int i = 0; i < givenParameters->size(); i++){
|
||||||
|
boundParameters[i] = this -> BindExpression(givenParameters->at(i));
|
||||||
|
givenParameterTypes[i] = boundParameters[i]->GetType();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto functionOption = functionType->GetFunctionOption(givenParameterTypes);
|
||||||
|
if (functionOption == nullptr){
|
||||||
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidFunctionParameters,
|
||||||
expression->GetStartPosition(),
|
expression->GetStartPosition(),
|
||||||
expression->GetLength());
|
expression->GetLength());
|
||||||
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
|
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
|
||||||
}
|
}
|
||||||
vector<BoundExpression *> boundParameters = vector<BoundExpression *>(givenParameters->size());
|
|
||||||
for (int i = 0; i < givenParameters->size(); i++) {
|
|
||||||
auto parameter = givenParameters->at(i);
|
|
||||||
auto boundParameter = this->BindExpression(parameter);
|
|
||||||
if (boundParameter->GetType().get()->operator!=(parameterTypes.at(i).get())) {
|
|
||||||
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::ParameterTypeMismatch,
|
|
||||||
parameter->GetStartPosition(),
|
|
||||||
parameter->GetLength());
|
|
||||||
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
|
|
||||||
}
|
|
||||||
boundParameters[i] = boundParameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new BoundFunctionCallExpression(functionExpression, boundParameters, functionType.get()->GetReturnType(),
|
return new BoundFunctionCallExpression(functionExpression, boundParameters, functionOption, functionOption->GetReturnType(),
|
||||||
expression->GetStartPosition(), expression->GetLength());
|
expression->GetStartPosition(), expression->GetLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "../Script.hpp"
|
#include "../Script.hpp"
|
||||||
#include "BoundVariables/BoundScope.hpp"
|
#include "BoundVariables/BoundScope.hpp"
|
||||||
#include "../Parser/ParsedExpressions/ParsedTableExpression.hpp"
|
#include "../Parser/ParsedExpressions/ParsedTableExpression.hpp"
|
||||||
|
#include "../FunctionScriptType.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Porygon::Parser;
|
using namespace Porygon::Parser;
|
||||||
|
@ -14,7 +15,7 @@ namespace Porygon::Binder {
|
||||||
class Binder {
|
class Binder {
|
||||||
Porygon::Script *_scriptData;
|
Porygon::Script *_scriptData;
|
||||||
BoundScope *_scope;
|
BoundScope *_scope;
|
||||||
shared_ptr<FunctionScriptType> _currentFunction;
|
GenericFunctionOption* _currentFunction;
|
||||||
|
|
||||||
~Binder();
|
~Binder();
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "../../ScriptType.hpp"
|
#include "../../ScriptType.hpp"
|
||||||
#include "../BoundOperators.hpp"
|
#include "../BoundOperators.hpp"
|
||||||
#include "../BoundVariables/BoundVariableKey.hpp"
|
#include "../BoundVariables/BoundVariableKey.hpp"
|
||||||
|
#include "../../FunctionScriptType.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -227,36 +228,6 @@ namespace Porygon::Binder {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class BoundFunctionCallExpression : public BoundExpression {
|
|
||||||
const BoundExpression *_functionExpression;
|
|
||||||
const vector<BoundExpression *> _parameters;
|
|
||||||
public:
|
|
||||||
BoundFunctionCallExpression(BoundExpression *functionExpression, vector<BoundExpression *> parameters,
|
|
||||||
shared_ptr<ScriptType> result,
|
|
||||||
unsigned int start, unsigned int length)
|
|
||||||
: BoundExpression(start, length, std::move(result)), _functionExpression(functionExpression),
|
|
||||||
_parameters(std::move(parameters)) {}
|
|
||||||
|
|
||||||
~BoundFunctionCallExpression() final {
|
|
||||||
delete _functionExpression;
|
|
||||||
for (auto p : _parameters) {
|
|
||||||
delete p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const BoundExpressionKind GetKind() const final {
|
|
||||||
return BoundExpressionKind::FunctionCall;
|
|
||||||
}
|
|
||||||
|
|
||||||
const BoundExpression *GetFunctionExpression() const {
|
|
||||||
return _functionExpression;
|
|
||||||
}
|
|
||||||
|
|
||||||
const vector<BoundExpression *> *GetParameters() const {
|
|
||||||
return &_parameters;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class BoundIndexExpression : public BoundExpression {
|
class BoundIndexExpression : public BoundExpression {
|
||||||
const BoundExpression *_indexableExpression;
|
const BoundExpression *_indexableExpression;
|
||||||
const BoundExpression *_indexExpression;
|
const BoundExpression *_indexExpression;
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
#include "BoundFunctionCallExpression.hpp"
|
|
@ -0,0 +1,45 @@
|
||||||
|
#ifndef PORYGONLANG_BOUNDFUNCTIONCALLEXPRESSION_HPP
|
||||||
|
#define PORYGONLANG_BOUNDFUNCTIONCALLEXPRESSION_HPP
|
||||||
|
|
||||||
|
#include "BoundExpression.hpp"
|
||||||
|
|
||||||
|
namespace Porygon::Binder {
|
||||||
|
class BoundFunctionCallExpression : public Porygon::Binder::BoundExpression {
|
||||||
|
const BoundExpression *_functionExpression;
|
||||||
|
const vector<BoundExpression *> _parameters;
|
||||||
|
const Porygon::GenericFunctionOption *_option;
|
||||||
|
public:
|
||||||
|
BoundFunctionCallExpression(BoundExpression *functionExpression, vector<BoundExpression *> parameters,
|
||||||
|
Porygon::GenericFunctionOption *option, shared_ptr<Porygon::ScriptType> result,
|
||||||
|
unsigned int start, unsigned int length)
|
||||||
|
: BoundExpression(start, length, move(result)), _functionExpression(functionExpression),
|
||||||
|
_parameters(move(parameters)), _option(option) {}
|
||||||
|
|
||||||
|
~BoundFunctionCallExpression() final {
|
||||||
|
delete _functionExpression;
|
||||||
|
for (auto p : _parameters) {
|
||||||
|
delete p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Porygon::Binder::BoundExpressionKind GetKind() const final {
|
||||||
|
return Porygon::Binder::BoundExpressionKind::FunctionCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BoundExpression *GetFunctionExpression() const {
|
||||||
|
return _functionExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vector<BoundExpression *> *GetParameters() const {
|
||||||
|
return &_parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Porygon::GenericFunctionOption *GetFunctionOption() const {
|
||||||
|
return _option;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "BoundExpression.hpp"
|
||||||
|
|
||||||
|
#endif //PORYGONLANG_BOUNDFUNCTIONCALLEXPRESSION_HPP
|
|
@ -1,19 +1,18 @@
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef PORYGONLANG_BOUNDFUNCTIONDECLARATIONSTATEMENT_HPP
|
#ifndef PORYGONLANG_BOUNDFUNCTIONDECLARATIONSTATEMENT_HPP
|
||||||
#define PORYGONLANG_BOUNDFUNCTIONDECLARATIONSTATEMENT_HPP
|
#define PORYGONLANG_BOUNDFUNCTIONDECLARATIONSTATEMENT_HPP
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "BoundStatement.hpp"
|
#include "BoundStatement.hpp"
|
||||||
|
#include "../../FunctionScriptType.hpp"
|
||||||
|
|
||||||
namespace Porygon::Binder {
|
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<GenericFunctionScriptType> _type;
|
||||||
public:
|
public:
|
||||||
BoundFunctionDeclarationStatement(std::shared_ptr<FunctionScriptType> type, BoundVariableKey *key,
|
BoundFunctionDeclarationStatement(std::shared_ptr<GenericFunctionScriptType> type, BoundVariableKey *key,
|
||||||
BoundBlockStatement *block)
|
BoundBlockStatement *block)
|
||||||
: _key(key), _block(block), _type(std::move(type)) {
|
: _key(key), _block(block), _type(std::move(type)) {
|
||||||
}
|
}
|
||||||
|
@ -34,12 +33,10 @@ namespace Porygon::Binder {
|
||||||
return _block;
|
return _block;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::shared_ptr<FunctionScriptType> GetType() const {
|
const std::shared_ptr<GenericFunctionScriptType> GetType() const {
|
||||||
return _type;
|
return _type;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "BoundStatement.hpp"
|
|
||||||
|
|
||||||
#endif //PORYGONLANG_BOUNDFUNCTIONDECLARATIONSTATEMENT_HPP
|
#endif //PORYGONLANG_BOUNDFUNCTIONDECLARATIONSTATEMENT_HPP
|
||||||
|
|
|
@ -17,8 +17,6 @@ namespace Porygon::Diagnostics {
|
||||||
CantAssignVariable,
|
CantAssignVariable,
|
||||||
VariableNotFound,
|
VariableNotFound,
|
||||||
ExpressionIsNotAFunction,
|
ExpressionIsNotAFunction,
|
||||||
ParameterCountMismatch,
|
|
||||||
ParameterTypeMismatch,
|
|
||||||
CantIndex,
|
CantIndex,
|
||||||
InvalidReturnType,
|
InvalidReturnType,
|
||||||
ConditionNotABool,
|
ConditionNotABool,
|
||||||
|
@ -27,7 +25,8 @@ namespace Porygon::Diagnostics {
|
||||||
UserDataFieldNoGetter,
|
UserDataFieldNoGetter,
|
||||||
UserDataFieldNoSetter,
|
UserDataFieldNoSetter,
|
||||||
NumericalForArgumentNotANumber,
|
NumericalForArgumentNotANumber,
|
||||||
CantIterateExpression
|
CantIterateExpression,
|
||||||
|
InvalidFunctionParameters
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif //PORYGONLANG_DIAGNOSTICCODE_HPP
|
#endif //PORYGONLANG_DIAGNOSTICCODE_HPP
|
||||||
|
|
|
@ -48,16 +48,16 @@ size_t DiagnosticsHolder::GetLineFromPosition(size_t i) {
|
||||||
if (bottomLimit == topLimit){
|
if (bottomLimit == topLimit){
|
||||||
return bottomLimit;
|
return bottomLimit;
|
||||||
}
|
}
|
||||||
size_t half = (topLimit - bottomLimit) / 2;
|
size_t half = bottomLimit + ((topLimit - bottomLimit) / 2);
|
||||||
size_t pos = _lineStarts[half];
|
size_t pos = _lineStarts[half];
|
||||||
size_t length = _lineLength[half];
|
size_t length = _lineLength[half];
|
||||||
if (pos < i && pos + length > i){
|
if (pos < i && pos + length > i){
|
||||||
return half;
|
return half;
|
||||||
}
|
}
|
||||||
if (pos > i){
|
if (pos > i){
|
||||||
bottomLimit = half;
|
|
||||||
} else if (pos < i){
|
|
||||||
topLimit = half;
|
topLimit = half;
|
||||||
|
} else if (pos < i){
|
||||||
|
bottomLimit = half;
|
||||||
} else{
|
} else{
|
||||||
return half;
|
return half;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,24 +4,63 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <unordered_map>
|
||||||
#include "../../ScriptType.hpp"
|
#include "../../ScriptType.hpp"
|
||||||
#include "EvalValue.hpp"
|
#include "EvalValue.hpp"
|
||||||
#include "../../Binder/BoundStatements/BoundStatement.hpp"
|
#include "../../Binder/BoundStatements/BoundStatement.hpp"
|
||||||
#include "../EvaluationScope/EvaluationScope.hpp"
|
#include "../EvaluationScope/EvaluationScope.hpp"
|
||||||
|
#include "../../FunctionScriptType.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace Porygon::Evaluation {
|
namespace Porygon::Evaluation {
|
||||||
|
class GenericFunctionOption{
|
||||||
|
public:
|
||||||
|
virtual ~GenericFunctionOption() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EvaluationScriptFunctionOption : public GenericFunctionOption{
|
||||||
|
const std::shared_ptr<BoundBlockStatement> _innerBlock;
|
||||||
|
const std::shared_ptr<EvaluationScope> _scope;
|
||||||
|
|
||||||
|
public:
|
||||||
|
EvaluationScriptFunctionOption(const shared_ptr<BoundBlockStatement> innerBlock, const shared_ptr<EvaluationScope> scope)
|
||||||
|
: _innerBlock(innerBlock), _scope(scope) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::shared_ptr<BoundBlockStatement> &GetInnerBlock() const {
|
||||||
|
return _innerBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::shared_ptr<EvaluationScope> &GetScope() const {
|
||||||
|
return _scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class GenericFunctionEvalValue : public EvalValue{
|
class GenericFunctionEvalValue : public EvalValue{
|
||||||
protected:
|
protected:
|
||||||
const std::shared_ptr<GenericFunctionScriptType> _type;
|
const std::shared_ptr<GenericFunctionScriptType> _type;
|
||||||
const std::size_t _hash;
|
const std::size_t _hash;
|
||||||
|
std::vector<shared_ptr<GenericFunctionOption>> _options;
|
||||||
public:
|
public:
|
||||||
GenericFunctionEvalValue(shared_ptr<GenericFunctionScriptType> type, size_t hash)
|
GenericFunctionEvalValue(shared_ptr<GenericFunctionScriptType> type, size_t hash)
|
||||||
: _type(move(type)),
|
: _type(move(type)),
|
||||||
_hash(hash){
|
_hash(hash){
|
||||||
|
}
|
||||||
|
|
||||||
|
const shared_ptr<EvalValue> Clone() const final {
|
||||||
|
auto t = make_shared<GenericFunctionEvalValue>(_type, _hash);
|
||||||
|
for (const auto& o: _options){
|
||||||
|
t->_options.push_back(o);
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterOption(GenericFunctionOption* option){
|
||||||
|
_options.push_back(shared_ptr<GenericFunctionOption>(option));
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::shared_ptr<ScriptType> GetType() const {
|
const std::shared_ptr<ScriptType> GetType() const {
|
||||||
|
@ -41,42 +80,9 @@ namespace Porygon::Evaluation {
|
||||||
const std::size_t GetHashCode() const final {
|
const std::size_t GetHashCode() const final {
|
||||||
return _hash;
|
return _hash;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
class ScriptFunctionEvalValue : public GenericFunctionEvalValue {
|
const shared_ptr<GenericFunctionOption> GetOption(const size_t id) const{
|
||||||
const std::shared_ptr<BoundBlockStatement> _innerBlock;
|
return this->_options.at(id);
|
||||||
const std::shared_ptr<EvaluationScope> _scope;
|
|
||||||
|
|
||||||
explicit ScriptFunctionEvalValue(shared_ptr<BoundBlockStatement> innerBlock,
|
|
||||||
shared_ptr<EvaluationScope> scope,
|
|
||||||
shared_ptr<FunctionScriptType> type, size_t hash)
|
|
||||||
: GenericFunctionEvalValue(move(type), hash),
|
|
||||||
_innerBlock(std::move(innerBlock)),
|
|
||||||
_scope(std::move(scope)){
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit ScriptFunctionEvalValue(std::shared_ptr<BoundBlockStatement> innerBlock,
|
|
||||||
std::shared_ptr<EvaluationScope> scope,
|
|
||||||
std::shared_ptr<FunctionScriptType> type)
|
|
||||||
: GenericFunctionEvalValue(move(type), rand()),
|
|
||||||
_innerBlock(std::move(innerBlock)),
|
|
||||||
_scope(std::move(scope)){
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const shared_ptr<EvalValue> Clone() const final {
|
|
||||||
// We don't run make_shared here as it can't call private constructors
|
|
||||||
return shared_ptr<ScriptFunctionEvalValue>(new ScriptFunctionEvalValue(_innerBlock, _scope,
|
|
||||||
dynamic_pointer_cast<FunctionScriptType>(_type), _hash));
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::shared_ptr<BoundBlockStatement> &GetInnerBlock() const {
|
|
||||||
return _innerBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::shared_ptr<EvaluationScope> &GetScope() const {
|
|
||||||
return _scope;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,12 @@
|
||||||
#include "EvalValues/ScriptFunctionEvalValue.hpp"
|
#include "EvalValues/ScriptFunctionEvalValue.hpp"
|
||||||
#include "EvalValues/TableEvalValue.hpp"
|
#include "EvalValues/TableEvalValue.hpp"
|
||||||
#include "../Binder/BoundExpressions/BoundTableExpression.hpp"
|
#include "../Binder/BoundExpressions/BoundTableExpression.hpp"
|
||||||
|
#include "../Binder/BoundExpressions/BoundFunctionCallExpression.hpp"
|
||||||
#include "../TableScriptType.hpp"
|
#include "../TableScriptType.hpp"
|
||||||
#include "../UserData/UserDataFunction.hpp"
|
#include "../UserData/UserDataFunction.hpp"
|
||||||
#include "../Utilities/StringUtils.hpp"
|
#include "../Utilities/StringUtils.hpp"
|
||||||
#include "EvalValues/NumericalTableEvalValue.hpp"
|
#include "EvalValues/NumericalTableEvalValue.hpp"
|
||||||
|
#include "../FunctionScriptType.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Porygon::Binder;
|
using namespace Porygon::Binder;
|
||||||
|
@ -96,11 +98,16 @@ namespace Porygon::Evaluation {
|
||||||
auto type = statement->GetType();
|
auto type = statement->GetType();
|
||||||
auto key = statement->GetKey();
|
auto key = statement->GetKey();
|
||||||
auto block = statement->GetBlock();
|
auto block = statement->GetBlock();
|
||||||
auto value = make_shared<ScriptFunctionEvalValue>(block, this->_evaluationScope, type);
|
auto option = new Evaluation::EvaluationScriptFunctionOption(block, this->_evaluationScope);
|
||||||
|
|
||||||
if (key->IsCreation()) {
|
if (key->IsCreation()) {
|
||||||
|
auto value = make_shared<GenericFunctionEvalValue>(type, rand());
|
||||||
|
value->RegisterOption(option);
|
||||||
this->_evaluationScope->CreateVariable(key, value);
|
this->_evaluationScope->CreateVariable(key, value);
|
||||||
} else {
|
} else {
|
||||||
this->_evaluationScope->SetVariable(key, value);
|
auto var = dynamic_pointer_cast<GenericFunctionEvalValue>(this -> _evaluationScope ->GetVariable(key));
|
||||||
|
var->RegisterOption(option);
|
||||||
|
this->_evaluationScope->SetVariable(key, var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,20 +377,23 @@ namespace Porygon::Evaluation {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto type = std::dynamic_pointer_cast<GenericFunctionScriptType>(function->GetType());
|
auto type = std::dynamic_pointer_cast<GenericFunctionScriptType>(function->GetType());
|
||||||
if (type -> IsScriptFunction()){
|
auto func = dynamic_pointer_cast<GenericFunctionEvalValue>(function);
|
||||||
auto parameterTypes = type->GetParameterTypes();
|
auto option = functionCall ->GetFunctionOption();
|
||||||
auto scriptFunctionType = std::dynamic_pointer_cast<FunctionScriptType>(type);
|
auto opt = func->GetOption(option->GetOptionId());
|
||||||
|
if (option -> IsScriptFunction()){
|
||||||
|
auto parameterTypes = option->GetParameterTypes();
|
||||||
|
auto scriptFunctionType = (ScriptFunctionOption*)option;
|
||||||
auto parameterKeys = scriptFunctionType->GetParameterKeys();
|
auto parameterKeys = scriptFunctionType->GetParameterKeys();
|
||||||
auto originalScope = this->_evaluationScope;
|
auto originalScope = this->_evaluationScope;
|
||||||
auto scriptFunction = dynamic_pointer_cast<ScriptFunctionEvalValue>(function);
|
auto scriptOption = dynamic_pointer_cast<EvaluationScriptFunctionOption>(opt);
|
||||||
this->_evaluationScope = scriptFunction->GetScope();
|
this->_evaluationScope = scriptOption->GetScope();
|
||||||
|
|
||||||
for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++) {
|
for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++) {
|
||||||
auto parameter = parameters[i];
|
auto parameter = parameters[i];
|
||||||
auto key = parameterKeys.at(i);
|
auto key = parameterKeys.at(i);
|
||||||
this->_evaluationScope->CreateVariable(key.get(), parameter->Clone());
|
this->_evaluationScope->CreateVariable(key.get(), parameter->Clone());
|
||||||
}
|
}
|
||||||
this->EvaluateBlockStatement(scriptFunction->GetInnerBlock().get());
|
this->EvaluateBlockStatement(scriptOption->GetInnerBlock().get());
|
||||||
this->_evaluationScope = originalScope;
|
this->_evaluationScope = originalScope;
|
||||||
|
|
||||||
this->_hasReturned = false;
|
this->_hasReturned = false;
|
||||||
|
@ -391,30 +401,33 @@ namespace Porygon::Evaluation {
|
||||||
this->_returnValue = nullptr;
|
this->_returnValue = nullptr;
|
||||||
return r;
|
return r;
|
||||||
} else{
|
} else{
|
||||||
auto userDataFunction = dynamic_pointer_cast<UserData::UserDataFunction>(function);
|
auto scriptOption = dynamic_pointer_cast<UserData::UserDataFunction>(opt);
|
||||||
EvalValue* arr[parameters.size()];
|
EvalValue* arr[parameters.size()];
|
||||||
for (int i = 0; i < parameters.size(); i++){
|
for (int i = 0; i < parameters.size(); i++){
|
||||||
arr[i] = parameters[i].get();
|
arr[i] = parameters[i].get();
|
||||||
}
|
}
|
||||||
return shared_ptr<EvalValue>(userDataFunction -> Call(arr, parameters.size()));
|
return shared_ptr<EvalValue>(scriptOption -> Call(arr, parameters.size()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const shared_ptr<EvalValue> Evaluator::EvaluateFunction(const ScriptFunctionEvalValue *function,
|
const shared_ptr<EvalValue> Evaluator::EvaluateFunction(const GenericFunctionEvalValue *function,
|
||||||
const vector<EvalValue *> ¶meters) {
|
const vector<EvalValue *> ¶meters) {
|
||||||
auto type = std::dynamic_pointer_cast<FunctionScriptType>(function->GetType());
|
auto type = std::dynamic_pointer_cast<GenericFunctionScriptType>(function->GetType());
|
||||||
auto parameterTypes = type->GetParameterTypes();
|
auto option = (ScriptFunctionOption*)type-> GetFirstOption();
|
||||||
auto parameterKeys = type->GetParameterKeys();
|
|
||||||
|
auto parameterTypes = option->GetParameterTypes();
|
||||||
|
auto parameterKeys = option->GetParameterKeys();
|
||||||
|
|
||||||
auto originalScope = this->_evaluationScope;
|
auto originalScope = this->_evaluationScope;
|
||||||
this->_evaluationScope = function->GetScope();
|
auto scriptOption = dynamic_pointer_cast<EvaluationScriptFunctionOption>(function->GetOption(0));
|
||||||
|
this->_evaluationScope = scriptOption->GetScope();
|
||||||
|
|
||||||
for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++) {
|
for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++) {
|
||||||
auto parameter = parameters[i];
|
auto parameter = parameters[i];
|
||||||
auto key = parameterKeys.at(i);
|
auto key = parameterKeys.at(i);
|
||||||
this->_evaluationScope->CreateVariable(key.get(), parameter->Clone());
|
this->_evaluationScope->CreateVariable(key.get(), parameter->Clone());
|
||||||
}
|
}
|
||||||
this->EvaluateBlockStatement(function->GetInnerBlock().get());
|
this->EvaluateBlockStatement(scriptOption->GetInnerBlock().get());
|
||||||
this->_evaluationScope = originalScope;
|
this->_evaluationScope = originalScope;
|
||||||
this->_hasReturned = false;
|
this->_hasReturned = false;
|
||||||
auto r = this->_returnValue;
|
auto r = this->_returnValue;
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace Porygon::Evaluation{
|
||||||
}
|
}
|
||||||
|
|
||||||
EvalValue* Evaluate(const BoundScriptStatement* statement);
|
EvalValue* Evaluate(const BoundScriptStatement* statement);
|
||||||
const shared_ptr<EvalValue> EvaluateFunction(const ScriptFunctionEvalValue *function,
|
const shared_ptr<EvalValue> EvaluateFunction(const GenericFunctionEvalValue *function,
|
||||||
const vector<EvalValue *> ¶meters);
|
const vector<EvalValue *> ¶meters);
|
||||||
|
|
||||||
EvalValue* GetLastValue(){
|
EvalValue* GetLastValue(){
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
#include "FunctionScriptType.hpp"
|
|
@ -0,0 +1,112 @@
|
||||||
|
|
||||||
|
#ifndef PORYGONLANG_FUNCTIONSCRIPTTYPE_HPP
|
||||||
|
#define PORYGONLANG_FUNCTIONSCRIPTTYPE_HPP
|
||||||
|
|
||||||
|
#include "ScriptType.hpp"
|
||||||
|
|
||||||
|
namespace Porygon {
|
||||||
|
class GenericFunctionOption{
|
||||||
|
shared_ptr<ScriptType> _returnType;
|
||||||
|
vector<shared_ptr<ScriptType>> _parameterTypes;
|
||||||
|
size_t _option = 0;
|
||||||
|
public:
|
||||||
|
GenericFunctionOption(shared_ptr<ScriptType> returnType, vector<shared_ptr<ScriptType>> parameterTypes){
|
||||||
|
_returnType = move(returnType);
|
||||||
|
_parameterTypes = move(parameterTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~GenericFunctionOption() = default;
|
||||||
|
|
||||||
|
const shared_ptr<ScriptType> GetReturnType() const {
|
||||||
|
return _returnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetOption(size_t v){
|
||||||
|
_option = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetReturnType(shared_ptr<ScriptType> t) {
|
||||||
|
_returnType = move(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
const vector<shared_ptr<ScriptType>> GetParameterTypes() const {
|
||||||
|
return _parameterTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool IsValid(const vector<shared_ptr<ScriptType>>& parameters){
|
||||||
|
if (parameters.size() != _parameterTypes.size()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < parameters.size(); i++){
|
||||||
|
if (parameters[i]->operator!=(_parameterTypes[i].get())){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t GetOptionId() const{
|
||||||
|
return _option;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const bool IsScriptFunction() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GenericFunctionScriptType : public Porygon::ScriptType {
|
||||||
|
vector<GenericFunctionOption *> _options;
|
||||||
|
public:
|
||||||
|
GenericFunctionScriptType()
|
||||||
|
: ScriptType(Porygon::TypeClass::Function){};
|
||||||
|
|
||||||
|
explicit GenericFunctionScriptType(GenericFunctionOption * option)
|
||||||
|
: ScriptType(Porygon::TypeClass::Function){
|
||||||
|
this -> RegisterFunctionOption(option);
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~GenericFunctionScriptType() final{
|
||||||
|
for (auto o: _options){
|
||||||
|
delete o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterFunctionOption (GenericFunctionOption * opt){
|
||||||
|
opt->SetOption(_options.size());
|
||||||
|
_options.push_back(opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericFunctionOption* GetFunctionOption(const vector<shared_ptr<ScriptType>>& parameters){
|
||||||
|
for (auto o: _options){
|
||||||
|
if (o->IsValid(parameters)){
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericFunctionOption* GetFirstOption(){
|
||||||
|
return _options[0];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScriptFunctionOption : public GenericFunctionOption {
|
||||||
|
vector<shared_ptr<Porygon::Binder::BoundVariableKey>> _parameterKeys;
|
||||||
|
public:
|
||||||
|
ScriptFunctionOption(shared_ptr<ScriptType> returnType, vector<shared_ptr<ScriptType>> parameterTypes,
|
||||||
|
vector<shared_ptr<Porygon::Binder::BoundVariableKey>> parameterKeys)
|
||||||
|
: GenericFunctionOption(move(returnType), std::move(parameterTypes)) {
|
||||||
|
_parameterKeys = move(parameterKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
const vector<shared_ptr<Porygon::Binder::BoundVariableKey>> GetParameterKeys() const {
|
||||||
|
return _parameterKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool IsScriptFunction() const final {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "ScriptType.hpp"
|
||||||
|
|
||||||
|
#endif //PORYGONLANG_FUNCTIONSCRIPTTYPE_HPP
|
|
@ -85,7 +85,7 @@ bool Porygon::Script::HasFunction(const u16string &key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<EvalValue> Porygon::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 = (GenericFunctionEvalValue*)GetVariable(key);
|
||||||
return this->_evaluator->EvaluateFunction(var, variables);
|
return this->_evaluator->EvaluateFunction(var, variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,10 @@ namespace Porygon{
|
||||||
for (int i = 0; i < parameterCount; i++){
|
for (int i = 0; i < parameterCount; i++){
|
||||||
vector[i] = shared_ptr<ScriptType>(parameters[i]);
|
vector[i] = shared_ptr<ScriptType>(parameters[i]);
|
||||||
}
|
}
|
||||||
return new UserData::UserDataFunctionType(shared_ptr<ScriptType>(returnType), vector);
|
auto option = new UserData::UserDataFunctionOption(shared_ptr<ScriptType>(returnType), vector);
|
||||||
|
auto type = new GenericFunctionScriptType();
|
||||||
|
type->RegisterFunctionOption(option);
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef PORYGONLANG_SCRIPTTYPE_HPP
|
#ifndef PORYGONLANG_SCRIPTTYPE_HPP
|
||||||
#define PORYGONLANG_SCRIPTTYPE_HPP
|
#define PORYGONLANG_SCRIPTTYPE_HPP
|
||||||
|
@ -110,55 +106,6 @@ namespace Porygon{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class GenericFunctionScriptType : public ScriptType{
|
|
||||||
shared_ptr<ScriptType> _returnType;
|
|
||||||
vector<shared_ptr<ScriptType>> _parameterTypes;
|
|
||||||
public:
|
|
||||||
GenericFunctionScriptType(std::shared_ptr<ScriptType> returnType, vector<shared_ptr<ScriptType>> parameterTypes)
|
|
||||||
: ScriptType(TypeClass::Function){
|
|
||||||
_returnType = std::move(returnType);
|
|
||||||
_parameterTypes = std::move(parameterTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
const shared_ptr<ScriptType> GetReturnType() const{
|
|
||||||
return _returnType;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetReturnType(shared_ptr<ScriptType> t){
|
|
||||||
_returnType = std::move(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
const vector<shared_ptr<ScriptType>> GetParameterTypes() const{
|
|
||||||
return _parameterTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual const bool IsScriptFunction() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FunctionScriptType : public GenericFunctionScriptType{
|
|
||||||
vector<shared_ptr<Binder::BoundVariableKey>> _parameterKeys;
|
|
||||||
int _scopeIndex;
|
|
||||||
public:
|
|
||||||
FunctionScriptType(std::shared_ptr<ScriptType> returnType, vector<shared_ptr<ScriptType>> parameterTypes,
|
|
||||||
vector<shared_ptr<Binder::BoundVariableKey>> parameterKeys, int scopeIndex)
|
|
||||||
: GenericFunctionScriptType(std::move(returnType), parameterTypes){
|
|
||||||
_parameterKeys = std::move(parameterKeys);
|
|
||||||
_scopeIndex = scopeIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
const vector<shared_ptr<Binder::BoundVariableKey>> GetParameterKeys() const{
|
|
||||||
return _parameterKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int GetScopeIndex() const{
|
|
||||||
return _scopeIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool IsScriptFunction() const final{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class NumericalTableScriptType : public ScriptType{
|
class NumericalTableScriptType : public ScriptType{
|
||||||
shared_ptr<ScriptType> _valueType;
|
shared_ptr<ScriptType> _valueType;
|
||||||
// Consider adding a check whether the table actually contains a type if every key is static.
|
// Consider adding a check whether the table actually contains a type if every key is static.
|
||||||
|
|
|
@ -32,19 +32,28 @@ namespace Porygon::StandardLibraries{
|
||||||
static void RegisterVariables(std::map<Utilities::HashedString, Binder::BoundVariable *>* bound,
|
static void RegisterVariables(std::map<Utilities::HashedString, Binder::BoundVariable *>* bound,
|
||||||
std::map<Utilities::HashedString, shared_ptr<Evaluation::EvalValue>>* values){
|
std::map<Utilities::HashedString, shared_ptr<Evaluation::EvalValue>>* values){
|
||||||
// Register error function
|
// Register error function
|
||||||
auto errorFuncType = make_shared<UserData::UserDataFunctionType>(
|
auto errorFuncTypeOption = new UserData::UserDataFunctionOption(
|
||||||
make_shared<ScriptType>(TypeClass::Nil),
|
make_shared<ScriptType>(TypeClass::Nil),
|
||||||
vector<shared_ptr<ScriptType>>{make_shared<StringScriptType>(false, 0)});
|
vector<shared_ptr<ScriptType>>{make_shared<StringScriptType>(false, 0)});
|
||||||
auto errorFunc = make_shared<UserData::UserDataFunction>(_error, nullptr);
|
auto errorFuncType = make_shared<GenericFunctionScriptType>();
|
||||||
|
errorFuncType->RegisterFunctionOption(errorFuncTypeOption);
|
||||||
|
auto errorFuncOption = new UserData::UserDataFunction(_error, nullptr);
|
||||||
|
auto errorFunc = make_shared<Evaluation::GenericFunctionEvalValue>(errorFuncType, rand());
|
||||||
|
errorFunc->RegisterOption(errorFuncOption);
|
||||||
auto errorLookup = Utilities::HashedString::CreateLookup(u"error");
|
auto errorLookup = Utilities::HashedString::CreateLookup(u"error");
|
||||||
bound->insert({errorLookup, new Binder::BoundVariable(errorFuncType)});
|
bound->insert({errorLookup, new Binder::BoundVariable(errorFuncType)});
|
||||||
values->insert({errorLookup, errorFunc});
|
values->insert({errorLookup, errorFunc});
|
||||||
|
|
||||||
// Register assert function
|
// Register assert function
|
||||||
auto assertFuncType = make_shared<UserData::UserDataFunctionType>(
|
auto assertFuncTypeOption = new UserData::UserDataFunctionOption(
|
||||||
make_shared<ScriptType>(TypeClass::Bool),
|
make_shared<ScriptType>(TypeClass::Bool),
|
||||||
vector<shared_ptr<ScriptType>>{make_shared<ScriptType>(TypeClass::Bool)});
|
vector<shared_ptr<ScriptType>>{make_shared<ScriptType>(TypeClass::Bool)});
|
||||||
auto assertFunc = make_shared<UserData::UserDataFunction>(_assert, nullptr);
|
auto assertFuncType = make_shared<GenericFunctionScriptType>();
|
||||||
|
assertFuncType->RegisterFunctionOption(assertFuncTypeOption);
|
||||||
|
auto assertFuncOption = new UserData::UserDataFunction(_assert, nullptr);
|
||||||
|
auto assertFunc = make_shared<Evaluation::GenericFunctionEvalValue>(assertFuncType, rand());
|
||||||
|
assertFunc->RegisterOption(assertFuncOption);
|
||||||
|
|
||||||
auto assertLookup = Utilities::HashedString::CreateLookup(u"assert");
|
auto assertLookup = Utilities::HashedString::CreateLookup(u"assert");
|
||||||
bound->insert({assertLookup, new Binder::BoundVariable(assertFuncType)});
|
bound->insert({assertLookup, new Binder::BoundVariable(assertFuncType)});
|
||||||
values->insert({assertLookup, assertFunc});
|
values->insert({assertLookup, assertFunc});
|
||||||
|
|
|
@ -24,6 +24,12 @@ namespace Porygon::StandardLibraries{
|
||||||
InternalScope(){
|
InternalScope(){
|
||||||
BasicLibrary::RegisterVariables(&_boundVariables, &_variables);
|
BasicLibrary::RegisterVariables(&_boundVariables, &_variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~InternalScope(){
|
||||||
|
for (const auto& b: _boundVariables){
|
||||||
|
delete b.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static InternalScope _internal;
|
static InternalScope _internal;
|
||||||
|
|
|
@ -6,7 +6,10 @@ using namespace Porygon::Evaluation;
|
||||||
namespace Porygon::UserData{
|
namespace Porygon::UserData{
|
||||||
extern "C" {
|
extern "C" {
|
||||||
EvalValue * CreateFunctionEvalValue(Evaluation::EvalValue* (*func)(void* , EvalValue* [], int ), void* obj) {
|
EvalValue * CreateFunctionEvalValue(Evaluation::EvalValue* (*func)(void* , EvalValue* [], int ), void* obj) {
|
||||||
return new UserDataFunction(func, obj);
|
auto opt = new UserDataFunction(func, obj);
|
||||||
|
auto t = new GenericFunctionEvalValue(make_shared<GenericFunctionScriptType>(), rand());
|
||||||
|
t->RegisterOption(opt);
|
||||||
|
return t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,32 +4,28 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include "../Evaluator/EvalValues/ScriptFunctionEvalValue.hpp"
|
#include "../Evaluator/EvalValues/ScriptFunctionEvalValue.hpp"
|
||||||
#include "UserDataFunctionType.hpp"
|
#include "UserDataFunctionType.hpp"
|
||||||
|
#include "../FunctionScriptType.hpp"
|
||||||
|
|
||||||
namespace Porygon::UserData{
|
namespace Porygon::UserData{
|
||||||
class UserDataFunction : public Evaluation::GenericFunctionEvalValue {
|
class UserDataFunction : public Evaluation::GenericFunctionOption {
|
||||||
Evaluation::EvalValue* (*_call)(void* obj, EvalValue* parameters[], int parameterCount);
|
Evaluation::EvalValue* (*_call)(void* obj, Evaluation::EvalValue* parameters[], int parameterCount);
|
||||||
void *_obj;
|
void *_obj;
|
||||||
|
|
||||||
UserDataFunction(Evaluation::EvalValue* (*call)(void* obj, EvalValue* parameters[], int parameterCount), void* obj,
|
UserDataFunction(Evaluation::EvalValue* (*call)(void* obj, Evaluation::EvalValue* parameters[], int parameterCount), void* obj,
|
||||||
shared_ptr<GenericFunctionScriptType> type, size_t hash) : GenericFunctionEvalValue(std::move(type), hash){
|
shared_ptr<GenericFunctionScriptType> type, size_t hash) : GenericFunctionOption(){
|
||||||
_call = call;
|
_call = call;
|
||||||
_obj = obj;
|
_obj = obj;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
UserDataFunction(Evaluation::EvalValue* (*call)(void* obj, EvalValue* parameters[], int parameterCount), void* obj) :
|
UserDataFunction(Evaluation::EvalValue* (*call)(void* obj, Evaluation::EvalValue* parameters[], int parameterCount), void* obj) :
|
||||||
GenericFunctionEvalValue(make_shared<UserDataFunctionType>(nullptr, vector<shared_ptr<ScriptType>>{}), rand()){
|
GenericFunctionOption(){
|
||||||
_call = call;
|
_call = call;
|
||||||
_obj = obj;
|
_obj = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
EvalValue* Call(EvalValue* parameters[], int parameterCount){
|
Evaluation::EvalValue* Call(Evaluation::EvalValue* parameters[], int parameterCount){
|
||||||
return _call(_obj, parameters, parameterCount);
|
return _call(_obj, parameters, parameterCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
const shared_ptr<EvalValue> Clone() const final {
|
|
||||||
// We don't run make_shared here as it can't call private constructors
|
|
||||||
return shared_ptr<UserDataFunction>(new UserDataFunction(_call, _obj, _type, _hash));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,26 +3,27 @@
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include "../ScriptType.hpp"
|
#include "../ScriptType.hpp"
|
||||||
|
#include "../FunctionScriptType.hpp"
|
||||||
|
|
||||||
namespace Porygon::UserData{
|
namespace Porygon::UserData{
|
||||||
class UserDataFunctionType : public GenericFunctionScriptType{
|
class UserDataFunctionOption : public GenericFunctionOption{
|
||||||
public:
|
public:
|
||||||
UserDataFunctionType(std::shared_ptr<ScriptType> returnType, vector<shared_ptr<ScriptType>> parameterTypes)
|
UserDataFunctionOption(std::shared_ptr<ScriptType> returnType, vector<shared_ptr<ScriptType>> parameterTypes)
|
||||||
: GenericFunctionScriptType(std::move(returnType), std::move(parameterTypes)){
|
: GenericFunctionOption(std::move(returnType), std::move(parameterTypes)) {
|
||||||
|
|
||||||
}
|
}
|
||||||
static UserDataFunctionType* FromRawPointers(ScriptType* returnType, vector<ScriptType*> parameterTypes){
|
static UserDataFunctionOption* FromRawPointers(ScriptType* returnType, vector<ScriptType*> parameterTypes){
|
||||||
auto rt = shared_ptr<ScriptType>(returnType);
|
auto rt = shared_ptr<ScriptType>(returnType);
|
||||||
auto p = vector<shared_ptr<ScriptType>>(parameterTypes.size());
|
auto p = vector<shared_ptr<ScriptType>>(parameterTypes.size());
|
||||||
for (int i = 0; i < parameterTypes.size(); i++){
|
for (int i = 0; i < parameterTypes.size(); i++){
|
||||||
p[i] = shared_ptr<ScriptType>(parameterTypes[i]);
|
p[i] = shared_ptr<ScriptType>(parameterTypes[i]);
|
||||||
}
|
}
|
||||||
return new UserDataFunctionType(rt, p);
|
return new UserDataFunctionOption(rt, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static UserDataFunctionType* FromRawPointers(ScriptType* returnType){
|
static UserDataFunctionOption* FromRawPointers(ScriptType* returnType){
|
||||||
auto rt = shared_ptr<ScriptType>(returnType);
|
auto rt = shared_ptr<ScriptType>(returnType);
|
||||||
return new UserDataFunctionType(rt, {});
|
return new UserDataFunctionOption(rt, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -67,14 +67,18 @@
|
||||||
#define PORYGON_FUNCTION(fieldName, returnType, ...) \
|
#define PORYGON_FUNCTION(fieldName, returnType, ...) \
|
||||||
{ \
|
{ \
|
||||||
Porygon::Utilities::HashedString::ConstHash(#fieldName), \
|
Porygon::Utilities::HashedString::ConstHash(#fieldName), \
|
||||||
new Porygon::UserData::UserDataField(Porygon::UserData::UserDataFunctionType::FromRawPointers(returnType, {__VA_ARGS__} ), \
|
new Porygon::UserData::UserDataField( \
|
||||||
|
new Porygon::GenericFunctionScriptType( \
|
||||||
|
Porygon::UserData::UserDataFunctionOption::FromRawPointers(returnType, {__VA_ARGS__} )), \
|
||||||
\
|
\
|
||||||
\
|
\
|
||||||
[](void* obj) -> Porygon::Evaluation::EvalValue* { \
|
[](void* obj) -> Porygon::Evaluation::EvalValue* { \
|
||||||
return new Porygon::UserData::UserDataFunction( \
|
auto t = new Porygon::Evaluation::GenericFunctionEvalValue(make_shared<GenericFunctionScriptType>(), rand()); \
|
||||||
|
t->RegisterOption(new Porygon::UserData::UserDataFunction( \
|
||||||
[](void* obj, Porygon::Evaluation::EvalValue* par[], int parameterCount) \
|
[](void* obj, Porygon::Evaluation::EvalValue* par[], int parameterCount) \
|
||||||
-> Porygon::Evaluation::EvalValue*{return ((T_USERDATA*)obj)->invoke__##fieldName(obj, par, parameterCount);}, \
|
-> Porygon::Evaluation::EvalValue*{return ((T_USERDATA*)obj)->invoke__##fieldName(obj, par, parameterCount);}, \
|
||||||
obj);}, \
|
obj)); \
|
||||||
|
return t;}, \
|
||||||
nullptr) \
|
nullptr) \
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -150,5 +150,33 @@ return
|
||||||
delete script;
|
delete script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "Allow declaration of multiple functions with different signatures", "[integration]" ) {
|
||||||
|
Script* script = Script::Create(
|
||||||
|
R"(
|
||||||
|
function add(number a, number b)
|
||||||
|
return a + b
|
||||||
|
end
|
||||||
|
|
||||||
|
function add(string a, string b)
|
||||||
|
return a + b
|
||||||
|
end
|
||||||
|
|
||||||
|
intResult = add(5, 500)
|
||||||
|
stringResult = add('foo', 'bar')
|
||||||
|
)"
|
||||||
|
);
|
||||||
|
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||||
|
script->Evaluate();
|
||||||
|
auto intVar = script -> GetVariable(u"intResult");
|
||||||
|
REQUIRE(intVar != nullptr);
|
||||||
|
CHECK(intVar->EvaluateInteger() == 505);
|
||||||
|
auto stringVar = script -> GetVariable(u"stringResult");
|
||||||
|
REQUIRE(stringVar != nullptr);
|
||||||
|
CHECK(stringVar->EvaluateString() == u"foobar");
|
||||||
|
|
||||||
|
|
||||||
|
delete script;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue