From 8f6c232b42dd08ffeff8a4867c89b7d86a5efc08 Mon Sep 17 00:00:00 2001 From: nshaheed Date: Mon, 28 Oct 2024 19:41:44 -0700 Subject: [PATCH 1/3] add ModuloByZero exception --- src/core/chuck_instr.cpp | 105 ++++++++++++++++-- .../01-Basic/254-modulo-0-float-assign.ck | 4 + .../01-Basic/254-modulo-0-float-assign.txt | 1 + src/test/01-Basic/254-modulo-0-float.ck | 1 + src/test/01-Basic/254-modulo-0-float.txt | 1 + src/test/01-Basic/254-modulo-0-int-assign.ck | 4 + src/test/01-Basic/254-modulo-0-int-assign.txt | 1 + src/test/01-Basic/254-modulo-0-int.ck | 1 + src/test/01-Basic/254-modulo-0-int.txt | 1 + 9 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 src/test/01-Basic/254-modulo-0-float-assign.ck create mode 100644 src/test/01-Basic/254-modulo-0-float-assign.txt create mode 100644 src/test/01-Basic/254-modulo-0-float.ck create mode 100644 src/test/01-Basic/254-modulo-0-float.txt create mode 100644 src/test/01-Basic/254-modulo-0-int-assign.ck create mode 100644 src/test/01-Basic/254-modulo-0-int-assign.txt create mode 100644 src/test/01-Basic/254-modulo-0-int.ck create mode 100644 src/test/01-Basic/254-modulo-0-int.txt diff --git a/src/core/chuck_instr.cpp b/src/core/chuck_instr.cpp index 5f11bb32c..0747395ec 100644 --- a/src/core/chuck_instr.cpp +++ b/src/core/chuck_instr.cpp @@ -294,13 +294,28 @@ void Chuck_Instr_Complement_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred //----------------------------------------------------------------------------- // name: execute() -// desc: ... +// desc: module two ints //----------------------------------------------------------------------------- void Chuck_Instr_Mod_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); + if( val_(sp+1) == 0 ) goto mod_zero; push_( sp, val_(sp) % val_(sp+1) ); + + return; + + mod_zero: + // we have a problem + EM_exception( + "ModuloByZero: on line[%lu] in shred[id=%lu:%s]", + m_linepos, shred->xid, shred->name.c_str()); + goto done; + + done: + // do something! + shred->is_running = FALSE; + shred->is_done = TRUE; } @@ -308,13 +323,28 @@ void Chuck_Instr_Mod_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) //----------------------------------------------------------------------------- // name: execute() -// desc: ... +// desc: module two ints (in reverse) //----------------------------------------------------------------------------- void Chuck_Instr_Mod_int_Reverse::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); + if( val_(sp) == 0 ) goto mod_zero; push_( sp, val_(sp+1) % val_(sp) ); + + return; + + mod_zero: + // we have a problem + EM_exception( + "ModuloByZero: on line[%lu] in shred[id=%lu:%s]", + m_linepos, shred->xid, shred->name.c_str()); + goto done; + + done: + // do something! + shred->is_running = FALSE; + shred->is_done = TRUE; } @@ -507,13 +537,28 @@ void Chuck_Instr_Divide_double_Reverse::execute( Chuck_VM * vm, Chuck_VM_Shred * //----------------------------------------------------------------------------- // name: execute() -// desc: ... +// desc: modulo two floats //----------------------------------------------------------------------------- void Chuck_Instr_Mod_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; pop_( sp, 2 ); + if( val_(sp+1) == 0 ) goto mod_zero; push_( sp, ::fmod( val_(sp), val_(sp+1) ) ); + + return; + + mod_zero: + // we have a problem + EM_exception( + "ModuloByZero: on line[%lu] in shred[id=%lu:%s]", + m_linepos, shred->xid, shred->name.c_str()); + goto done; + + done: + // do something! + shred->is_running = FALSE; + shred->is_done = TRUE; } @@ -521,13 +566,28 @@ void Chuck_Instr_Mod_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) //----------------------------------------------------------------------------- // name: execute() -// desc: ... +// desc: modulo two floats (in reverse) //----------------------------------------------------------------------------- void Chuck_Instr_Mod_double_Reverse::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; pop_( sp, 2 ); + if( val_(sp) == 0 ) goto mod_zero; push_( sp, ::fmod( val_(sp+1), val_(sp) ) ); + + return; + + mod_zero: + // we have a problem + EM_exception( + "ModuloByZero: on line[%lu] in shred[id=%lu:%s]", + m_linepos, shred->xid, shred->name.c_str()); + goto done; + + done: + // do something! + shred->is_running = FALSE; + shred->is_done = TRUE; } @@ -1239,14 +1299,29 @@ void Chuck_Instr_Add_int_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred //----------------------------------------------------------------------------- // name: execute() -// desc: ... +// desc: modulo assign two ints //----------------------------------------------------------------------------- void Chuck_Instr_Mod_int_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT temp, *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); + if( val_(sp) == 0 ) goto mod_zero; temp = **(t_CKINT **)(sp+1) %= val_(sp); push_( sp, temp ); + + return; + + mod_zero: + // we have a problem + EM_exception( + "ModuloByZero: on line[%lu] in shred[id=%lu:%s]", + m_linepos, shred->xid, shred->name.c_str()); + goto done; + + done: + // do something! + shred->is_running = FALSE; + shred->is_done = TRUE; } @@ -1388,7 +1463,7 @@ void Chuck_Instr_Divide_double_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * //----------------------------------------------------------------------------- // name: execute() -// desc: ... +// desc: modulo assign two doubles //----------------------------------------------------------------------------- void Chuck_Instr_Mod_double_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { @@ -1396,11 +1471,27 @@ void Chuck_Instr_Mod_double_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shr t_CKBYTE *& sp = (t_CKBYTE *&)shred->reg->sp; // pop value + pointer pop_( sp, sz_FLOAT + sz_UINT ); + + if( val_((t_CKFLOAT *&)sp) == 0 ) goto mod_zero; // assign temp = ::fmod( **(t_CKFLOAT **)(sp+sz_FLOAT), val_((t_CKFLOAT *&)sp) ); **(t_CKFLOAT **)(sp+sz_FLOAT) = temp; // push result push_( (t_CKFLOAT *&)sp, temp ); + + return; + + mod_zero: + // we have a problem + EM_exception( + "ModuloByZero: on line[%lu] in shred[id=%lu:%s]", + m_linepos, shred->xid, shred->name.c_str()); + goto done; + + done: + // do something! + shred->is_running = FALSE; + shred->is_done = TRUE; } @@ -8719,7 +8810,7 @@ void Chuck_Instr_ForEach_Inc_And_Branch::execute( Chuck_VM * vm, Chuck_VM_Shred if( arr->contains_objects() && *pVar) { // add ref, as this will be cleaned up at end of scope, hopefully - ((Chuck_VM_Object *)(*pVar))->add_ref(); + ((Chuck_VM_Object *)(*pVar))->add_ref(); } break; } diff --git a/src/test/01-Basic/254-modulo-0-float-assign.ck b/src/test/01-Basic/254-modulo-0-float-assign.ck new file mode 100644 index 000000000..eeb54a86d --- /dev/null +++ b/src/test/01-Basic/254-modulo-0-float-assign.ck @@ -0,0 +1,4 @@ +0 => float a; +1 => float b; + +a %=> b; diff --git a/src/test/01-Basic/254-modulo-0-float-assign.txt b/src/test/01-Basic/254-modulo-0-float-assign.txt new file mode 100644 index 000000000..098f67aec --- /dev/null +++ b/src/test/01-Basic/254-modulo-0-float-assign.txt @@ -0,0 +1 @@ +[chuck]:(EXCEPTION) ModuloByZero: on line[4] in shred[id=1:01-Basic/254-modulo-0-float-assign.ck] diff --git a/src/test/01-Basic/254-modulo-0-float.ck b/src/test/01-Basic/254-modulo-0-float.ck new file mode 100644 index 000000000..257f5aada --- /dev/null +++ b/src/test/01-Basic/254-modulo-0-float.ck @@ -0,0 +1 @@ +1.0 % 0.0; diff --git a/src/test/01-Basic/254-modulo-0-float.txt b/src/test/01-Basic/254-modulo-0-float.txt new file mode 100644 index 000000000..1b93d74ac --- /dev/null +++ b/src/test/01-Basic/254-modulo-0-float.txt @@ -0,0 +1 @@ +[chuck]:(EXCEPTION) ModuloByZero: on line[1] in shred[id=1:01-Basic/254-modulo-0-float.ck] diff --git a/src/test/01-Basic/254-modulo-0-int-assign.ck b/src/test/01-Basic/254-modulo-0-int-assign.ck new file mode 100644 index 000000000..40edd29e1 --- /dev/null +++ b/src/test/01-Basic/254-modulo-0-int-assign.ck @@ -0,0 +1,4 @@ +0 => int a; +1 => int b; + +a %=> b; diff --git a/src/test/01-Basic/254-modulo-0-int-assign.txt b/src/test/01-Basic/254-modulo-0-int-assign.txt new file mode 100644 index 000000000..505f25b99 --- /dev/null +++ b/src/test/01-Basic/254-modulo-0-int-assign.txt @@ -0,0 +1 @@ +[chuck]:(EXCEPTION) ModuloByZero: on line[4] in shred[id=1:01-Basic/254-modulo-0-int-assign.ck] diff --git a/src/test/01-Basic/254-modulo-0-int.ck b/src/test/01-Basic/254-modulo-0-int.ck new file mode 100644 index 000000000..85ed31b2f --- /dev/null +++ b/src/test/01-Basic/254-modulo-0-int.ck @@ -0,0 +1 @@ +1 % 0; diff --git a/src/test/01-Basic/254-modulo-0-int.txt b/src/test/01-Basic/254-modulo-0-int.txt new file mode 100644 index 000000000..b1670606e --- /dev/null +++ b/src/test/01-Basic/254-modulo-0-int.txt @@ -0,0 +1 @@ +[chuck]:(EXCEPTION) ModuloByZero: on line[1] in shred[id=1:01-Basic/254-modulo-0-int.ck] From 36f8f738f998540fad8738645abba3b0949079c5 Mon Sep 17 00:00:00 2001 From: Ge Wang Date: Mon, 28 Oct 2024 20:01:49 -0700 Subject: [PATCH 2/3] add line number to mod instructions for exception reporting --- src/core/chuck_emit.cpp | 6 ++++++ src/core/chuck_instr.cpp | 10 +++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/core/chuck_emit.cpp b/src/core/chuck_emit.cpp index eba94ec21..d8f41fe07 100644 --- a/src/core/chuck_emit.cpp +++ b/src/core/chuck_emit.cpp @@ -2633,6 +2633,7 @@ t_CKBOOL emit_engine_emit_op( Chuck_Emitter * emit, ae_Operator op, a_Exp lhs, a if( ( left == te_time && right == te_dur ) ) // time % dur = dur { emit->append( instr = new Chuck_Instr_Mod_double ); + instr->set_linepos( rhs->line ); } else // other types { @@ -2640,10 +2641,12 @@ t_CKBOOL emit_engine_emit_op( Chuck_Emitter * emit, ae_Operator op, a_Exp lhs, a { case te_int: emit->append( instr = new Chuck_Instr_Mod_int ); + instr->set_linepos( rhs->line ); break; case te_float: case te_dur: emit->append( instr = new Chuck_Instr_Mod_double ); + instr->set_linepos( rhs->line ); break; default: break; @@ -2656,6 +2659,7 @@ t_CKBOOL emit_engine_emit_op( Chuck_Emitter * emit, ae_Operator op, a_Exp lhs, a if( ( left == te_dur && right == te_time ) ) // time % dur = dur { emit->append( instr = new Chuck_Instr_Mod_double_Assign ); + instr->set_linepos( lhs->line ); } else // other types { @@ -2663,10 +2667,12 @@ t_CKBOOL emit_engine_emit_op( Chuck_Emitter * emit, ae_Operator op, a_Exp lhs, a { case te_int: emit->append( instr = new Chuck_Instr_Mod_int_Assign ); + instr->set_linepos( lhs->line ); break; case te_float: case te_dur: emit->append( instr = new Chuck_Instr_Mod_double_Assign ); + instr->set_linepos( lhs->line ); break; default: break; diff --git a/src/core/chuck_instr.cpp b/src/core/chuck_instr.cpp index 0747395ec..19782eab4 100644 --- a/src/core/chuck_instr.cpp +++ b/src/core/chuck_instr.cpp @@ -306,7 +306,7 @@ void Chuck_Instr_Mod_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) return; mod_zero: - // we have a problem + // we have a problem | 1.5.4.0 (nshaheed) throw exception EM_exception( "ModuloByZero: on line[%lu] in shred[id=%lu:%s]", m_linepos, shred->xid, shred->name.c_str()); @@ -335,7 +335,7 @@ void Chuck_Instr_Mod_int_Reverse::execute( Chuck_VM * vm, Chuck_VM_Shred * shred return; mod_zero: - // we have a problem + // we have a problem | 1.5.4.0 (nshaheed) throw exception EM_exception( "ModuloByZero: on line[%lu] in shred[id=%lu:%s]", m_linepos, shred->xid, shred->name.c_str()); @@ -549,7 +549,7 @@ void Chuck_Instr_Mod_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) return; mod_zero: - // we have a problem + // we have a problem | 1.5.4.0 (nshaheed) throw exception EM_exception( "ModuloByZero: on line[%lu] in shred[id=%lu:%s]", m_linepos, shred->xid, shred->name.c_str()); @@ -1312,7 +1312,7 @@ void Chuck_Instr_Mod_int_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred return; mod_zero: - // we have a problem + // we have a problem | 1.5.4.0 (nshaheed) throw exception EM_exception( "ModuloByZero: on line[%lu] in shred[id=%lu:%s]", m_linepos, shred->xid, shred->name.c_str()); @@ -1482,7 +1482,7 @@ void Chuck_Instr_Mod_double_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shr return; mod_zero: - // we have a problem + // we have a problem | 1.5.4.0 (nshaheed) throw exception EM_exception( "ModuloByZero: on line[%lu] in shred[id=%lu:%s]", m_linepos, shred->xid, shred->name.c_str()); From 3acdddc9cece028415d26b434b09892383aac47b Mon Sep 17 00:00:00 2001 From: Ge Wang Date: Mon, 28 Oct 2024 20:23:47 -0700 Subject: [PATCH 3/3] update release notes for modulo by zero --- VERSIONS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/VERSIONS b/VERSIONS index 4c916fffc..05ce42705 100644 --- a/VERSIONS +++ b/VERSIONS @@ -51,6 +51,8 @@ ChucK VERSIONS log are distinguished from windows drive letters (e.g., "A:\") - (fixed) Type.of() now reports more specific array type (e.g., `string[]`) instead of generic `@array` +- (fixed) modulo `%` by zero (int or float) now throws an exception; previously this would + either produce an incorrect result or cause a crash - (updated) .sort() a string array will now sort alphabetically (instead of by Object refs) - (updated, internal) dynamic array types are now cached and reused, preventing potential memory build-up across compilations