struct Crystal::Repl::Interpreter::CallFrame

Defined in:

compiler/crystal/interpreter/interpreter.cr

Constructors

Instance Method Summary

Instance methods inherited from struct Struct

==(other : YAML::Any)
==(other) : Bool
==
, hash(hasher) hash, inspect(io : IO) : Nil inspect, pretty_print(pp) : Nil pretty_print, to_s(io : IO) : Nil to_s

Class methods inherited from struct Struct

pre_initialize(address : Pointer) : Nil pre_initialize

Instance methods inherited from struct Value

==(other : Log::Metadata::Value)
==(other : JSON::Any)
==(other : YAML::Any)
==(other)
==
, dup dup

Instance methods inherited from class Object

! : Bool !, !=(other) !=, !~(other) !~, ==(other) ==, ===(other : JSON::Any)
===(other : YAML::Any)
===(other)
===
, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash
hash
, in?(collection : Object) : Bool
in?(*values : Object) : Bool
in?
, inspect(io : IO) : Nil
inspect : String
inspect
, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil!(message)
not_nil!
not_nil!
, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO) : Nil
to_json : String
to_json
, to_pretty_json(indent : String = " ") : String
to_pretty_json(io : IO, indent : String = " ") : Nil
to_pretty_json
, to_s(io : IO) : Nil
to_s : String
to_s
, to_yaml(io : IO) : Nil
to_yaml : String
to_yaml
, try(&) try, unsafe_as(type : T.class) forall T unsafe_as

Class methods inherited from class Object

from_json(string_or_io : String | IO, root : String)
from_json(string_or_io : String | IO)
from_json
, from_yaml(string_or_io : String | IO) from_yaml

Macros inherited from class Object

class_getter(*names, &block) class_getter, class_getter!(*names) class_getter!, class_getter?(*names, &block) class_getter?, class_property(*names, &block) class_property, class_property!(*names) class_property!, class_property?(*names, &block) class_property?, class_setter(*names) class_setter, def_clone def_clone, def_equals(*fields) def_equals, def_equals_and_hash(*fields) def_equals_and_hash, def_hash(*fields) def_hash, delegate(*methods, to object) delegate, forward_missing_to(delegate) forward_missing_to, getter(*names, &block) getter, getter!(*names) getter!, getter?(*names, &block) getter?, property(*names, &block) property, property!(*names) property!, property?(*names, &block) property?, setter(*names) setter

Constructor Detail

def self.new(compiled_def : CompiledDef, compiled_block : CompiledBlock | Nil, instructions : CompiledInstructions, ip : Pointer(UInt8), stack : Pointer(UInt8), stack_bottom : Pointer(UInt8), block_caller_frame_index : Int32, real_frame_index : Int32, overflow_offset : Int32) #

[View source]

Instance Method Detail

def block_caller_frame_index : Int32 #

The index of the frame that called a block. This is useful to know because when a yield happens, we more or less create a new stack frame that has the same local variables as this frame, because the block will need to access that frame's variables. It's -1 if the value is not present.


def clone #

[View source]
def compiled_block : CompiledBlock | Nil #

The CompiledBlock related to this call frame, if any


def compiled_def : CompiledDef #

The CompiledDef related to this call frame


def copy_with(compiled_def _compiled_def = @compiled_def, compiled_block _compiled_block = @compiled_block, instructions _instructions = @instructions, ip _ip = @ip, stack _stack = @stack, stack_bottom _stack_bottom = @stack_bottom, block_caller_frame_index _block_caller_frame_index = @block_caller_frame_index, real_frame_index _real_frame_index = @real_frame_index, overflow_offset _overflow_offset = @overflow_offset) #

[View source]
def instructions : CompiledInstructions #

Instructions for this frame


def ip : Pointer(UInt8) #

The pointer to the current instruction for this call frame. This value changes as the program goes, and when a call is made this value is useful to know where we need to continue after the call returns.


def overflow_offset : Int32 #

This is a bit hacky, but... Right now, when we produce an OverflowError we do it directly in the instruction that potentially produces the overflow. When we do that, the backtrace that is produced in that case is incorrect because the backtrace computing logic assumes an all call frames are, well, calls. But in this case it could be an add_i32 instruction which has a different layout. To solve this, we have an optional #overflow_offset that we put on a frame to indicate that the caller frame must add to get the correct backtrace location.


def real_frame_index : Int32 #

When a yield happens we copy the frame pointed by #block_caller_frame_index. If a return happens inside that block we need to return from that frame (the defs one.) With #real_frame_index we know where that frame is actually in the call stack (the original, not the copy) and we can go back to just before that frame when a return happens.


def stack : Pointer(UInt8) #

What's the frame's stack. This value changes as the program goes, and when a call is made this value is useful to know what values in the stack we need to have when the call returns.


def stack_bottom : Pointer(UInt8) #

What's the frame's stack bottom. After this position come the def's local variables.