class XfOOrth::VirtualMachine
The virtual machine is the heart of the fOOrth language system that is used to facilitate the stack oriented processing of data and language elements.
-
fOOrth.rb - Version info lives here.
-
compiler.rb - The compiler service of the virtual machine.
-
compiler/cast.rb - Support for casting methods to alternate routings.
-
modes.rb - The control of the various compiler modes.
-
compiler/modes/compiled.rb - The control of the compiled system mode.
-
compiler/modes/deferred.rb - The control of the deferred compiler mode.
-
compiler/modes/delayed.rb - The delayed compile system mode.
-
compiler/modes/nested.rb - The control of the nested compiler modes.
-
compiler/modes/suspend.rb - The ability to suspend buffered mode.
-
compiler/process.rb - Process source code from a code source.
-
compiler/process/generate.rb - Generate the Ruby object code.
-
compiler/process/get_token.rb - Get a complete language element.
-
compiler/process/procedure.rb - Get an embedded procedure literal.
-
compiler/process/string.rb - Get an embedded string literal.
-
core/virtual_machine.rb - The core connection to the virtual machine.
-
debug/dbg_puts.rb - Display diagnostic/debug information if enabled.
-
debug/display_abort.rb - Display diagnostic information on an error.
-
initialize.rb - The initialize method for the virtual machine
-
interpreter.rb - The run time interpreter portion of the fOOrth language system.
-
interpreter/add_to_hash.rb - The fOOrth language hash literal support module.
-
interpreter/data_stack.rb - The fOOrth language system data stack.
-
interpreter/do_loop.rb - The fOOrth language do loop support module.
-
interpreter/squash.rb - The fOOrth language do loop support module.
Alias support methods in the VirtualMachine
class.
-
library/introspection/vm.rb - Virtual Machine support for introspection.
Stub support methods in the VirtualMachine
class.
Constants
- ALLOWED_ALIAS_TYPES
- PROC_VAL
The procedure used for procedure instance values
- PROC_VAR
The procedure used for procedure instance variables
Attributes
The current execution/compile context.
The thread data associated with this virtual machine.
The fOOrth data stack. This is the primary means used to hold data for processing.
Set true for verbose compiler play-by-plays and detailed error reports.
The currently active fiber, if any.
The descriptive name of this virtual machine.
The level of comment nesting.
The current compiler parser.
The level of quote nesting.
Set true to print out the data stack after every interactive line is processed.
The fOOrth timer anchor point. Used to assist in benchmarking etc.
Public Class Methods
Create a new fOOrth subclass of this class. This is not allowed for the VirtualMachine
class so this stub merely raises an exception.
# File lib/fOOrth/core/virtual_machine.rb, line 21 def create_foorth_subclass(_name) error "F13: Forbidden operation: VirtualMachine .class: " end
Create an new instance of a fOOrth virtual machine
Parameters:
-
name - An optional string that describes this virtual machine instance.
Note
-
A
XfOOrthError
will be raised if an attempt is made to create more than one virtual machine on a thread.
# File lib/fOOrth/initialize.rb, line 38 def initialize(name='-') @name, @debug, @show_stack, @data = name, false, false, {} #Bring the major sub-systems to a known state. self.reset.connect_vm_to_thread end
Get or create a virtual machine for this thread.
Paramters:
-
name - The name of the virtual machine, if one is created. If a virtual machine already exists for this thread, this parameter is ignored.
Note: Non-intuitive code.
-
VitualMachine.new connects to the thread, setting up Thread.current[:vm] as a side-effect. Thus it is not done here.
# File lib/fOOrth/initialize.rb, line 16 def self.vm(name='-') Thread.current[:vm] || VirtualMachine.new(name) end
Public Instance Methods
Append text to the compile buffer.
# File lib/fOOrth/compiler.rb, line 48 def <<(text) dbg_puts " Append=#{text.inspect}" @buffer << text rescue NoMethodError error "F14: The current mode does not allow code to be appended." end
Add the key and value to the hash being constructed.
# File lib/fOOrth/interpreter/add_to_hash.rb, line 10 def add_to_hash key, value = popm(2) peek(1)[key] = value end
Start compiling a fOOrth definition. This is used to get things going by the various compiling words like ':', '::', ':::', etc.
Parameters:
-
ctrl - The control symbol that started the compilation.
-
action - A block to be executed when the compilation is done.
Note:
-
Adds a nested context level to be un-nested at a later point.
# File lib/fOOrth/compiler/modes/compiled.rb, line 15 def begin_compile_mode(ctrl, defs={}, &action) dbg_puts " begin_compile_mode" @context.check_set(:mode, [:execute]) @context = Context.new(@context, mode: :compile, ctrl: ctrl, action: action) @context.merge(defs) @buffer = '' end
Is the buffer valid?
# File lib/fOOrth/compiler.rb, line 56 def buffer_valid? @buffer.is_a?(String) end
Verify the deferred execution state. This are used by words that work within a word grouping like else or while.
Parameters:
-
text - Some text to append to the buffer before bundling it up.
-
ctrls - An array of control symbols that could have started the deferral.
# File lib/fOOrth/compiler/modes/deferred.rb, line 35 def check_deferred_mode(text, ctrls) @context.check_set(:ctrl, ctrls) self << text end
Clear the method cast
# File lib/fOOrth/compiler/cast.rb, line 16 def clear_cast @cast = nil end
Return the compiler to a known state.
# File lib/fOOrth/compiler.rb, line 39 def compiler_reset @buffer = @parser = nil @quotes = @parens = 0 clear_cast @context = Context.new(nil, vm: self, mode: :execute) self end
Connect the vm to a thread variable.
# File lib/fOOrth/initialize.rb, line 70 def connect_vm_to_thread #Check for duplicates. current = Thread.current error "F91: Only one virtual machine allowed per thread" if current[:vm] #This virtual machine is associated with this thread. current[:vm] = self @start_time = Time.now self end
The current system console object. Gets the current console object only creating one if somebody asks for one.
Note
-
This is to be the sole occurrence of @_private_console
# File lib/fOOrth/compiler.rb, line 22 def console @_private_console ||= Console.new end
Create an exclusive method alias
# File lib/fOOrth/library/alias_library.rb, line 62 def create_exclusive_alias(new_name) old_name, target = popm(2) old_spec = get_old_exclusive_spec(target, old_name) target.create_exclusive_method(new_name, get_alias_type(old_spec, new_name), old_spec.tags, &old_spec.does) clear_cast end
Create an exclusive method stub
# File lib/fOOrth/library/stubs_library.rb, line 39 def create_exclusive_stub(name) target = pop type = XfOOrth.name_to_type(name, self) XfOOrth.validate_type(self, type, name) target.create_exclusive_method(name, type, [:stub]) clear_cast end
Create a virtual machine word method alias.
# File lib/fOOrth/library/alias_library.rb, line 33 def create_word_alias(new_name) old_name, target = pop, self.class old_spec = get_old_shared_spec(target, old_name) target.create_shared_method(new_name, old_spec.class, old_spec.tags, &old_spec.does) end
Send out debug info to the fOOrth debug port if debug is enabled.
# File lib/fOOrth/debug/dbg_puts.rb, line 10 def dbg_puts(*args) $foorth_dbg.puts(*args) if debug end
Enter a delayed compile mode in which compilation is delayed till a later time.
# File lib/fOOrth/compiler/modes/delayed.rb, line 10 def delayed_compile_mode(start) dbg_puts " begin_delayed_compile_mode" buffer = do_delayed_compile_mode(start) dbg_puts " Append=#{buffer}" @buffer << buffer dbg_puts " end_delayed_compile_mode" end
Display the diagnostic data required for a language abort error.
Parameters:
-
exception - The exception object that required the system abort or a string describing the error that was encountered.
# File lib/fOOrth/debug/display_abort.rb, line 13 def display_abort(exception) puts "\n#{exception.foorth_message}" if debug puts "Data Stack Contents: #{data_stack.inspect}" puts "\nInternal Backtrace Dump:" puts puts exception.backtrace puts end reset end
The worker bee for delayed_compile_mode.
Endemic Code Smells
-
:reek:FeatureEnvy – false positive
# File lib/fOOrth/compiler/modes/delayed.rb, line 23 def do_delayed_compile_mode(start) buffer, depth = start + ' ', 1 while depth > 0 if (word = parser.get_word_or_string) buffer << word + ' ' depth += 1 if [':', '!:', '.:', '.::'].include?(word) depth -= 1 if word == ';' else error "F12: Error, Invalid compile nesting." end end "vm.process_string(#{buffer.foorth_embed}); " end
Finish compiling a fOOrth definition. This is used to wrap things up, mostly by the semi-colon ';' word.
Parameters:
-
ctrls - an array of the allowed set of control values.
Returns:
-
The value of the action block.
Note:
-
Un-nests a context level.
# File lib/fOOrth/compiler/modes/compiled.rb, line 31 def end_compile_mode(ctrls) @context.check_set(:ctrl, ctrls) source, @buffer = "lambda {|vm| #{@buffer} }", nil result = instance_exec(self, source, @context.tags, &@context[:action]) @context = @context.previous dbg_puts " end_compile_mode" result end
Check to see if the virtual machine is in execute mode.
# File lib/fOOrth/compiler/modes.rb, line 27 def execute_mode? @context[:mode] == :execute end
Create a copy of a donor vm instance.
Parameters:
-
name - An optional string that describes this virtual machine instance.
# File lib/fOOrth/initialize.rb, line 48 def foorth_copy(name) copy = self.clone copy.reinitialize(name) copy end
The name of the virtual machine instance
# File lib/fOOrth/core/virtual_machine.rb, line 10 def foorth_name "#{self.class.foorth_name} instance <#{@name}>" end
Finally generate some code!
Parameters:
-
token - The token to receive the generated code.
-
word - The text of the word.
# File lib/fOOrth/compiler/process/generate.rb, line 13 def generate_code(token, word) if (spec = @context.map_with_defaults(word)) token.add(spec.builds, spec.tags) elsif (value = word.to_foorth_n) token.add("vm.push(#{value.foorth_embed}); ", [:numeric]) else error "F10: ?#{word}?" end end
Get the method cast and clear it.
# File lib/fOOrth/compiler/cast.rb, line 33 def get_cast @cast end
Get introspection info.
# File lib/fOOrth/library/introspection/vm.rb, line 10 def get_info results = get_basic_vm_info get_instance_variable_info(results) get_vm_thread_data_info(results) get_exclusive_method_info(results, "Exclusive") results end
Get the next token structure from the source code or nil if none can be found.
Returns
-
A
Token
structure or nil.
# File lib/fOOrth/compiler/process/get_token.rb, line 13 def get_token return nil unless (word = parser.get_word) token = Token.new string_parms(token, word) || procedure_parms(token, word) generate_code(token, word) token end
Reset the state of the fOOrth inner interpreter.
# File lib/fOOrth/interpreter.rb, line 18 def interpreter_reset @data_stack = Array.new self end
Enter a nested context without altering the current mode.
Parameters:
-
text - Some text to append associated with the nested state.
-
ctrl - The control symbol that started the nested context.
Note:
-
Adds a nested context level to be un-nested at a later point.
# File lib/fOOrth/compiler/modes/nested.rb, line 14 def nest_mode(text, ctrl) dbg_puts " nest_context" @context = Context.new(@context, ctrl: ctrl) process_text(text) end
Read an entry from the data stack without modify that stack.
Parameters:
-
index - The (optional) entry to be retrieved. 1 corresponds to the “top” of the stack, 2 the next element, etc. This parameter defaults to 1.
Returns:
-
The element specified from the data stack.
Note:
-
Attempting to access an element deeper than the number of elements on the stack will fail with an
XfOOrthError
exception.
# File lib/fOOrth/interpreter/data_stack.rb, line 72 def peek(index=1) unless @data_stack.length >= index && index > 0 error "F30: Data Stack Underflow: peek" end @data_stack[-index] end
Read an entry from the data stack as a boolean without modify that stack.
Parameters:
-
index - The (optional) entry to be retrieved. 1 corresponds to the “top” of the stack, 2 the next element, etc. This parameter defaults to 1.
Returns:
-
The element specified from the data stack as a boolean.
Note:
-
Attempting to access an element deeper than the number of elements on the stack will fail with an
XfOOrthError
exception.
# File lib/fOOrth/interpreter/data_stack.rb, line 99 def peek?(index=1) peek(index).to_foorth_b end
Overwrite the TOS with the supplied data.
Parameters:
-
datum - The data to be placed in the data stack.
Note:
-
Attempting to poke an empty stack will fail with an
XfOOrthError
exception.
# File lib/fOOrth/interpreter/data_stack.rb, line 85 def poke(datum) error "F30: Data Stack Underflow: poke" if @data_stack.empty? @data_stack[-1] = datum end
Remove the “top” entry from the data stack.
Returns:
-
The “top” element of the data stack.
Note:
-
If the stack is empty this will raise an
XfOOrthError
exception.
# File lib/fOOrth/interpreter/data_stack.rb, line 31 def pop error "F30: Data Stack Underflow: pop" if @data_stack.empty? @data_stack.pop end
Remove the “top” entry from the data stack as a boolean.
Returns:
-
The “top” element of the data stack as a boolean
Note:
-
If the stack is empty this will raise an
XfOOrthError
exception.
# File lib/fOOrth/interpreter/data_stack.rb, line 58 def pop? pop.to_foorth_b end
Remove multiple entries from the “top” of the data stack.
Parameters:
-
count - the number of elements to be returned.
Returns:
-
An array containing the “top” count elements of the data stack.
Note:
-
Raises an
XfOOrthError
exception if the stack has too few data.
# File lib/fOOrth/interpreter/data_stack.rb, line 43 def popm(count) begin error "F30: Data Stack Underflow: popm" if @data_stack.length < count @data_stack.pop(count) rescue @data_stack = [] raise end end
Execute code from the interactive console.
# File lib/fOOrth/compiler.rb, line 61 def process_console process(console) ensure console.flush end
Execute a file of code.
# File lib/fOOrth/compiler.rb, line 73 def process_file(name) source = FileSource.new(name) begin process(source) ensure source.close end end
Execute a string of code.
# File lib/fOOrth/compiler.rb, line 68 def process_string(str) process(StringSource.new(str)) end
Depending on the mode, process the text source code.
Parameters:
-
text - Some text to be executed or deferred.
# File lib/fOOrth/compiler/modes.rb, line 17 def process_text(text) if execute_mode? dbg_puts " Code=#{text.inspect}" @context.target.instance_exec(self, &eval("lambda {|vm| #{text} }")) else self << text end end
Add an entry to the data stack.
Parameters:
-
datum - The data to be added to the data stack.
# File lib/fOOrth/interpreter/data_stack.rb, line 15 def push(datum) @data_stack << datum end
Add some entries to the data stack.
Parameters:
-
datum - An array of data to be mass added to the data stack.
# File lib/fOOrth/interpreter/data_stack.rb, line 22 def pushm(datum) @data_stack += datum end
Get the vm ready for operation
Parameters:
-
name - A string that describes this virtual machine instance.
# File lib/fOOrth/initialize.rb, line 57 def reinitialize(name) @data_stack = @data_stack.clone @name = name @data = @data.full_clone end
Reset the interpreter and the compiler.
# File lib/fOOrth/initialize.rb, line 64 def reset interpreter_reset compiler_reset end
While compiling and compiling is suspended, resume normal compiling.
Parameters:
-
ctrls - An array of control symbols that could have suspended the compilation.
Note:
-
Un-nests a context level.
# File lib/fOOrth/compiler/modes/suspend.rb, line 29 def resume_buffered_mode(ctrls) dbg_puts " resume_buffered_mode" @context.check_set(:ctrl, ctrls) @context = @context.previous end
If execution was previously deferred, resume the previous mode. This is used in words that close off a block action like then, loop, or repeat.
Parameters:
-
text - Some text to append to the buffer before bundling it up.
-
ctrls - An array of control symbols that could have started the deferral.
Note:
-
Un-nests a context level.
# File lib/fOOrth/compiler/modes/deferred.rb, line 47 def resume_execute_mode(text, ctrls) dbg_puts " resume_execute_mode" check_deferred_mode(text, ctrls) @context = @context.previous if @context[:mode] == :execute source, @buffer = "lambda {|vm| #{@buffer} }", nil instance_exec(self, &eval(source)) end end
Set the method cast.
# File lib/fOOrth/compiler/cast.rb, line 10 def set_cast(spec) error "F12: Multiple methods casts detected." if @cast @cast = spec end
Compress the entire data stack into a single entry.
# File lib/fOOrth/interpreter/squash.rb, line 10 def squash @data_stack = [@data_stack] end
Process optional string parameters.
Parameters:
-
token - The token to receive the generated code.
-
word - The text of the word.
# File lib/fOOrth/compiler/process/string.rb, line 13 def string_parms(token, word) source = parser.source if word.end_with?('"') string_value = parser.get_string.foorth_embed if source.peek == '*' source.get token.add("vm.push(StringBuffer.new(#{string_value})); ", [:string]) else token.add("vm.push(#{string_value}.freeze); ", [:string]) end end end
While compiling, suspend compiling so that some code may be executed.
Parameters:
-
ctrl - The control symbol that suspended the compilation.
Note:
-
Adds a nested context level to be un-nested at a later point.
# File lib/fOOrth/compiler/modes/suspend.rb, line 13 def suspend_buffered_mode(ctrl) dbg_puts " suspend_buffered_mode" unless buffer_valid? error "F14: The #{ctrl} method is not available in execute mode." end @context = Context.new(@context, mode: :execute, ctrl: ctrl) end
Enter a mode where execution is deferred. If currently in :execute mode, enter :deferred mode else the mode is unchanged. This is used by words that need to group words together to work like if, do, and begin.
Parameters:
-
text - Some text to append to the buffer before proceeding.
-
ctrl - The control symbol that started the deferral.
Notes:
-
Adds a nested context level to be un-nested at a later point.
-
Enters deferred mode only if currently in execute mode. Otherwise continues in the current mode.
# File lib/fOOrth/compiler/modes/deferred.rb, line 18 def suspend_execute_mode(text, ctrl) dbg_puts " suspend_execute_mode" @context = Context.new(@context, ctrl: ctrl) if execute_mode? @context[:mode] = :deferred @buffer = '' end self << text end
A special operation to support dyadic operators. Swap then pop.
Returns:
-
The second element from the data stack.
Note:
-
If the stack has less than 2 elements, this will raise an
XfOOrthError
exception.
# File lib/fOOrth/interpreter/data_stack.rb, line 109 def swap_pop begin unless @data_stack.length >= 2 error "F30: Data Stack Underflow: swap_pop" end nos, tos = @data_stack.pop(2) @data_stack << tos nos rescue @data_stack = [] raise end end
Leave a nested context without altering the current mode.
Parameters:
-
text - Some text to append associated with the nested state.
-
ctrls - An array of control symbols that could have started the nest.
Note:
-
Removes a nested context level.
# File lib/fOOrth/compiler/modes/nested.rb, line 26 def unnest_mode(text, ctrls) dbg_puts " unnest_context" @context.check_set(:ctrl, ctrls) @context = @context.previous process_text(text) if text end
Compress all the added entries into a single entry and revive the previous contents of the data stack.
# File lib/fOOrth/interpreter/squash.rb, line 16 def unsquash previous = @data_stack[0] data = @data_stack[1..-1] @data_stack = previous push(data) end
Verify the method cast
# File lib/fOOrth/compiler/cast.rb, line 21 def verify_cast(allowed) if @cast && !allowed.include?(@cast) error "F13: Cast of #{@cast.foorth_class_name} not allowed." end end
Make sure there are no dangling casts.
# File lib/fOOrth/compiler/cast.rb, line 28 def verify_casts_cleared error "F12: Dangling method cast detected." if @cast end
Get the version string for this virtual machine.
Endemic Code Smells
-
:reek:UtilityFunction
# File lib/fOOrth.rb, line 49 def version XfOOrth.version end
The runtime implementation of the “do” word.
Parameters:
-
jloop - An optional outer loop value.
-
block - A block of code to be executed as the do loop body.
Block Parameters:
-
iloop - The stack frame of the current loop counter. This corresponds to the fOOrth 'i' value.
-
jloop - The stack frame of any containing loop counter. This corresponds to the fOOrth 'j' value. If there is no containing loop, this will always be a zero frame ie: [0, 0, 0].
Note:
-
Nested loops must be in the same compiler context in order to use this mechanism. Otherwise, loop index counters must be passed in explicitly.
Endemic Code Smells
-
:reek:FeatureEnvy – false positive
# File lib/fOOrth/interpreter/do_loop.rb, line 24 def vm_do(jloop = [0, 0, 0], &block) #Pop the start and ending values from the stack. start_index, end_index = popm(2) #Construct the loop data frame. iloop = [start_index, end_index - 1, start_index + end_index - 1] #Loop until done! while iloop[0] <= iloop[1] #Yield to the loop. yield iloop, jloop end end
The runtime implementation of the “+loop” word.
# File lib/fOOrth/interpreter/do_loop.rb, line 39 def vm_do_increment inc_raw = self.pop unless (inc_value = inc_raw.to_foorth_n) error "F40: Cannot convert a #{inc_raw.foorth_name} to a Numeric instance" end if inc_value > 0 inc_value else error "F41: Invalid loop increment value: #{inc_value}" end end
Private Instance Methods
Handle the closing of a procedure literal.
# File lib/fOOrth/compiler/process/procedure.rb, line 91 def close_procedure_literal unnest_mode(nil, [:procedure]) end
The actual work of processing source code.
# File lib/fOOrth/compiler/process.rb, line 30 def due_process while (token = get_token) due_token(token) end end
Finally, process the taken.
# File lib/fOOrth/compiler/process.rb, line 37 def due_token(token) dbg_puts token.to_s code = token.code if execute_mode? || token.has_tag?(:immediate) @context.target.instance_exec(self, &eval("lambda {|vm| #{code} }")) else self << code end end
Get the type of the aliased method.
# File lib/fOOrth/library/alias_library.rb, line 106 def get_alias_type(old_spec, new_name) old_type = old_spec.class new_type = XfOOrth.name_to_type(new_name, self) old_desc, new_desc = old_type.foorth_name, new_type.foorth_name unless (allowed = ALLOWED_ALIAS_TYPES[old_type]) error "F13: A #{old_desc} method may not be aliased." end unless allowed.include?(new_type) error "F13: A #{old_desc} method may not be aliased as a #{new_desc}" end XfOOrth.validate_type(self, new_type, new_name) new_type end
Get the vm basic stuff first.
# File lib/fOOrth/library/introspection/vm.rb, line 22 def get_basic_vm_info results = [["Name", foorth_name], ["Ruby", self.to_s], ["Stack", @data_stack.inspect], ["Nesting", @context.depth], ["Quotes", @quotes], ["Debug", @debug], ["Show", @show_stack], ["Start", @start_time]] if (source = @parser && @parser.source) results << ["Source", source.source_name] results << ["Buffer", source.read_buffer.inspect] end results end
Get the exclusive specification of the original method.
# File lib/fOOrth/library/alias_library.rb, line 88 def get_old_exclusive_spec(target, old_name) old_symbol = get_old_symbol(old_name) unless (old_spec = target.map_foorth_exclusive(old_symbol)) f20_error(target, old_name, old_symbol) end old_spec end
Get the symbol of the old method.
# File lib/fOOrth/library/alias_library.rb, line 99 def get_old_symbol(old_name) old_symbol = XfOOrth::SymbolMap.map(old_name) error "F10: ?#{old_name}?" unless old_symbol old_symbol end
Extract a procedure literal from the source code.
# File lib/fOOrth/compiler/process/procedure.rb, line 22 def get_procedure_literal save, @buffer = @buffer, "" open_procedure_literal begin token = get_procedure_token due_token(token) end until token.has_tag?(:end) close_procedure_literal (_, @buffer = @buffer, save)[0] end
Get a token for the procedure literal.
# File lib/fOOrth/compiler/process/procedure.rb, line 96 def get_procedure_token error "F12: Error, Invalid nesting." unless (token = get_token) token end
Get the thread data info.
# File lib/fOOrth/library/introspection/vm.rb, line 41 def get_vm_thread_data_info(results) unless @data.empty? results.concat([["", ""], ["Data", "Thread"], ["", ""]]) @data .keys .map{|symbol| [SymbolMap.unmap(symbol), symbol]} .sort{|first, second| first[0] <=> second[0]} .map{|name, symbol| [name, @data[symbol]]} .each do |name, value| results << [name, value.inspect] end end end
Handle the opening of a procedure literal.
# File lib/fOOrth/compiler/process/procedure.rb, line 72 def open_procedure_literal suspend_execute_mode("vm.push(lambda {|vm, val=nil, idx=nil| ", :procedure) #Support for the standard procedure parameters. context.create_local_method('v', MacroSpec, [:macro, "vm.push(val); "]) context.create_local_method('x', MacroSpec, [:macro, "vm.push(idx); "]) #Support for local data. context.create_local_method('var:', LocalSpec, [:immediate], &Local_Var_Action) context.create_local_method('val:', LocalSpec, [:immediate], &Local_Val_Action) #Support for procedure instance data. context.create_local_method('var@:', LocalSpec, [:immediate], &PROC_VAR) context.create_local_method('val@:', LocalSpec, [:immediate], &PROC_VAL) context.create_local_method('}}', MacroSpec, [:macro, :end, "}); "]) end
Process optional string parameters.
Parameters:
-
token - The token to receive the generated code.
-
word - The text of the word.
# File lib/fOOrth/compiler/process/procedure.rb, line 15 def procedure_parms(token, word) if word.end_with?('{{') token.add(get_procedure_literal, [:procedure]) end end
Process the source code provided by the source parameter.
Parameters:
-
source - A source object. Typically a
Console
,StringSource
orFileSource
.
# File lib/fOOrth/compiler/process.rb, line 19 def process(source) save, @parser, start_depth = @parser, Parser.new(source), @context.depth due_process @context.check_depth(start_depth) verify_casts_cleared @parser = save end