support for subclassing ScriptFunc's, esp. for alternate lambda closures

This commit is contained in:
Vern Paxson 2021-03-18 10:10:44 -07:00
parent 91c2e05099
commit 78f18b4fa6
3 changed files with 26 additions and 6 deletions

View file

@ -587,6 +587,11 @@ bool ScriptFunc::StrengthenClosureReference(Frame* f)
return true; return true;
} }
bool ScriptFunc::CopySemantics() const
{
return type->GetCaptures().has_value();
}
void ScriptFunc::SetClosureFrame(Frame* f) void ScriptFunc::SetClosureFrame(Frame* f)
{ {
if ( closure ) if ( closure )

View file

@ -145,7 +145,7 @@ protected:
namespace detail { namespace detail {
class ScriptFunc final : public Func { class ScriptFunc : public Func {
public: public:
ScriptFunc(const IDPtr& id, StmtPtr body, ScriptFunc(const IDPtr& id, StmtPtr body,
const std::vector<IDPtr>& inits, const std::vector<IDPtr>& inits,
@ -210,12 +210,17 @@ public:
*/ */
bool StrengthenClosureReference(Frame* f); bool StrengthenClosureReference(Frame* f);
/**
* Whether the function's closure uses copy semantics.
*/
virtual bool CopySemantics() const;
/** /**
* Serializes this function's closure or capture frame. * Serializes this function's closure or capture frame.
* *
* @return a serialized version of the function's closure/capture frame. * @return a serialized version of the function's closure/capture frame.
*/ */
broker::expected<broker::data> SerializeClosure() const; virtual broker::expected<broker::data> SerializeClosure() const;
/** /**
* Sets the captures frame to one built from *data*. * Sets the captures frame to one built from *data*.
@ -257,6 +262,7 @@ public:
protected: protected:
ScriptFunc() : Func(SCRIPT_FUNC) {} ScriptFunc() : Func(SCRIPT_FUNC) {}
StmtPtr AddInits( StmtPtr AddInits(
StmtPtr body, StmtPtr body,
const std::vector<IDPtr>& inits); const std::vector<IDPtr>& inits);
@ -280,7 +286,7 @@ protected:
* *
* @param f the frame holding the values of capture variables * @param f the frame holding the values of capture variables
*/ */
void SetCaptures(Frame* f); virtual void SetCaptures(Frame* f);
private: private:
size_t frame_size; size_t frame_size;

View file

@ -392,6 +392,17 @@ struct val_converter {
if ( a.size() == 2 ) // we have a closure/capture frame if ( a.size() == 2 ) // we have a closure/capture frame
{ {
// Note, seems if we already have a separate
// instance of the same lambda, then unless
// we use a cloned value, we'll step on that
// one's captures, too. This is because
// the capture mapping lives with the Func
// object rather than the FuncVal. However,
// we can't readily Clone() here because
// rval is const (and, grrr, Clone() is not).
// -VP
// rval = rval->Clone();
auto frame = broker::get_if<broker::vector>(a[1]); auto frame = broker::get_if<broker::vector>(a[1]);
if ( ! frame ) if ( ! frame )
return nullptr; return nullptr;
@ -400,9 +411,7 @@ struct val_converter {
if ( ! b ) if ( ! b )
return nullptr; return nullptr;
auto copy_semantics = b->GetType()->GetCaptures().has_value(); if ( b->CopySemantics() )
if ( copy_semantics )
{ {
if ( ! b->DeserializeCaptures(*frame) ) if ( ! b->DeserializeCaptures(*frame) )
return nullptr; return nullptr;