From 4f27aef0d95d74ddbe4c9c448f75efbd27b233a6 Mon Sep 17 00:00:00 2001 From: Ge Wang Date: Tue, 3 Dec 2024 21:03:04 -0800 Subject: [PATCH] fix accessing local variables decl after funcion that uses the variable --- VERSIONS | 17 ++++++++ src/core/chuck_emit.cpp | 42 ++++++++++++++++--- .../01-Basic/269-foreach-auto-arraylit.ck | 3 ++ .../01-Basic/269-foreach-auto-arraylit.txt | 4 ++ src/test/01-Basic/270-var-func-order.ck | 20 +++++++++ 5 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 src/test/01-Basic/269-foreach-auto-arraylit.ck create mode 100644 src/test/01-Basic/269-foreach-auto-arraylit.txt create mode 100644 src/test/01-Basic/270-var-func-order.ck diff --git a/VERSIONS b/VERSIONS index 98002b237..18589a1f8 100644 --- a/VERSIONS +++ b/VERSIONS @@ -2,6 +2,23 @@ ChucK VERSIONS log ------------------ +1.5.4.4 +======= +(fixed) crash due to functions / classes references a local variable defined + at file-scope; code emission is now internally re-ordered to compile + file-scope code segments -> function definitions -> class definitions +(fixed) foreach `auto` variable typing for multi-dimenion array, e.g., + -------- + // two dim array + for( auto x : [[1,2],[3,4]] ) { + for( auto y : x ) { + // print + <<< y >>>; + } + } + -------- + + 1.5.4.3 (December 2024) ======= new ChuGL v0.2.5 (see ChuGL release notes below) diff --git a/src/core/chuck_emit.cpp b/src/core/chuck_emit.cpp index 70819c03f..dda6cb75a 100644 --- a/src/core/chuck_emit.cpp +++ b/src/core/chuck_emit.cpp @@ -165,7 +165,7 @@ t_CKBOOL emit_engine_shutdown( Chuck_Emitter *& emit ) //----------------------------------------------------------------------------- // name: emit_engine_emit_prog() -// desc: ... +// desc: emit a chuck program/AST into VM bytecode //----------------------------------------------------------------------------- Chuck_VM_Code * emit_engine_emit_prog( Chuck_Emitter * emit, a_Program prog, te_HowMuch how_much ) @@ -208,6 +208,11 @@ Chuck_VM_Code * emit_engine_emit_prog( Chuck_Emitter * emit, a_Program prog, // push global scope (added 1.3.0.0) emit->push_scope(); + // for separating out function defs and class defs | 1.5.4.4 (ge) added + // this is to re-order code emission by stmt_lists -> func defs -> class defs + vector func_defs; + vector class_defs; + // loop over the program sections while( prog && ret ) { @@ -223,17 +228,16 @@ Chuck_VM_Code * emit_engine_emit_prog( Chuck_Emitter * emit, a_Program prog, case ae_section_func: // function definition // check the compilation criteria | 1.5.2.5 (ge) added if( !howMuch_criteria_match( how_much, prog->section->func_def ) ) break; - // check function definition - ret = emit_engine_emit_func_def( emit, prog->section->func_def ); + // add function def for emission + func_defs.push_back( prog->section->func_def ); break; case ae_section_class: // class definition // 1.5.2.5 (ge) check the compilation criteria // if( !howMuch_criteria_match( how_much, prog->section->class_def ) ) break; // 1.5.4.0 (ge) commented out (see type_engine_prog0_scan() for explanation) - - // emit class definition - ret = emit_engine_emit_class_def( emit, prog->section->class_def ); + // add class def for emission + class_defs.push_back( prog->section->class_def ); break; default: // bad @@ -250,6 +254,32 @@ Chuck_VM_Code * emit_engine_emit_prog( Chuck_Emitter * emit, a_Program prog, prog = prog->next; } + // make sure we are good so far + if( ret ) + { + // iterate over func defs + for( size_t i = 0; i < func_defs.size(); i++ ) + { + // check function definition + ret = emit_engine_emit_func_def( emit, func_defs[i] ); + // check success code + if( !ret ) break; + } + } + + // make sure we are good so far + if( ret ) + { + // iterate over func defs + for( size_t i = 0; i < class_defs.size(); i++ ) + { + // emit class definition + ret = emit_engine_emit_class_def( emit, class_defs[i] ); + // check success code + if( !ret ) break; + } + } + // 1.4.1.0 (jack): error-checking: was dac-replacement initted? // (see chuck_compile.h for an explanation on replacement dacs) if( emit->should_replace_dac ) diff --git a/src/test/01-Basic/269-foreach-auto-arraylit.ck b/src/test/01-Basic/269-foreach-auto-arraylit.ck new file mode 100644 index 000000000..8b7e861d1 --- /dev/null +++ b/src/test/01-Basic/269-foreach-auto-arraylit.ck @@ -0,0 +1,3 @@ +for( auto x : [[1,2],[3,4]] ) + for( auto y : x ) + { <<< y >>>; } diff --git a/src/test/01-Basic/269-foreach-auto-arraylit.txt b/src/test/01-Basic/269-foreach-auto-arraylit.txt new file mode 100644 index 000000000..1b5004e9d --- /dev/null +++ b/src/test/01-Basic/269-foreach-auto-arraylit.txt @@ -0,0 +1,4 @@ +1 :(int) +2 :(int) +3 :(int) +4 :(int) diff --git a/src/test/01-Basic/270-var-func-order.ck b/src/test/01-Basic/270-var-func-order.ck new file mode 100644 index 000000000..8789b4bb9 --- /dev/null +++ b/src/test/01-Basic/270-var-func-order.ck @@ -0,0 +1,20 @@ +// test using a local variable declared after a function that uses that variable +// +// added 1.5.4.4; previously this would cause a crash because the emitter +// emitted foo() first, at which point the variable `osc` has not yet received +// it's stack offset, since `SinOsc osc(440);` appears later in the file +// fix: now code emisison is sorted for file-level code, function defs, class +// defs. + +// function def +fun void foo() +{ + // uses `osc` + if( Math.equal(osc.freq(),440) ) <<< "success" >>>; +} + +// osc is declared +SinOsc osc(440); + +// call foo +foo();