Skip to content

Commit

Permalink
Add input file contents to traceback (#666)
Browse files Browse the repository at this point in the history
* Start get_traceback_entries + add convenience methos

* Add fn is_call_instruction

* add code

* Refactor code

* Clippy

* Add get_traceback method

* Fix get_error_attr_value

* Add traceback to VmException

* Make traceback non-optional

* Add tests for is_call_instruction

* Add traceback to error display

* Add test + fix logic for get_traceback_entries

* Code refactor

* Add one more test for get_traceback_entries

* Fix string format + add test for get_traceback

* Improve fn

* Add reference to is_call_instruction signature

* Add reference to immediate in decode_instruction + remove clone

* Fix hint_processor mutability in tests

* Add Location::get_location_marks

* Fix method to_string_with_contents

* Fix string format

* Fix string format

* Update traceback tests

* Add tests for Location::to_string_with_contents()

* Fix intermediate string format

* Fix test

* Add tests for Location::get_location_marks()

* Update VmException display

* Fix string format

* Fix string format

* Remove debug print

* Fix Display

* Implement Display for MaybeRelocatable

* Add real-case test for VmException Display

* Remove debug format from erros containing MaybeRelocatable and Relocatable

* Add tests for display implementation

* Update Changelog

* Clippy

* Remove unnecessary &
  • Loading branch information
fmoletta authored Jan 2, 2023
1 parent 5373211 commit c71d95e
Show file tree
Hide file tree
Showing 6 changed files with 280 additions and 31 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@
* `pub fn get_location(pc: &usize, runner: &CairoRunner) -> Option<Location>` is now `pub fn get_location(pc: usize, runner: &CairoRunner) -> Option<Location>`
* `pub fn decode_instruction(encoded_instr: i64, mut imm: Option<BigInt>) -> Result<instruction::Instruction, VirtualMachineError>` is now `pub fn decode_instruction(encoded_instr: i64, mut imm: Option<&BigInt>) -> Result<instruction::Instruction, VirtualMachineError>`
* `VmExcepion` field's string format now mirror their cairo-lang conterparts.

* Add input file contents to traceback [#666](https://github.com/lambdaclass/cairo-rs/pull/666/files)
* Public Api changes:
* `VirtualMachineError` enum variants containing `MaybeRelocatable` and/or `Relocatable` values now use the `Display` format instead of `Debug` in their `Display` implementation
* `get_traceback` now adds the source code line to each traceback entry
25 changes: 25 additions & 0 deletions cairo_programs/bad_programs/bad_range_check.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
%builtins range_check

func check_range{range_check_ptr: felt*}(num: felt) {
with_attr error_message("Failed range-check") {
[range_check_ptr] = num;
}
return();
}

func sub_1_check_range{range_check_ptr: felt*}(num: felt) -> felt {
check_range(num - 1);
return num - 1;
}

func sub_by_1_check_range{range_check_ptr: felt*}(num: felt, sub_amount: felt) {
if (sub_amount == 0) {
return();
}
return sub_by_1_check_range(sub_1_check_range(num), sub_amount -1);
}

func main{range_check_ptr: felt*}() {
sub_by_1_check_range(6, 7);
return ();
}
44 changes: 43 additions & 1 deletion src/types/relocatable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use crate::{
use num_bigint::BigInt;
use num_integer::Integer;
use num_traits::{FromPrimitive, Signed, ToPrimitive};
use std::ops::Add;
use std::{
fmt::{self, Display},
ops::Add,
};

#[derive(Eq, Hash, PartialEq, PartialOrd, Clone, Copy, Debug)]
pub struct Relocatable {
Expand Down Expand Up @@ -64,6 +67,21 @@ impl From<Relocatable> for MaybeRelocatable {
}
}

impl Display for MaybeRelocatable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
MaybeRelocatable::RelocatableValue(rel) => rel.fmt(f),
MaybeRelocatable::Int(num) => write!(f, "{}", num),
}
}
}

impl Display for Relocatable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}:{}", self.segment_index, self.offset)
}
}

impl Add<usize> for Relocatable {
type Output = Relocatable;
fn add(self, other: usize) -> Self {
Expand Down Expand Up @@ -850,4 +868,28 @@ mod tests {
mayberelocatable!(3).get_relocatable()
)
}

#[test]
fn relocatable_display() {
assert_eq!(
format!("{}", Relocatable::from((1, 0))),
String::from("1:0")
)
}

#[test]
fn maybe_relocatable_relocatable_display() {
assert_eq!(
format!("{}", MaybeRelocatable::from((1, 0))),
String::from("1:0")
)
}

#[test]
fn maybe_relocatable_int_display() {
assert_eq!(
format!("{}", MaybeRelocatable::from(bigint!(6))),
String::from("6")
)
}
}
32 changes: 16 additions & 16 deletions src/vm/errors/vm_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ pub enum VirtualMachineError {
UnconstrainedResJumpRel,
#[error("Res.UNCONSTRAINED cannot be used with Opcode.ASSERT_EQ")]
UnconstrainedResAssertEq,
#[error("ASSERT_EQ instruction failed; {0:?} != {1:?}")]
#[error("An ASSERT_EQ instruction failed: {0} != {1}.")]
DiffAssertValues(MaybeRelocatable, MaybeRelocatable),
#[error("Call failed to write return-pc (inconsistent op0): {0:?} != {1:?}. Did you forget to increment ap?")]
#[error("Call failed to write return-pc (inconsistent op0): {0} != {1}. Did you forget to increment ap?")]
CantWriteReturnPc(MaybeRelocatable, MaybeRelocatable),
#[error("Call failed to write return-fp (inconsistent dst): {0:?} != {1:?}. Did you forget to increment ap?")]
#[error("Call failed to write return-fp (inconsistent dst): {0} != {1}. Did you forget to increment ap?")]
CantWriteReturnFp(MaybeRelocatable, MaybeRelocatable),
#[error("Couldn't get or load dst")]
NoDst,
Expand All @@ -50,31 +50,31 @@ pub enum VirtualMachineError {
NotImplemented,
#[error("Can only subtract two relocatable values of the same segment")]
DiffIndexSub,
#[error("Inconsistent auto-deduction for builtin {0}, expected {1:?}, got {2:?}")]
#[error("Inconsistent auto-deduction for builtin {0}, expected {1}, got {2:?}")]
InconsistentAutoDeduction(String, MaybeRelocatable, Option<MaybeRelocatable>),
#[error(transparent)]
RunnerError(#[from] RunnerError),
#[error("Invalid hint encoding at pc: {0:?}")]
#[error("Invalid hint encoding at pc: {0}")]
InvalidHintEncoding(MaybeRelocatable),
#[error(transparent)]
MemoryError(#[from] MemoryError),
#[error("Expected range_check builtin to be present")]
NoRangeCheckBuiltin,
#[error("Expected ecdsa builtin to be present")]
NoSignatureBuiltin,
#[error("Failed to retrieve value from address {0:?}")]
#[error("Failed to retrieve value from address {0}")]
MemoryGet(MaybeRelocatable),
#[error("Expected integer at address {0:?}")]
#[error("Expected integer at address {0}")]
ExpectedInteger(MaybeRelocatable),
#[error("Expected relocatable at address {0:?}")]
#[error("Expected relocatable at address {0}")]
ExpectedRelocatable(MaybeRelocatable),
#[error("Failed to get ids for hint execution")]
FailedToGetIds,
#[error("Assertion failed, {0}, is not less or equal to {1}")]
NonLeFelt(BigInt, BigInt),
#[error("Div out of range: 0 < {0} <= {1}")]
OutOfValidRange(BigInt, BigInt),
#[error("Assertion failed, 0 <= ids.a % PRIME < range_check_builtin.bound \n a = {0:?} is out of range")]
#[error("Assertion failed, 0 <= ids.a % PRIME < range_check_builtin.bound \n a = {0} is out of range")]
ValueOutOfRange(BigInt),
#[error("Value: {0} should be positive")]
ValueNotPositive(BigInt),
Expand All @@ -86,11 +86,11 @@ pub enum VirtualMachineError {
SplitIntNotZero,
#[error("split_int(): Limb {0} is out of range.")]
SplitIntLimbOutOfRange(BigInt),
#[error("Failed to compare {0:?} and {1:?}, cant compare a relocatable to an integer value")]
#[error("Failed to compare {0} and {1}, cant compare a relocatable to an integer value")]
DiffTypeComparison(MaybeRelocatable, MaybeRelocatable),
#[error("assert_not_equal failed: {0:?} = {1:?}")]
#[error("assert_not_equal failed: {0} = {1}")]
AssertNotEqualFail(MaybeRelocatable, MaybeRelocatable),
#[error("Failed to compare {0:?} and {1:?}, cant compare two relocatable values of different segment indexes")]
#[error("Failed to compare {0} and {1}, cant compare two relocatable values of different segment indexes")]
DiffIndexComp(Relocatable, Relocatable),
#[error("Value: {0} is outside of the range [0, 2**250)")]
ValueOutside250BitRange(BigInt),
Expand Down Expand Up @@ -132,7 +132,7 @@ pub enum VirtualMachineError {
NoneApTrackingData,
#[error("Tracking groups should be the same, got {0} and {1}")]
InvalidTrackingGroup(usize, usize),
#[error("Expected relocatable for ap, got {0:?}")]
#[error("Expected relocatable for ap, got {0}")]
InvalidApValue(MaybeRelocatable),
#[error("Dict Error: Tried to create a dict whithout an initial dict")]
NoInitialDict,
Expand Down Expand Up @@ -178,13 +178,13 @@ pub enum VirtualMachineError {
CouldntPopPositions,
#[error("unexpected verify multiplicity fail: last_pos not found")]
LastPosNotFound,
#[error("Set's starting point {0:?} is bigger it's ending point {1:?}")]
#[error("Set's starting point {0} is bigger it's ending point {1}")]
InvalidSetRange(MaybeRelocatable, MaybeRelocatable),
#[error("Failed to construct a fixed size array of size: {0}")]
FixedSizeArrayFail(usize),
#[error("{0}")]
AssertionFailed(String),
#[error("Wrong dict pointer supplied. Got {0:?}, expected {1:?}.")]
#[error("Wrong dict pointer supplied. Got {0}, expected {1}.")]
MismatchedDictPtr(Relocatable, Relocatable),
#[error("Integer must be postive or zero, got: {0}")]
SecpSplitNegative(BigInt),
Expand Down Expand Up @@ -218,7 +218,7 @@ pub enum VirtualMachineError {
NoImm,
#[error("Tried to compute an address but there was no register in the reference.")]
NoRegisterInReference,
#[error("Couldn't compute operand {0} at address {1:?}")]
#[error("Couldn't compute operand {0} at address {1}")]
FailedToComputeOperands(String, Relocatable),
#[error("Custom Hint Error: {0}")]
CustomHint(String),
Expand Down
Loading

0 comments on commit c71d95e

Please sign in to comment.