Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ModuloByZero exception #472

Merged
merged 3 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions VERSIONS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions src/core/chuck_emit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2633,17 +2633,20 @@ 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
{
switch( left )
{
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;
Expand All @@ -2656,17 +2659,20 @@ 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
{
switch( left )
{
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;
Expand Down
105 changes: 98 additions & 7 deletions src/core/chuck_instr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,27 +294,57 @@ 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 | 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());
goto done;

done:
// do something!
shred->is_running = FALSE;
shred->is_done = TRUE;
}




//-----------------------------------------------------------------------------
// 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 | 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());
goto done;

done:
// do something!
shred->is_running = FALSE;
shred->is_done = TRUE;
}


Expand Down Expand Up @@ -507,27 +537,57 @@ 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 | 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());
goto done;

done:
// do something!
shred->is_running = FALSE;
shred->is_done = TRUE;
}




//-----------------------------------------------------------------------------
// 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;
}


Expand Down Expand Up @@ -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 | 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());
goto done;

done:
// do something!
shred->is_running = FALSE;
shred->is_done = TRUE;
}


Expand Down Expand Up @@ -1388,19 +1463,35 @@ 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 )
{
t_CKFLOAT temp;
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 | 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());
goto done;

done:
// do something!
shred->is_running = FALSE;
shred->is_done = TRUE;
}


Expand Down Expand Up @@ -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;
}
Expand Down
4 changes: 4 additions & 0 deletions src/test/01-Basic/254-modulo-0-float-assign.ck
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
0 => float a;
1 => float b;

a %=> b;
1 change: 1 addition & 0 deletions src/test/01-Basic/254-modulo-0-float-assign.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[chuck]:(EXCEPTION) ModuloByZero: on line[4] in shred[id=1:01-Basic/254-modulo-0-float-assign.ck]
1 change: 1 addition & 0 deletions src/test/01-Basic/254-modulo-0-float.ck
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.0 % 0.0;
1 change: 1 addition & 0 deletions src/test/01-Basic/254-modulo-0-float.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[chuck]:(EXCEPTION) ModuloByZero: on line[1] in shred[id=1:01-Basic/254-modulo-0-float.ck]
4 changes: 4 additions & 0 deletions src/test/01-Basic/254-modulo-0-int-assign.ck
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
0 => int a;
1 => int b;

a %=> b;
1 change: 1 addition & 0 deletions src/test/01-Basic/254-modulo-0-int-assign.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[chuck]:(EXCEPTION) ModuloByZero: on line[4] in shred[id=1:01-Basic/254-modulo-0-int-assign.ck]
1 change: 1 addition & 0 deletions src/test/01-Basic/254-modulo-0-int.ck
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1 % 0;
1 change: 1 addition & 0 deletions src/test/01-Basic/254-modulo-0-int.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[chuck]:(EXCEPTION) ModuloByZero: on line[1] in shred[id=1:01-Basic/254-modulo-0-int.ck]
Loading