Skip to content

Commit

Permalink
add callback_on_instantiate chugins API
Browse files Browse the repository at this point in the history
  • Loading branch information
gewang committed Oct 8, 2023
1 parent af21080 commit d99336c
Show file tree
Hide file tree
Showing 12 changed files with 239 additions and 7 deletions.
20 changes: 18 additions & 2 deletions src/core/chuck_dl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ void CK_DLL_CALL ck_remove_all_shreds( Chuck_VM * vm );
Chuck_DL_Api::Type CK_DLL_CALL ck_type_lookup( Chuck_VM * vm, const char * name );
t_CKBOOL CK_DLL_CALL ck_type_isequal( Chuck_Type * lhs, Chuck_Type * rhs );
t_CKBOOL CK_DLL_CALL ck_type_isa( Chuck_Type * lhs, Chuck_Type * rhs );

void CK_DLL_CALL ck_callback_on_instantiate( f_callback_on_instantiate callback, Chuck_Type * base_type, Chuck_VM * vm, t_CKBOOL shouldSetShredOrigin );



Expand Down Expand Up @@ -1952,7 +1952,8 @@ Chuck_DL_Api::Api::TypeApi::TypeApi() :
lookup(ck_type_lookup),
get_vtable_offset(ck_get_vtable_offset),
is_equal(ck_type_isequal),
isa(ck_type_isa)
isa(ck_type_isa),
callback_on_instantiate(ck_callback_on_instantiate)
{ }


Expand Down Expand Up @@ -2116,6 +2117,21 @@ t_CKBOOL CK_DLL_CALL ck_type_isa( Chuck_Type * lhs, Chuck_Type * rhs )



//-----------------------------------------------------------------------------
// name: ck_callback_on_instantiate()
// desc: register a callback to be invoked whenever a base-type (or its subclass)
// is instantiated, with option for type system to auto-set shred origin if available
//-----------------------------------------------------------------------------
void CK_DLL_CALL ck_callback_on_instantiate( f_callback_on_instantiate callback,
Chuck_Type * base_type, Chuck_VM * vm, t_CKBOOL shouldSetShredOrigin )
{
// register the callback with chuck type
base_type->add_instantiate_cb( callback, shouldSetShredOrigin );
}




//-----------------------------------------------------------------------------
// windows translation
//-----------------------------------------------------------------------------
Expand Down
4 changes: 4 additions & 0 deletions src/core/chuck_dl.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,8 @@ typedef t_CKBOOL (CK_DLL_CALL * f_mainthreadhook)( void * bindle );
typedef t_CKBOOL (CK_DLL_CALL * f_mainthreadquit)( void * bindle );
// shreds watcher callback
typedef void (CK_DLL_CALL * f_shreds_watcher)( Chuck_VM_Shred * SHRED, t_CKINT CODE, t_CKINT PARAM, Chuck_VM * VM, void * BINDLE );
// type instantiation callback
typedef void (CK_DLL_CALL * f_callback_on_instantiate)( Chuck_Type * typeInstantiated, Chuck_VM_Shred * originShred, Chuck_VM * VM );
}


Expand Down Expand Up @@ -908,6 +910,8 @@ struct Api
t_CKBOOL (CK_DLL_CALL * const is_equal)(Type lhs, Type rhs);
// test if lhs is a type of rhs (e.g., SinOsc is a type of UGen)
t_CKBOOL (CK_DLL_CALL * const isa)(Type lhs, Type rhs);
// register a callback to be invoked whenever a base-type (or its subclass) is instantiated, with option for type system to auto-set shred origin if available
void (CK_DLL_CALL * const callback_on_instantiate)( f_callback_on_instantiate callback, Type base_type, Chuck_VM * vm, t_CKBOOL shouldSetShredOrigin );
} * const type;

// constructor
Expand Down
24 changes: 21 additions & 3 deletions src/core/chuck_instr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3991,7 +3991,7 @@ void Chuck_Instr_Pre_Constructor::execute( Chuck_VM * vm, Chuck_VM_Shred * shred
// name: instantiate_object()
// desc: ...
//-----------------------------------------------------------------------------
t_CKBOOL initialize_object( Chuck_Object * object, Chuck_Type * type, Chuck_VM_Shred * shred, Chuck_VM * vm )
t_CKBOOL initialize_object( Chuck_Object * object, Chuck_Type * type, Chuck_VM_Shred * shred, Chuck_VM * vm, t_CKBOOL setShredOrigin )
{
// check if already initialized | 1.5.1.5
if( object->vtable != NULL ) return TRUE;
Expand All @@ -4009,7 +4009,8 @@ t_CKBOOL initialize_object( Chuck_Object * object, Chuck_Type * type, Chuck_VM_S
// UGens: needs shred for auto-disconnect when shred is removed
// user-defined classes (that refer to global-scope variables):
// ...needs shred to access the global-scope variables across sporking
if( type->ugen_info || type->originHint == te_originUserDefined )
// setShredOrigin: if true, this is likely a registered callback_on_instantiate
if( type->ugen_info || type->originHint == te_originUserDefined || setShredOrigin )
{
// set origin shred | 1.5.1.5 (ge) was: ugen->shred = shred;
object->setOriginShred( shred );
Expand Down Expand Up @@ -4130,6 +4131,8 @@ Chuck_Object * instantiate_and_initialize_object( Chuck_Type * type, Chuck_VM_Sh
Chuck_Object * object = NULL;
Chuck_UGen * ugen = NULL;
Chuck_UAna * uana = NULL;
vector<Chuck_Type::CallbackOnInstantiate> instance_cbs;
t_CKBOOL setShredOrigin = FALSE;

// sanity
assert( type != NULL );
Expand Down Expand Up @@ -4184,9 +4187,24 @@ Chuck_Object * instantiate_and_initialize_object( Chuck_Type * type, Chuck_VM_Sh
// check to see enough memory
if( !object ) goto out_of_memory;

// check for callback
setShredOrigin = type->cbs_on_instantiate( instance_cbs );

// initialize
if( !initialize_object( object, type, shred, vm ) ) goto error;
if( !initialize_object( object, type, shred, vm, setShredOrigin ) ) goto error;

// check for callback
if( instance_cbs.size() )
{
// loop over callbacks to call
for( t_CKUINT i = 0; i < instance_cbs.size(); i++ )
{
// call it
instance_cbs[i].callback( type, shred, vm );
}
}

// return the instantiated object
return object;

out_of_memory:
Expand Down
4 changes: 2 additions & 2 deletions src/core/chuck_instr.h
Original file line number Diff line number Diff line change
Expand Up @@ -4232,8 +4232,8 @@ struct Chuck_Instr_Gack : public Chuck_Instr
Chuck_Object * instantiate_and_initialize_object( Chuck_Type * type, Chuck_VM_Shred * shred );
Chuck_Object * instantiate_and_initialize_object( Chuck_Type * type, Chuck_VM * vm );
Chuck_Object * instantiate_and_initialize_object( Chuck_Type * type, Chuck_VM_Shred * shred, Chuck_VM * vm );
// initialize object using Type
t_CKBOOL initialize_object( Chuck_Object * obj, Chuck_Type * type, Chuck_VM_Shred * shred, Chuck_VM * vm );
// initialize object using Type | 1.5.1.5 (ge) added setShredOrigin flag
t_CKBOOL initialize_object( Chuck_Object * obj, Chuck_Type * type, Chuck_VM_Shred * shred, Chuck_VM * vm, t_CKBOOL setShredOrigin = FALSE );

// "throw exception" (halt current shred, print message)
void ck_throw_exception(Chuck_VM_Shred * shred, const char * name);
Expand Down
87 changes: 87 additions & 0 deletions src/core/chuck_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10393,3 +10393,90 @@ bool Chuck_Op_Overload::operator <( const Chuck_Op_Overload & other ) const
// (aL, aR) < (bL, bR) iff (aL < bL) OR ( aL == bL && aR < bR )
return (aL < bL) || (aL == bL && aR < bR);
}




//-----------------------------------------------------------------------------
// name: add_instantiate_cb()
// desc: register type instantiation callback
//-----------------------------------------------------------------------------
void Chuck_Type::add_instantiate_cb( f_callback_on_instantiate cb, t_CKBOOL setShredOrigin )
{
// avoid duplicate
for( t_CKUINT i = 0; i < m_cbs_on_instantiate.size(); i++ )
{
// compare callback pointer
if( cb == m_cbs_on_instantiate[i].callback ) return;
}
// append
m_cbs_on_instantiate.push_back( CallbackOnInstantiate(cb, setShredOrigin) );
}




//-----------------------------------------------------------------------------
// name: remove_instantiate_cb()
// desc: unregister type instantiation callback
//-----------------------------------------------------------------------------
void Chuck_Type::remove_instantiate_cb( f_callback_on_instantiate cb )
{
// iterator
vector<CallbackOnInstantiate>::iterator it = m_cbs_on_instantiate.begin();
// iterate
while( it != m_cbs_on_instantiate.end() )
{
// check the callback
if( (*it).callback == cb )
{
// erase while iterating | c++11 or higher
it = m_cbs_on_instantiate.erase( it );
// m_cbs_on_instantiate.erase( it++ ); // before c++11
}
else
{
it++;
}
}
}




//-----------------------------------------------------------------------------
// name: cbs_on_instantiate()
// desc: get vector of callbacks (including this and parents), return whether any requires setShredOrigin
//-----------------------------------------------------------------------------
t_CKBOOL Chuck_Type::cbs_on_instantiate( std::vector<CallbackOnInstantiate> & results )
{
// clear
results.clear();
// process this
return this->do_cbs_on_instantiate( results );
}




//-----------------------------------------------------------------------------
// name: do_cbs_on_instantiate()
// desc: internal get vector of callbacks (including this and parents), return whether any requires setShredOrigin
//-----------------------------------------------------------------------------
t_CKBOOL Chuck_Type::do_cbs_on_instantiate( std::vector<CallbackOnInstantiate> & results )
{
// number of callbacks in total
t_CKBOOL retval = 0;
// process parents
if( this->parent ) retval = this->parent->do_cbs_on_instantiate( results );
// process this
for( t_CKUINT i = 0; i < m_cbs_on_instantiate.size(); i++ )
{
// copy
results.push_back( m_cbs_on_instantiate[i] );
// if and set shred origin
if( m_cbs_on_instantiate[i].shouldSetShredOrigin ) retval = TRUE;
}
// done
return retval;
}
26 changes: 26 additions & 0 deletions src/core/chuck_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,32 @@ struct Chuck_Type : public Chuck_Object
void apropos_vars( std::string & output, const std::string & prefix, t_CKBOOL inherited );
// dump info about examples
void apropos_examples( std::string & output, const std::string & prefix );

public:
// struct to hold callback on instantiate
struct CallbackOnInstantiate
{
// whether to auto-set shred origin at instantiation;
// see t_CKBOOL initialize_object( ... )
t_CKBOOL shouldSetShredOrigin;
// the callback
f_callback_on_instantiate callback;
// constructor
CallbackOnInstantiate( f_callback_on_instantiate cb = NULL, t_CKBOOL setShredOrigin = FALSE )
: callback(cb), shouldSetShredOrigin(setShredOrigin) { }
};
// register type instantiation callback
void add_instantiate_cb( f_callback_on_instantiate cb, t_CKBOOL setShredOrigin );
// unregister type instantiation callback
void remove_instantiate_cb( f_callback_on_instantiate cb );
// get vector of callbacks (including this and parents), return whether any requires setShredOrigin
t_CKBOOL cbs_on_instantiate( std::vector<CallbackOnInstantiate> & results );

protected:
// vector of callbacks on instantiation of this type (or its subclass)
std::vector<CallbackOnInstantiate> m_cbs_on_instantiate;
// internal get vector of callbacks (including this and parents), return whether any requires setShredOrigin
t_CKBOOL do_cbs_on_instantiate( std::vector<CallbackOnInstantiate> & results );
};


Expand Down
40 changes: 40 additions & 0 deletions src/test/01-Basic/213-spork-nested-var.ck
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// test nested sporking, and accessing file-scope vars from
// nested sporked member function

// accessing this var
5 => int a;

// a (non-public) class
// (public classes wouldn't be able to access file-scope vars)
class Foo
{
// a member function
fun void update( float dt )
{
while( true )
{
// access global-scope var a
a++;
// print
<<< a, dt >>>;
// advance time
200::ms => now;
}
}

fun void go()
{
// spork
spork ~ this.update(2);
// wait a long time (until the parent shred is done)
eon => now;
}
}

// instantiate a Foo
Foo foo;
// call go
spork ~ foo.go();
// let time pass
2.1::second => now;
// (should remove child and grandchild shreds as this shred exits)
11 changes: 11 additions & 0 deletions src/test/01-Basic/213-spork-nested-var.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
6 2.000000
7 2.000000
8 2.000000
9 2.000000
10 2.000000
11 2.000000
12 2.000000
13 2.000000
14 2.000000
15 2.000000
16 2.000000
14 changes: 14 additions & 0 deletions src/test/01-Basic/214-num-types.ck
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// test basic numerical type literals

// int
<<< 1 >>>;
// float
<<< 2.0 >>>;
// complex
<<< #(3,4) >>>;
// polar
<<< %(1,pi/2) >>>;
// vec3
<<< @(5,6,7) >>>;
// vec4
<<< @(5,6,7,8) >>>;
6 changes: 6 additions & 0 deletions src/test/01-Basic/214-num-types.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
1 :(int)
2.000000 :(float)
#(3.0000,4.0000) :(complex)
%(1.0000,0.5000*pi) :(polar)
@(5.0000,6.0000,7.0000) :(vec3)
@(5.0000,6.0000,7.0000,8.0000) :(vec4)
7 changes: 7 additions & 0 deletions src/test/06-Errors/error-depend-var2.ck
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// error case using a global-scope var before declaration

// the use
<<< a >>>;

// the decl
int a;
3 changes: 3 additions & 0 deletions src/test/06-Errors/error-depend-var2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
error-depend-var2.ck:4:5: error: variable/member 'a' is used before declaration
[4] <<< a >>>;
^

0 comments on commit d99336c

Please sign in to comment.