class Novika::Block
- Novika::Block
- Reference
- Object
Overview
Blocks are fundamental to Novika.
They are a kind of AST node, they hold continuations and are continuations, they are arrays, stacks, and hash tables, all at the same time.
In this sense, blocks have roles. But any block can be any role, and change its role as often and whenever it wants or needs to.
Included Modules
Defined in:
novika/forms/block.crConstant Summary
-
MAX_COUNT_TO_S =
128
-
Maximum amount of forms to display in block string representation.
-
MAX_NESTED_COUNT_TO_S =
12
-
Maximum amount of forms to display in string representation of nested blocks.
Constructors
Class Method Summary
- .typedesc
-
.with(array : Array(Form), leaf : Bool | Nil = nil)
Creates and returns an orphan block with array being its tape substrate's container.
-
.with(form1 : Form, form2 : Form)
Double-form optimized version of
Block.with
. -
.with(form : Form)
Single-form optimized version of
Block.with
.
Instance Method Summary
-
#==(other) : Bool
Loose equality: for two blocks to be loosely equal, their tapes and their dictionaries must be loosely equal.
-
#a(type : T.class, _depth = 0) : T forall T
Converts this block into the given type.
-
#add(form : Form) : self
Adds form to the tape.
-
#at(b : Int32, e : Int32)
Returns a block of forms between b and e, both inclusive.
-
#at(name : Form, entry : Entry) : self
Binds name to entry in this block's dictionary.
-
#at(name : Form, form : Form) : self
Binds name to form in this block's dictionary.
-
#at(index : Int32) : Form
Returns the form at index in the tape.
-
#at(name : String, desc = "a builtin", &code : Engine, Block -> ) : self
Makes an
OpenEntry
called name for code wrapped inBuiltin
. -
#at(name : Word, desc = "a builtin", &code : Engine, Block -> ) : self
Makes an
OpenEntry
called name for code wrapped inBuiltin
. -
#at?(index)
Returns the form at index, or nil.
-
#befriend(other : Block) : self
Adds other to the friendlist of this block.
-
#can_be?(type : T.class) : Bool forall T
Returns whether this block implements hook(s) needed for behaving like type.
-
#clear_entries : self
Removes all owned dictionary entries in this block.
-
#count
Returns the amount of forms in this block.
-
#cursor
Returns the cursor position in this block.
-
#delete_at(index : Int32) : self
Deletes the form at index.
-
#delete_entry(name : Form) : self
Deletes the entry corresponding to name form from the dictionary of this block if it exists there.
-
#delete_if(& : Form -> Bool) : self
Yields forms from left to right until the block returns
true
for one, then deletes that form. -
#desc(io : IO)
Appends a string description of this form to io.
-
#describe_with?(comment : String, force = false) : String | Nil
Sets the block comment of this block to comment in case it doesn't have a comment already.
-
#drop : Form
Removes and returns the top form.
-
#dupe : self
Duplicates the form before the cursor, dies if none.
-
#each(&)
Yields all forms in this block, going from left to right.
-
#each_entry(&)
Yields entry names and
Entry
objects from the dictionary of this block. -
#each_entry_name(&)
Yields entry name forms in this block's dictionary.
-
#each_entry_value(&)
Yields entry value forms in this block's dictionary.
-
#each_friend(&)
Yields friends of this block.
-
#each_neighbor(payload : Block -> T | Nil, visited : BlockIdMap | Nil = nil) forall T
Explores neighbor blocks of this block, calls payload with each such neighbor block.
-
#each_neighbor(visited : BlockIdMap | Nil = nil, &payload : Block -> T | Nil) forall T
Explores neighbor blocks of this block, calls payload with each such neighbor block.
-
#each_occurrence_of(pattern : Form, &)
Yields occurrences of the given pattern found in this block.
-
#each_relative_fetch(fetcher : Block -> T | Nil, seen : BlockIdMap | Nil = nil, skip_self : Bool = false, history : Block | Nil = nil) : T | Nil forall T
Explores this block's relatives, i.e., its vertical (parent) and horizontal (friend) hierarchy, calls fetcher on each relative.
-
#each_relative_fetch(*args, **kwargs, &fetcher : Block -> T | Nil) : T | Nil forall T
Explores this block's relatives, i.e., its vertical (parent) and horizontal (friend) hierarchy, calls fetcher on each relative.
-
#effect(io)
Generates and returns a description for the stack effect of this form.
-
#eject : Form
Drops and returns the form after the cursor.
-
#entry_count
Returns the amount of entries owned by (defined in) this block.
-
#entry_for(name : Form) : Entry
Returns the dictionary entry for name, or dies.
-
#entry_for?(name : Form) : Entry | Nil
Returns the dictionary entry for name, or nil.
-
#flat_at?(name : Form) : Entry | Nil
Returns the dictionary entry corresponding to name.
-
#flat_has?(name : Form) : Bool
Returns whether this block's (and this block's only) dictionary has an entry corresponding to name.
-
#form_for?(name : Form) : Form | Nil
Returns the value form for an entry with the given name, or nil if no such entry exists.
-
#has_comment? : Bool
Returns whether this block has a comment.
-
#has_dict? : Bool
Returns whether this block has a dict.
-
#has_form_for?(name : Form) : Bool
Returns whether this store has an entry with the given name.
-
#has_friends? : Bool
Returns whether this block has any friends.
-
#has_relatives? : Bool
Returns whether this block has a parent, friends, or both.
-
#has_tape? : Bool
Returns whether this block has a tape.
-
#import!(from donor : Block) : self
Imports entries from donor to this block's dictionary by mutating this block's dictionary.
-
#includes?(other : Form) : Bool
Returns whether the tape of this block includes other, as per loose equality
#==(other)
. -
#inject(form : Form) : self
Adds form after the cursor.
-
#instance(parent new_parent : Block = self, shallow = false, __tr : BlockIdMap | Nil = nil) : Block
Creates and returns an instance of this block, under the given parent.
-
#next? : Form | Nil
See
Tape#next?
. -
#on_open(engine : Engine, stack : Block = engine.stack) : self
Schedules this block for execution in engine using the safe scheduling method (see
Engine#schedule
). -
#opener?(name : Form) : Bool
Returns whether name opens its value form, as defined in this store.
-
#parent : Block | Nil
Holds a reference to the parent block (them all in a linked list of ancestors).
-
#parent=(parent : Block | Nil)
Holds a reference to the parent block (them all in a linked list of ancestors).
-
#parent? : Block | Nil | Nil
Holds a reference to the parent block (them all in a linked list of ancestors).
-
#paste(forms : Block)
Mutably adds forms before the cursor in forms block's tape after the cursor in this block's tape.
-
#path_to_entry?(name : Form) : Tuple(Entry, Block) | Nil
Returns a tuple that consists of the dictionary entry corresponding to name, followed by the path block which holds all blocks leading to the entry.
-
#prototype : Block
Returns the prototype of this block.
-
#prototype=(prototype : Block)
Returns the prototype of this block.
-
#prototype? : Block | Nil
Returns the prototype of this block.
-
#pusher?(name : Form) : Bool
Returns whether name pushes its value form, as defined in this store.
-
#resub(other : Block) : self
Replaces this block's tape with other's.
-
#reverse_each(&)
Yields all forms in this block, going from right to left.
-
#schedule(engine : Engine, stack : Block) : self
Schedules an instance of this block for execution, with stack set as the stack that will be used by the instance during execution.
-
#schedule!(engine : Engine, stack : Block) : self
Schedules this block for execution, with stack set as the stack that will be used by this block during execution.
-
#shallow : Block
Returns a shallow copy of this block.
-
#slice : Tuple(Block, Block)
Slices this block at cursor.
-
#slurp(source : String) : self
Parses all forms in string source, and adds them to this block.
-
#sort_using!(&cmp : Form, Form -> Int32) : self
Sorts this block's tape inplace, calls cmp comparator proc for each form pair for a comparison integer -1, 0, or 1.
-
#spot(io, vicinity = 10, colorful = true)
Appends a string representation of this block to io in which only forms in the negative and positive vicinity of this block's cursor are present, and the word before the cursor is emphasized.
-
#submit?(name : Form, form : Form)
Submits value form to an entry with the given name.
-
#swap : self
Swaps two forms before the cursor, dies if none.
-
#thru : Form
Returns form after cursor, and moves cursor past it.
-
#to(index : Int32) : self
Moves tape cursor to index.
-
#to_dict_block : Block
Builds and returns a dictionary block for this block.
-
#to_quote : Quote
Returns this form's quote representation.
- #to_s(io)
-
#to_tape_block : Block
Builds and returns a tape block for this block.
-
#top : Form
Returns the top form, dies if none.
-
#top? : Form | Nil
Returns the top form, or nil if none.
-
#unfriend(other : Block) : self
Removes other from the friendlist of this block.
Instance methods inherited from module Novika::ISubmittableStore
submit(name : Form, form : Form)
submit,
submit?(name : Form, form : Form)
submit?
Class methods inherited from module Novika::ISubmittableStore
typedesc
typedesc
Instance methods inherited from module Novika::IReadableStore
form_for(name : Form) : Form
form_for,
form_for?(name : Form) : Form | Nil
form_for?,
has_form_for?(name : Form) : Bool
has_form_for?,
opener?(name : Form) : Bool
opener?,
pusher?(name : Form) : Bool
pusher?
Class methods inherited from module Novika::IReadableStore
typedesc
typedesc
Instance methods inherited from module Novika::Form
a(type : T.class) : T forall T
a,
desc(io : IO)desc : String desc, die(details : String) die, effect(io)
effect effect, on_open(engine : Engine) : self on_open, on_parent_open(engine : Engine) : self on_parent_open, onto(block : Block) : self onto, sel(a, b) sel, to_quote : Quote to_quote
Instance methods inherited from module Novika::Schedulable
schedule(engine : Engine, stack : Block)
schedule,
schedule!(engine : Engine, stack : Block)
schedule!
Constructor Detail
Class Method Detail
Creates and returns an orphan block with array being
its tape substrate's container. See Tape.for
.
Double-form optimized version of Block.with
.
Instance Method Detail
Loose equality: for two blocks to be loosely equal, their tapes and their dictionaries must be loosely equal.
Supports recursive (reflection) equality, e.g.:
[ ] $: a
a a shove
a first a = "=> true"
Converts this block into the given type. Code execution
may be required, hence the need for engine. If failed,
same as Form#a
.
Returns a block of forms between b and e, both inclusive. Clamps b and e to bounds.
Binds name to entry in this block's dictionary.
Binds name to form in this block's dictionary.
Returns the form at index in the tape. Dies if index
is out of bounds. See Tape#at?
.
Makes an OpenEntry
called name for code wrapped
in Builtin
.
Makes an OpenEntry
called name for code wrapped
in Builtin
.
Returns whether this block implements hook(s) needed
for behaving like type. See also: a(type)
.
Deletes the form at index. Does nothing if index is out of bounds.
Deletes the entry corresponding to name form from the dictionary of this block if it exists there. Otherwise, does nothing.
Yields forms from left to right until the block returns true
for one, then deletes that form. If the block does not return
true
for any form, does nothing.
Appends a string description of this form to io.
Sets the block comment of this block to comment in case it doesn't have a comment already.
Setting the comment can also be forced by making force true.
Yields friends of this block. Asserts each is a block, otherwise, dies (e.g. the user may have mistakenly added some other form).
Explores neighbor blocks of this block, calls payload with each such neighbor block. Records all neighbors it visited in visited.
Explicitly nested (marked as ExN1-2 in the diagram below) neighbor blocks are blocks found in the dictionary and tape of this block (marked as B in the diagram below).
Implicitly nested (marked as ImN1-4 in the diagram below) neighbor blocks are blocks in the tapes and dictionaries of explicitly nested neighbor blocks, and so on, recursively.
┌───────────────────────────────────────┐
│ B │
│ ┌───────────────┐ ┌───────────────┐ │
│ │ ExN1 │ │ ExN2 │ │
│ │ ┌────┐ ┌────┐ │ │ ┌────┐ ┌────┐ │ │
│ │ │ImN1│ │ImN2│ │ │ │ImN3│ │ImN4│ │ │
│ │ └────┘ └────┘ │ │ └────┘ └────┘ │ │
│ │ ... ... │ │ ... ... │ │
│ └───────────────┘ └───────────────┘ │
│ │
└───────────────────────────────────────┘
Explores neighbor blocks of this block, calls payload with each such neighbor block. Records all neighbors it visited in visited.
Explicitly nested (marked as ExN1-2 in the diagram below) neighbor blocks are blocks found in the dictionary and tape of this block (marked as B in the diagram below).
Implicitly nested (marked as ImN1-4 in the diagram below) neighbor blocks are blocks in the tapes and dictionaries of explicitly nested neighbor blocks, and so on, recursively.
┌───────────────────────────────────────┐
│ B │
│ ┌───────────────┐ ┌───────────────┐ │
│ │ ExN1 │ │ ExN2 │ │
│ │ ┌────┐ ┌────┐ │ │ ┌────┐ ┌────┐ │ │
│ │ │ImN1│ │ImN2│ │ │ │ImN3│ │ImN4│ │ │
│ │ └────┘ └────┘ │ │ └────┘ └────┘ │ │
│ │ ... ... │ │ ... ... │ │
│ └───────────────┘ └───────────────┘ │
│ │
└───────────────────────────────────────┘
Yields occurrences of the given pattern found in this
block. Matching is done using loose equality #==(other)
.
Explores this block's relatives, i.e., its vertical (parent) and horizontal (friend) hierarchy, calls fetcher on each relative. This process is also known as the exploration of the block graph, where this block is the origin of exploration.
If fetcher returns a value of type T
(a non-nil) for the given
block, exploration terminates. If fetcher returns nil, exploration
continues.
The order of exploration is roughly as follows:
-
The first echelon is explored: the parents, friends, and friends of parents of this block are explored.
-
The second echelon is explored: the parents, friends, and friends of parents of the blocks in first echelon are explored by recursing on each, effectively allowing lookup that is unlimited in terms of depth.
seen can be used to disable exploration of specific blocks, also blocking off the exploration of their relatives (if they were not otherwise reached already).
skip_self can be set to true to disable calling fetcher for
this block. Note that if this block is reached by other means
(e.g. as in self -- other -- self
), fetcher is still going
to be called.
history, a block, can optionally be provided. It will hold all
explored blocks leading to the "discovery" of T
.
Explores this block's relatives, i.e., its vertical (parent) and horizontal (friend) hierarchy, calls fetcher on each relative. This process is also known as the exploration of the block graph, where this block is the origin of exploration.
If fetcher returns a value of type T
(a non-nil) for the given
block, exploration terminates. If fetcher returns nil, exploration
continues.
The order of exploration is roughly as follows:
-
The first echelon is explored: the parents, friends, and friends of parents of this block are explored.
-
The second echelon is explored: the parents, friends, and friends of parents of the blocks in first echelon are explored by recursing on each, effectively allowing lookup that is unlimited in terms of depth.
seen can be used to disable exploration of specific blocks, also blocking off the exploration of their relatives (if they were not otherwise reached already).
skip_self can be set to true to disable calling fetcher for
this block. Note that if this block is reached by other means
(e.g. as in self -- other -- self
), fetcher is still going
to be called.
history, a block, can optionally be provided. It will hold all
explored blocks leading to the "discovery" of T
.
Generates and returns a description for the stack effect of this form.
For blocks and builtins, tries to extract a ( ... -- ... )
(but see EFFECT_PATTERN
) from their corresponding
comment. If could not extract or no comment, returns
'a block' for blocks and 'native code' for builtins.
Drops and returns the form after the cursor. Dies if cursor is at the end.
Returns the dictionary entry for name, or dies.
See each_relative
for a detailed description of lookup
order etc.
Returns the dictionary entry for name, or nil.
See each_relative
for a detailed description of lookup
order etc.
Returns the dictionary entry corresponding to name. Does not traverse the block hierarchy.
Returns whether this block's (and this block's only) dictionary has an entry corresponding to name.
Returns the value form for an entry with the given name, or nil if no such entry exists.
Returns whether this store has an entry with the given name.
Imports entries from donor to this block's dictionary by mutating this block's dictionary.
Returns whether the tape of this block includes other,
as per loose equality #==(other)
.
Creates and returns an instance of this block, under the given parent.
Schedules this block for execution in engine using the
safe scheduling method (see Engine#schedule
). Optionally,
a stack block may be provided (otherwise, the engine's
current stack is used).
Returns whether name opens its value form, as defined in this store. Dies if name is not defined in this store.
Holds a reference to the parent block (them all in a linked list of ancestors).
Holds a reference to the parent block (them all in a linked list of ancestors).
Holds a reference to the parent block (them all in a linked list of ancestors).
Mutably adds forms before the cursor in forms block's tape after the cursor in this block's tape.
Returns a tuple that consists of the dictionary entry corresponding to name, followed by the path block which holds all blocks leading to the entry.
Returns nil if name could not be found.
In general works like #entry_for
and friends, the only
difference being that it also tracks and returns the path.
The latter makes this method slightly slower that #entry_for
.
Returns the prototype of this block. Block instances return their prototype (AST) blocks, AST blocks return themselves.
Returns the prototype of this block. Block instances return their prototype (AST) blocks, AST blocks return themselves.
Returns the prototype of this block. Block instances return their prototype (AST) blocks, AST blocks return themselves.
Returns whether name pushes its value form, as defined in this store. Dies if name is not defined in this store.
Schedules an instance of this block for execution, with stack set as the stack that will be used by the instance during execution.
Moves the cursor of the instance before the first form so that the entire block will be executed by engine.
Schedules this block for execution, with stack set as the stack that will be used by this block during execution.
Moves the cursor before the first form so that the entire block will be executed by engine.
Slices this block at cursor. This results in two halves, which are consequently returned.
Parses all forms in string source, and adds them to this block.
Sorts this block's tape inplace, calls cmp comparator proc for each form pair for a comparison integer -1, 0, or 1.
Appends a string representation of this block to io in which only forms in the negative and positive vicinity of this block's cursor are present, and the word before the cursor is emphasized.
Does not respect MAX_COUNT_TO_S
. Does not display quotes.
Does not display nested blocks.
Submits value form to an entry with the given name. Returns nil if no such entry exists.
Returns form after cursor, and moves cursor past it.
Similar to #eject
, but doesn't modify the block.
Moves tape cursor to index. Dies if index is out
of bounds. See Tape#to?
.
Builds and returns a dictionary block for this block.
Dictionary block is an orphan block whose dictionary is a shallow copy of this block's dictionary; and whose tape is empty.
Returns this form's quote representation.
Builds and returns a tape block for this block.
Tape block is an orphan block whose tape is a shallow copy of this block's tape; and whose dictionary is empty.