package vm import ( "errors" "fmt" "jinx/pkg/lang/vm/code" "jinx/pkg/lang/vm/mem" "jinx/pkg/lang/vm/text" "jinx/pkg/lang/vm/value" ) type Error struct { Pc int Line int Err error } func (e Error) Error() string { if e.Line == -1 { return fmt.Sprintf("vm error at pc %d, unknown line: %v", e.Pc, e.Err) } return fmt.Sprintf("vm error at pc %d, line %d: %v", e.Pc, e.Line, e.Err) } // Fatal errors var ( ErrStackOverflow = errors.New("stack overflow (max depth: 1000)") ErrStackUnderflow = errors.New("local stack underflow") ErrReachedMaxCallDepth = errors.New("reached max call depth (max depth: 1000)") ErrReachedRootCallFrame = errors.New("reached root call frame") ErrCallBaseCantBeNegative = errors.New("call base cannot be negative") ErrEnvNotSet = errors.New("env not set") ) type ErrLocalIndexOutOfBounds struct { Index int Len int } func (e ErrLocalIndexOutOfBounds) Error() string { return fmt.Sprintf("local index out of bounds: %d (len: %d)", e.Index, e.Len) } type ErrStackIndexOutOfBounds struct { Index int Len int } func (e ErrStackIndexOutOfBounds) Error() string { return fmt.Sprintf("stack index out of bounds: %d (len: %d)", e.Index, e.Len) } type ErrInvalidOp struct { Op uint8 } func (e ErrInvalidOp) Error() string { return fmt.Sprintf("invalid opcode: %d", e.Op) } type ErrUnexpectedMemCell struct { Ptr mem.Ptr Expected mem.CellKind Got mem.CellKind } func (e ErrUnexpectedMemCell) Error() string { return fmt.Sprintf("unexpected memory cell at %s: expected %v, got %v", e.Ptr.String(), e.Expected, e.Got) } type ErrMemNilCell struct { Ptr mem.Ptr } func (e ErrMemNilCell) Error() string { return fmt.Sprintf("found no value at %s", e.Ptr.String()) } type ErrCorruptedMemCell struct { Ptr mem.Ptr } func (e ErrCorruptedMemCell) Error() string { return fmt.Sprintf("corrupted memory cell at %s", e.Ptr.String()) } // Non-fatal errors, which will later be implemented as catchable exceptions type ErrInvalidOperandType struct { Op code.Op X value.Type } func (e ErrInvalidOperandType) Error() string { return fmt.Sprintf("invalid operand type for op %s: %v", text.OpToString(e.Op), e.X) } type ErrInvalidOperandTypes struct { Op code.Op X value.Type Y value.Type } func (e ErrInvalidOperandTypes) Error() string { return fmt.Sprintf("invalid operand types for op %s: %v, %v", text.OpToString(e.Op), e.X, e.Y) } type ErrArrayIndexOutOfBounds struct { Index int Len int } func (e ErrArrayIndexOutOfBounds) Error() string { return fmt.Sprintf("array index out of bounds: %d (len: %d)", e.Index, e.Len) }