Persist stack and variable in ~/.local/state/rpl.rb/machine

This commit is contained in:
Gwenhael Le Moine 2022-10-04 16:49:24 +02:00
parent dfac755ce5
commit 4dfe9554cb
No known key found for this signature in database
GPG key ID: FDFE3669426707A7
4 changed files with 72 additions and 20 deletions

View file

@ -12,10 +12,6 @@ To build gem: `rake gem`
-
# TODO-list
* REPL:
* autosave/autoload stack and vars from ~/.rplenv on start/exit
. autoload is just « '~/.rplenv' feval »
. autosave on exit overwrites
* Language:
* pseudo filesystem: subdir/namespace for variables
. 'a dir' crdir 'a dir' cd vars

32
bin/rpl
View file

@ -8,9 +8,7 @@ require 'readline'
require 'rpl'
class RplRepl
def initialize( interpreter )
interpreter ||= Rpl.new
def initialize( interpreter: Rpl.new )
@interpreter = interpreter
end
@ -51,11 +49,25 @@ class RplRepl
end
options = { run_REPL: ARGV.empty?,
persistence_filename: File.expand_path( '~/.local/state/rpl.rb/machine' ),
live_persistence: true,
files: [],
programs: [] }
OptionParser.new do |opts|
opts.on('-c', '--code "program"', ' ') do |program|
opts.on('-s', "--state filename", "persist state in filename (default: #{options[:persistence_filename]}) (will be created if needed)") do |filename|
options[:persistence_filename] = File.expand_path( filename )
end
opts.on('-q', '--no-state', 'Do not load persisted state') do
options[:persistence_filename] = nil
end
opts.on('-d', '--no-persist', 'Do not persist state') do
options[:live_persistence] = false
end
opts.on('-c', '--code "program"', 'run provided "program"') do |program|
options[:programs] << program
end
@ -69,7 +81,8 @@ OptionParser.new do |opts|
end.parse!
# Instantiate interpreter
interpreter = Rpl.new
interpreter = Rpl.new( persistence_filename: options[:persistence_filename],
live_persistence: options[:live_persistence] )
# first run provided files if any
options[:files].each do |filename|
@ -82,7 +95,8 @@ options[:programs].each do |program|
end
# third launch REPL if (explicitely or implicitely) asked
RplRepl.new( interpreter ).run if options[:run_REPL]
# last print defined vars and resulting stack on exit (formatted so that it can be fed back later to interpreter)
pp "#{interpreter.export_vars} #{interpreter.export_stack}"
if options[:run_REPL]
RplRepl.new( interpreter: interpreter ).run
else
interpreter.persist_state
end

View file

@ -7,10 +7,45 @@ require 'rpl/words'
class Rpl < Interpreter
include Types
def initialize( stack = [], dictionary = Dictionary.new )
super
attr_accessor :live_persistence
def initialize( stack: [],
dictionary: Dictionary.new,
persistence_filename: nil,
live_persistence: true )
super( stack: stack, dictionary: dictionary )
@persistence_filename = persistence_filename
@live_persistence = live_persistence
populate_dictionary if @dictionary.words.empty?
load_persisted_state
end
def load_persisted_state
return if @persistence_filename.nil?
FileUtils.mkdir_p( File.dirname( @persistence_filename ) )
FileUtils.touch( @persistence_filename )
run "\"#{@persistence_filename}\" feval"
end
def persist_state
return if @persistence_filename.nil?
File.open( @persistence_filename, 'w' ) do |persistence_file|
persistence_file.write "#{export_vars}\n#{export_stack}"
end
end
def run( input )
stack = super
persist_state if @live_persistence
stack
end
prepend RplLang::Words::Branch

View file

@ -36,7 +36,7 @@ class Interpreter
attr_accessor :precision
def initialize( stack = [], dictionary = Rpl::Lang::Dictionary.new )
def initialize( stack: [], dictionary: Dictionary.new )
@version = 0.91
@dictionary = dictionary
@ -100,12 +100,19 @@ class Interpreter
end
def export_vars
@dictionary.vars
.map { |name, value| "#{value} '#{name}' sto" }
.join(' ')
vars_as_string = "@ variables:\n"
vars_as_string += @dictionary.vars
.map { |name, value| "#{value}\n'#{name}' sto\n" }
.join("\n")
vars_as_string
end
def export_stack
@stack.map(&:to_s).join(' ')
stack_as_string = "@ stack:\n"
stack_as_string += @stack.map(&:to_s)
.join("\n")
stack_as_string
end
end