From 71c98392d97d714cd873325473e51ef464f4b653 Mon Sep 17 00:00:00 2001 From: Ge Wang Date: Tue, 26 Nov 2024 23:33:43 -0800 Subject: [PATCH] properly emit function value vs. function call #2024-func-call-update --- src/core/chuck_absyn.h | 5 ++ src/core/chuck_emit.cpp | 76 ++++++++++++++++++---- src/core/chuck_instr.cpp | 9 ++- src/core/chuck_scan.cpp | 9 ++- src/core/chuck_type.cpp | 28 ++++++-- src/core/chuck_type.h | 3 +- src/test/04-Stress/func-call-1.ck | 16 +++++ src/test/04-Stress/func-call-10-spork-s.ck | 12 ++++ src/test/04-Stress/func-call-2-static.ck | 11 ++++ src/test/04-Stress/func-call-3-member.ck | 16 +++++ src/test/04-Stress/func-call-4-vec.ck | 10 +++ src/test/04-Stress/func-call-5-sinosc.ck | 13 ++++ src/test/04-Stress/func-call-6-ctor.ck | 20 ++++++ src/test/04-Stress/func-call-7-class-m.ck | 13 ++++ src/test/04-Stress/func-call-8-class-s.ck | 13 ++++ src/test/04-Stress/func-call-9-spork-m.ck | 13 ++++ src/test/04-Stress/static-member-access.ck | 16 +++++ 17 files changed, 260 insertions(+), 23 deletions(-) create mode 100644 src/test/04-Stress/func-call-1.ck create mode 100644 src/test/04-Stress/func-call-10-spork-s.ck create mode 100644 src/test/04-Stress/func-call-2-static.ck create mode 100644 src/test/04-Stress/func-call-3-member.ck create mode 100644 src/test/04-Stress/func-call-4-vec.ck create mode 100644 src/test/04-Stress/func-call-5-sinosc.ck create mode 100644 src/test/04-Stress/func-call-6-ctor.ck create mode 100644 src/test/04-Stress/func-call-7-class-m.ck create mode 100644 src/test/04-Stress/func-call-8-class-s.ck create mode 100644 src/test/04-Stress/func-call-9-spork-m.ck create mode 100644 src/test/04-Stress/static-member-access.ck diff --git a/src/core/chuck_absyn.h b/src/core/chuck_absyn.h index da6edda89..d20b68661 100644 --- a/src/core/chuck_absyn.h +++ b/src/core/chuck_absyn.h @@ -407,6 +407,11 @@ struct a_Exp_ t_CKTYPE cast_to; t_CKUINT emit_var; // 1 = emit var, 2 = emit var and value + // assuming this Exp is a func, this will properly + // emit in preparation to be called | 1.5.4.3 (ge) added + // #2024-func-call-update + t_CKBOOL emit_as_funccall; + union { struct a_Exp_Binary_ binary; diff --git a/src/core/chuck_emit.cpp b/src/core/chuck_emit.cpp index 95832d22a..3b377bb4f 100644 --- a/src/core/chuck_emit.cpp +++ b/src/core/chuck_emit.cpp @@ -106,7 +106,7 @@ t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Exp_Func_Call exp ); t_CKBOOL emit_engine_emit_cast( Chuck_Emitter * emit, Chuck_Type * to, Chuck_Type * from, uint32_t where ); t_CKBOOL emit_engine_emit_symbol( Chuck_Emitter * emit, S_Symbol symbol, Chuck_Value * v, t_CKBOOL emit_var, - t_CKUINT line, t_CKUINT where ); + t_CKUINT line, t_CKUINT where, a_Exp_Primary exp ); Chuck_Instr_Stmt_Start * emit_engine_track_stmt_refs_start( Chuck_Emitter * emit, a_Stmt stmt ); void emit_engine_track_stmt_refs_cleanup( Chuck_Emitter * emit, Chuck_Instr_Stmt_Start * start ); // disabled until further notice (added 1.3.0.0) @@ -275,7 +275,7 @@ Chuck_VM_Code * emit_engine_emit_prog( Chuck_Emitter * emit, a_Program prog, emit->pop_scope(); // append end of code emit->append( new Chuck_Instr_EOC ); - // add code str to whichever instruction began this section | 1.5.4.2 (ge) added + // add code str to whichever instruction began this section | 1.5.4.3 (ge) added emit->code->code[index]->prepend_codestr( "/* end of code */" ); // make sure @@ -2050,12 +2050,19 @@ t_CKBOOL emit_engine_emit_exp_binary( Chuck_Emitter * emit, a_Exp_Binary binary // whether to track object references on stack (added 1.3.0.2) t_CKBOOL doRefLeft = FALSE; t_CKBOOL doRefRight = FALSE; + // check to see if this is a function call (added 1.3.0.2) + // i.e., does LHS => RHS resolve to function call RHS(LHS)? // added ae_op_chuck and make sure not null, latter has type-equivalence with object types in certain contexts | 1.5.1.7 - if( binary->op == ae_op_chuck && isa( binary->rhs->type, emit->env->ckt_function ) && !isnull( emit->env, binary->rhs->type ) ) + // if( binary->op == ae_op_chuck && isa( binary->rhs->type, emit->env->ckt_function ) && !isnull( emit->env, binary->rhs->type ) ) + if( type_engine_binary_is_func_call( emit->env, binary->op, binary->lhs, binary->rhs ) ) { // take care of objects in terms of reference counting doRefLeft = TRUE; + + // need to know here so the RHS can properly emit + // 1.5.4.3 (ge) added as part of #2024-func-call-update + binary->rhs->emit_as_funccall = TRUE; } // check operator overload | 1.5.1.5 (ge) t_CKBOOL op_overload = (binary->ck_overload_func != NULL); @@ -3158,6 +3165,9 @@ t_CKBOOL emit_engine_emit_op_overload_postfix( Chuck_Emitter * emit, a_Exp_Postf //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_op_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ) { + // consistency check | 1.5.4.3 (ge) added + assert( binary->op == ae_op_chuck ); + // any implicit cast happens before this Chuck_Type * left = lhs->cast_to ? lhs->cast_to : lhs->type; Chuck_Type * right = rhs->cast_to ? rhs->cast_to : rhs->type; @@ -3243,7 +3253,8 @@ t_CKBOOL emit_engine_emit_op_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs, // func call // make sure not 'null' which also looks like any object | 1.5.1.7 - if( isa( right, emit->env->ckt_function ) && !isnull(emit->env,right) ) + // if( isa( right, emit->env->ckt_function ) && !isnull(emit->env,right) ) + if( type_engine_binary_is_func_call( emit->env, binary->op, lhs, rhs ) ) { assert( binary->ck_func != NULL ); @@ -3740,7 +3751,7 @@ t_CKBOOL emit_engine_emit_exp_primary( Chuck_Emitter * emit, a_Exp_Primary exp ) { // emit the symbol return emit_engine_emit_symbol( - emit, exp->var, exp->value, exp->self->emit_var, exp->line, exp->where ); + emit, exp->var, exp->value, exp->self->emit_var, exp->line, exp->where, exp ); } break; @@ -4282,6 +4293,10 @@ t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, return FALSE; } + // need to know here so the func can properly emit + // 1.5.4.3 (ge) added as part of #2024-func-call-update + func_call->func->emit_as_funccall = TRUE; + // emit func if( !emit_engine_emit_exp( emit, func_call->func ) ) { @@ -4296,7 +4311,7 @@ t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, // additional func call options | 1.5.4.2 (ge) added Chuck_FuncCall_Options options; - // in the case of member func calls + // check if func is a dot_member if( func_call->func->s_type == ae_exp_dot_member ) { // if possible, get more accurate code position @@ -4620,10 +4635,15 @@ t_CKBOOL emit_engine_emit_exp_dot_member_special( Chuck_Emitter * emit, emit->append( new Chuck_Instr_Reg_Transmute_Value_To_Pointer( t_base->size ) ); } - // dup the base pointer ('this' pointer as argument -- special case primitive) - // as of 1.5.4.2 this is emitted for both literals and variables - // #special-primitive-member-func-from-literal - emit->append( new Chuck_Instr_Reg_Dup_Last ); + // check if we are part of a function call vs. function as value + // 1.5.4.3 (ge) added as part of #2024-func-call-update + if( member->self->emit_as_funccall ) + { + // dup the base pointer ('this' pointer as argument -- special case primitive) + // as of 1.5.4.2 this is emitted for both literals and variables + // #special-primitive-member-func-from-literal + emit->append( new Chuck_Instr_Reg_Dup_Last ); + } // find the offset for virtual table offset = func->vt_index; @@ -4700,8 +4720,13 @@ t_CKBOOL emit_engine_emit_exp_dot_member( Chuck_Emitter * emit, { // emit the base (TODO: return on error?) emit_engine_emit_exp( emit, member->base ); - // dup the base pointer ('this' pointer as argument) - emit->append( new Chuck_Instr_Reg_Dup_Last ); + // check if we are part of a function call vs. function as value + // 1.5.4.3 (ge) added as part of #2024-func-call-update + if( member->self->emit_as_funccall ) + { + // dup the base pointer ('this' pointer as argument) + emit->append( new Chuck_Instr_Reg_Dup_Last ); + } // find the offset for virtual table offset = func->vt_index; // emit the function @@ -4712,6 +4737,13 @@ t_CKBOOL emit_engine_emit_exp_dot_member( Chuck_Emitter * emit, { // emit the type emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)t_base ) ); + // check if we are part of a function call vs. function as value + // 1.5.4.3 (ge) added as part of #2024-func-call-update + if( member->self->emit_as_funccall ) + { + // dup the base pointer ('this' pointer as argument) + emit->append( new Chuck_Instr_Reg_Dup_Last ); + } // emit the static function emit->append( new Chuck_Instr_Dot_Static_Func( func ) ); } @@ -4769,6 +4801,14 @@ t_CKBOOL emit_engine_emit_exp_dot_member( Chuck_Emitter * emit, { // emit the type - spencer emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)t_base ) ); + // if part of a func call + // 1.5.4.3 (ge) added as part of #2024-func-call-update + if( member->self->emit_as_funccall ) + { + // dupe the pointer, as Chuck_Instr_Dot_Static_Func will consume it + // 1.5.4.3 (ge) added as part of #2024-func-call-update + emit->append( new Chuck_Instr_Reg_Dup_Last ); + } // get the func | 1.4.1.0 (ge) added looking in parent value = type_engine_find_value( t_base, member->xid ); // get the function reference @@ -5861,6 +5901,10 @@ t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Exp_Func_Call exp ) if( !emit_engine_emit_func_args( emit, exp ) ) return FALSE; + // need to know here so the func can properly emit + // 1.5.4.3 (ge) added as part of #2024-func-call-update + exp->func->emit_as_funccall = TRUE; + // emit func pointer on sporker shred if( !emit_engine_emit_exp( emit, exp->func ) ) { @@ -5953,11 +5997,11 @@ t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Exp_Func_Call exp ) //----------------------------------------------------------------------------- // name: emit_engine_emit_symbol() -// desc: ... +// desc: emit a symbol into code //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_symbol( Chuck_Emitter * emit, S_Symbol symbol, Chuck_Value * v, t_CKBOOL emit_var, - t_CKUINT line, t_CKUINT where ) + t_CKUINT line, t_CKUINT where, a_Exp_Primary exp ) { // look up the value // Chuck_Value * v = emit->env->curr->lookup_value( symbol, TRUE ); @@ -6040,6 +6084,10 @@ t_CKBOOL emit_engine_emit_symbol( Chuck_Emitter * emit, S_Symbol symbol, CK_SAFE_ADD_REF( dot->dot_member.t_base ); // 1.5.1.3 dot->emit_var = emit_var; + // propagate whether this should be emitted as a func call (vs. a function value only) + // 1.5.4.3 (ge) added as part of #2024-func-call-update + dot->emit_as_funccall = exp->self->emit_as_funccall; + // emit it if( !emit_engine_emit_exp_dot_member( emit, &dot->dot_member ) ) { diff --git a/src/core/chuck_instr.cpp b/src/core/chuck_instr.cpp index 23ea7ffe7..0c4829b58 100644 --- a/src/core/chuck_instr.cpp +++ b/src/core/chuck_instr.cpp @@ -7776,7 +7776,11 @@ void Chuck_Instr_Dot_Static_Func::execute( Chuck_VM * vm, Chuck_VM_Shred * shred // 1.4.1.0 (ge): leave the base type on the operand stack // commented out: pop the type pointer - // pop_( sp, 1 ); + // 1.5.4.3 (ge): uncommented, remove base pointer, consistent with + // other dot-member function emission; this helps cleaning up the + // stack, depending on whether this is part of a function value emission + // only, or going to be used as a function call #2024-func-call-update + pop_( sp, 1 ); // push the address push_( sp, (t_CKUINT)(m_func) ); @@ -9570,7 +9574,8 @@ void Chuck_Instr_Gack::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) if( *(sp) == 0 ) CK_FPRINTF_STDERR( "null " ); else - CK_FPRINTF_STDERR( "0x%lx (refcount=%d) ", *(sp), obj->m_ref_count ); + CK_FPRINTF_STDERR( "0x%lx :(%s|refcount=%d)\n", *(sp), type->c_name(), obj->m_ref_count ); + // CK_FPRINTF_STDERR( "0x%lx (refcount=%d) ", *(sp), obj->m_ref_count ); } else { diff --git a/src/core/chuck_scan.cpp b/src/core/chuck_scan.cpp index c25ef1444..03e511c0e 100644 --- a/src/core/chuck_scan.cpp +++ b/src/core/chuck_scan.cpp @@ -296,10 +296,15 @@ t_CKBOOL type_engine_scan0_class_def( Chuck_Env * env, a_Class_Def class_def ) if( the_class->is_public ) { the_class->nspc->parent = env->context->nspc; } else { the_class->nspc->parent = env->curr; } - the_class->func = NULL; + + // 1.5.4.3 (ge) commented out...type2func_bridge already init to NULL + // #2024-func-call-update + // the_class->type2func_bridge = NULL; + // 1.5.0.5 (ge) commented out; the AST is cleaned up after every compilation; // would need to make deep copy if want to keep around // the_class->def = class_def; + // add code the_class->nspc->pre_ctor = new Chuck_VM_Code; CK_SAFE_ADD_REF( the_class->nspc->pre_ctor ); @@ -3085,7 +3090,7 @@ t_CKBOOL type_engine_scan2_func_def( Chuck_Env * env, a_Func_Def f ) type->base_name = "[function]"; type->parent = env->ckt_function; // TODO: reference count the parent type->size = sizeof(void *); - type->func = func; + type->type2func_bridge = func; // TODO: consider ref count // make new value, with potential overloaded name value = env->context->new_Chuck_Value( type, func_name ); diff --git a/src/core/chuck_type.cpp b/src/core/chuck_type.cpp index a14ded583..7269c8e54 100644 --- a/src/core/chuck_type.cpp +++ b/src/core/chuck_type.cpp @@ -2737,7 +2737,8 @@ t_CKTYPE type_engine_check_op_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs, t_CKTYPE left = lhs->type, right = rhs->type; // chuck to function - if( !isnull(env, right) && isa( right, env->ckt_function ) ) + // if( !isnull(env, right) && isa( right, env->ckt_function ) ) + if( type_engine_binary_is_func_call( env, ae_op_chuck, lhs, rhs ) ) { // treat this function call return type_engine_check_exp_func_call( env, rhs, lhs, binary->ck_func, binary->where ); @@ -4737,7 +4738,7 @@ t_CKTYPE type_engine_check_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp } // copy the func - up = f->func; + up = f->type2func_bridge; // check the arguments if( args ) @@ -8962,6 +8963,25 @@ t_CKBOOL type_engine_is_base_static( Chuck_Env * env, Chuck_Type * baseType ) +//----------------------------------------------------------------------------- +// name: type_engine_binary_is_func_call() | 1.5.4.3 (ge) +// desc: check whether a binary expression is a function call +// i.e., LHS => RHS same as RHS(LHS) +//----------------------------------------------------------------------------- +t_CKBOOL type_engine_binary_is_func_call( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs ) +{ + // get types + t_CKTYPE right = rhs->type; + + // check LHS => RHS && RHS is a function (and not null)... + return op == ae_op_chuck + && isa( right, env->ckt_function ) + && !isnull(env,right); +} + + + + static const char * g_howmuch[] = { "ALL", "IMPORT_ONLY", "ALL_EXCEPT_IMPORT" }; //----------------------------------------------------------------------------- // name: howmuch2str() @@ -9744,7 +9764,7 @@ Chuck_Type::Chuck_Type( Chuck_Env * env, te_Type _id, const std::string & _n, array_depth = 0; obj_size = 0; nspc = NULL; - func = NULL; /* def = NULL; */ + type2func_bridge = NULL; /* def = NULL; */ is_public = FALSE; is_copy = FALSE; ugen_info = NULL; @@ -9836,7 +9856,7 @@ const Chuck_Type & Chuck_Type::operator =( const Chuck_Type & rhs ) this->is_copy = TRUE; this->array_depth = rhs.array_depth; this->array_type = rhs.array_type; CK_SAFE_ADD_REF(this->array_type); - this->func = rhs.func; CK_SAFE_ADD_REF(this->func); + this->type2func_bridge = rhs.type2func_bridge; CK_SAFE_ADD_REF(this->type2func_bridge); this->nspc = rhs.nspc; CK_SAFE_ADD_REF(this->nspc); // this->owner = rhs.owner; CK_SAFE_ADD_REF(this->owner); diff --git a/src/core/chuck_type.h b/src/core/chuck_type.h index 954d12288..51301c6df 100644 --- a/src/core/chuck_type.h +++ b/src/core/chuck_type.h @@ -1003,7 +1003,7 @@ struct Chuck_Type : public Chuck_Object // type info Chuck_Namespace * nspc; // func info - Chuck_Func * func; + Chuck_Func * type2func_bridge; // ugen Chuck_UGen_Info * ugen_info; // is public class | 1.5.4.0 (ge) added @@ -1402,6 +1402,7 @@ t_CKBOOL type_engine_check_const( Chuck_Env * env, a_Exp e, int pos ); // TODO t_CKBOOL type_engine_compat_func( a_Func_Def lhs, a_Func_Def rhs, int pos, std::string & err, t_CKBOOL print = TRUE ); t_CKBOOL type_engine_get_deprecate( Chuck_Env * env, const std::string & from, std::string & to ); t_CKBOOL type_engine_is_base_static( Chuck_Env * env, Chuck_Type * baseType ); // 1.5.0.0 (ge) added +t_CKBOOL type_engine_binary_is_func_call( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs ); // 1.5.4.3 (ge) added Chuck_Type * type_engine_find_common_anc( Chuck_Type * lhs, Chuck_Type * rhs ); Chuck_Type * type_engine_find_type( Chuck_Env * env, a_Id_List path ); Chuck_Type * type_engine_find_type( Chuck_Env * env, const std::string & name ); // 1.5.0.0 (ge) added diff --git a/src/test/04-Stress/func-call-1.ck b/src/test/04-Stress/func-call-1.ck new file mode 100644 index 000000000..338a33057 --- /dev/null +++ b/src/test/04-Stress/func-call-1.ck @@ -0,0 +1,16 @@ +// #2024-func-call-update verification + +// test custom non-class function +fun void foo( int a ) { } + +// call it +foo(1); +// get the function as value only +foo; + +// check for stack overflow +repeat(100000) foo(2); +repeat(100000) foo; + +// if we get here we are ok +<<< "success" >>>; \ No newline at end of file diff --git a/src/test/04-Stress/func-call-10-spork-s.ck b/src/test/04-Stress/func-call-10-spork-s.ck new file mode 100644 index 000000000..c2308c0a4 --- /dev/null +++ b/src/test/04-Stress/func-call-10-spork-s.ck @@ -0,0 +1,12 @@ +// #2024-func-call-update verification +// test spork static function from within a class +class Foo +{ + static int N; + fun static void foo() { N++; spork ~ bar(); me.yield(); } + fun static void bar() { if( N >= 10000 ) <<< "success" >>>; } +} + +0 => Foo.N; +// test for stack overflow +repeat(10000) Foo.foo(); diff --git a/src/test/04-Stress/func-call-2-static.ck b/src/test/04-Stress/func-call-2-static.ck new file mode 100644 index 000000000..409cc668b --- /dev/null +++ b/src/test/04-Stress/func-call-2-static.ck @@ -0,0 +1,11 @@ +// #2024-func-call-update verification + +// test static function +Machine.refcount; + +// check for stack overflow +repeat(1000000) + Machine.refcount; + +// if we get here, ok +<<< "success" >>>; diff --git a/src/test/04-Stress/func-call-3-member.ck b/src/test/04-Stress/func-call-3-member.ck new file mode 100644 index 000000000..25c5293bf --- /dev/null +++ b/src/test/04-Stress/func-call-3-member.ck @@ -0,0 +1,16 @@ +// #2024-func-call-update verification + +// test member function +SinOsc osc; + +// emit as value without call +osc.gain; + +// test for stack overflow +repeat(1000000) osc.gain; + +// this might yield a compiler later on, until then... +repeat(1000000) osc.gain == "hello"; + +// if we get here, ok +<<< "success" >>>; diff --git a/src/test/04-Stress/func-call-4-vec.ck b/src/test/04-Stress/func-call-4-vec.ck new file mode 100644 index 000000000..c56259e97 --- /dev/null +++ b/src/test/04-Stress/func-call-4-vec.ck @@ -0,0 +1,10 @@ +// #2024-func-call-update verification + +// test special prim-object hybrids +vec2 v; + +// test for stack overflow +repeat(1000000) v.dot; + +// if we get here, ok +<<< "success" >>>; diff --git a/src/test/04-Stress/func-call-5-sinosc.ck b/src/test/04-Stress/func-call-5-sinosc.ck new file mode 100644 index 000000000..5f1a2f728 --- /dev/null +++ b/src/test/04-Stress/func-call-5-sinosc.ck @@ -0,0 +1,13 @@ +// #2024-func-call-update verification + +// test various flavors of call member function... +SinOsc foo; + +// test stack alignment; just emit function as value +repeat(100000) foo.freq; +// test stack alignment; call the function +repeat(100000) foo.freq(440); +// test stack alignment; call the function with => +repeat(100000) 440 => foo.freq; + +<<< "success" >>>; \ No newline at end of file diff --git a/src/test/04-Stress/func-call-6-ctor.ck b/src/test/04-Stress/func-call-6-ctor.ck new file mode 100644 index 000000000..d6131635c --- /dev/null +++ b/src/test/04-Stress/func-call-6-ctor.ck @@ -0,0 +1,20 @@ +// #2024-func-call-update verification + +// test constructor instruction stack alignment +true => int OK; + +// class definition +class Foo +{ + int N; + // constructor + fun Foo(int n) { n => N; } +} + +// test stack overflow +repeat( 100000 ) +{ Foo foo(5); if( foo.N != 5 ) { false => OK; break; } } + +// print +if( OK ) <<< "success" >>>; +else <<< "noooooo" >>>; \ No newline at end of file diff --git a/src/test/04-Stress/func-call-7-class-m.ck b/src/test/04-Stress/func-call-7-class-m.ck new file mode 100644 index 000000000..62bef2072 --- /dev/null +++ b/src/test/04-Stress/func-call-7-class-m.ck @@ -0,0 +1,13 @@ +// #2024-func-call-update verification + +0 => int N; + +// test calling member function from within class definition +class Foo +{ + fun void foo() { N++; bar(); } + fun void bar() { if( N >= 100000 ) <<< "success" >>>; } +} + +// test for stack overflow +repeat(100000) { Foo foo; foo.foo(); } diff --git a/src/test/04-Stress/func-call-8-class-s.ck b/src/test/04-Stress/func-call-8-class-s.ck new file mode 100644 index 000000000..81aa43050 --- /dev/null +++ b/src/test/04-Stress/func-call-8-class-s.ck @@ -0,0 +1,13 @@ +// #2024-func-call-update verification + +0 => int N; + +// test calling member function from within class definition +class Foo +{ + fun static void foo() { N++; bar(); } + fun static void bar() { if( N >= 100000 ) <<< "success" >>>; } +} + +// test for stack overflow +repeat(100000) Foo.foo(); diff --git a/src/test/04-Stress/func-call-9-spork-m.ck b/src/test/04-Stress/func-call-9-spork-m.ck new file mode 100644 index 000000000..5b9ff47bc --- /dev/null +++ b/src/test/04-Stress/func-call-9-spork-m.ck @@ -0,0 +1,13 @@ +// #2024-func-call-update verification + +0 => int N; + +// test spork member function from within class definition +class Foo +{ + fun void foo() { N++; spork ~ bar(); me.yield(); } + fun void bar() { if( N >= 10000 ) <<< "success" >>>; } +} + +// test for stack overflow +repeat(10000) { Foo foo; foo.foo(); } diff --git a/src/test/04-Stress/static-member-access.ck b/src/test/04-Stress/static-member-access.ck new file mode 100644 index 000000000..6ad5bef0e --- /dev/null +++ b/src/test/04-Stress/static-member-access.ck @@ -0,0 +1,16 @@ +// test static non-function members +Math.PI; + +// test for stack overflow +repeat(1000000) Math.PI; + +class Foo +{ + static int bar; +} + +// test for stack overflow +repeat(1000000) Foo.bar; + +// if we get here, ok +<<< "success" >>>;