Fix the __return keyword

fixes #7811
This commit is contained in:
Gunnar Beutner 2014-11-24 00:04:26 +01:00
parent c29d6a99ac
commit d3a6277fec
6 changed files with 54 additions and 6 deletions

View File

@ -652,9 +652,7 @@ lterm: T_LOCAL indexer combined_set_op rterm
} }
| T_RETURN rterm | T_RETURN rterm
{ {
std::vector<Expression *> vname; $$ = new ReturnExpression($2, DebugInfoRange(@1, @2));
vname.push_back(MakeLiteral("__result"));
$$ = new SetExpression(vname, OpSetLiteral, $2, false, DebugInfoRange(@1, @2));
} }
| apply | apply
{ {

View File

@ -45,6 +45,8 @@ Value Expression::Evaluate(VMFrame& frame, DebugHint *dhint) const
#endif /* _DEBUG */ #endif /* _DEBUG */
return DoEvaluate(frame, dhint); return DoEvaluate(frame, dhint);
} catch (const InterruptExecutionError&) {
throw;
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
if (boost::get_error_info<boost::errinfo_nested_exception>(ex)) if (boost::get_error_info<boost::errinfo_nested_exception>(ex))
throw; throw;
@ -344,6 +346,11 @@ Value SetExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
return right; return right;
} }
Value ReturnExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
{
BOOST_THROW_EXCEPTION(InterruptExecutionError(m_Operand->Evaluate(frame)));
}
Value IndexerExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const Value IndexerExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
{ {
return VMOps::Indexer(frame, m_Indexer); return VMOps::Indexer(frame, m_Indexer);

View File

@ -101,6 +101,25 @@ enum CombinedSetOp
OpSetDivide OpSetDivide
}; };
class InterruptExecutionError : virtual public std::exception, virtual public boost::exception
{
public:
InterruptExecutionError(const Value& result)
: m_Result(result)
{ }
~InterruptExecutionError(void) throw()
{ }
Value GetResult(void) const
{
return m_Result;
}
private:
Value m_Result;
};
typedef std::map<String, String> DefinitionMap; typedef std::map<String, String> DefinitionMap;
/** /**
@ -537,6 +556,17 @@ private:
}; };
class I2_CONFIG_API ReturnExpression : public UnaryExpression
{
public:
ReturnExpression(Expression *expression, const DebugInfo& debugInfo = DebugInfo())
: UnaryExpression(expression, debugInfo)
{ }
protected:
virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API IndexerExpression : public DebuggableExpression class I2_CONFIG_API IndexerExpression : public DebuggableExpression
{ {
public: public:

View File

@ -30,7 +30,6 @@ struct VMFrame
{ {
Dictionary::Ptr Locals; Dictionary::Ptr Locals;
Object::Ptr Self; Object::Ptr Self;
Value Result;
VMFrame(void) VMFrame(void)
: Locals(new Dictionary()), Self(Locals) : Locals(new Dictionary()), Self(Locals)

View File

@ -295,8 +295,14 @@ private:
for (std::vector<Value>::size_type i = 0; i < std::min(arguments.size(), funcargs.size()); i++) for (std::vector<Value>::size_type i = 0; i < std::min(arguments.size(), funcargs.size()); i++)
frame.Locals->Set(funcargs[i], arguments[i]); frame.Locals->Set(funcargs[i], arguments[i]);
expr->Evaluate(frame); Value result;
return frame.Result; try {
result = expr->Evaluate(frame);
} catch (const InterruptExecutionError& iee) {
result = iee.GetResult();
}
return result;
} }
static inline void SlotWrapper(const Value& funcName, const std::vector<Value>& arguments) static inline void SlotWrapper(const Value& funcName, const std::vector<Value>& arguments)

View File

@ -226,6 +226,14 @@ BOOST_AUTO_TEST_CASE(advanced)
expr = ConfigCompiler::CompileText("<test>", "a = 3 b = 3"); expr = ConfigCompiler::CompileText("<test>", "a = 3 b = 3");
BOOST_CHECK(expr == NULL); BOOST_CHECK(expr == NULL);
expr = ConfigCompiler::CompileText("<test>", "__function() { 3 }()");
BOOST_CHECK(expr->Evaluate(frame) == 3);
delete expr;
expr = ConfigCompiler::CompileText("<test>", "__function() { __return 3, 5 }()");
BOOST_CHECK(expr->Evaluate(frame) == 3);
delete expr;
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()