rpl 0.9.1 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 21e9bc8ba67723150f213575e38739395c1e6e3d0a9e4698f674e3639ab1b832
4
- data.tar.gz: 3f2fbc820f3bdddca938a03b5ef84ea1ff87c6808ab1d7be54ad0e4acc3bf159
3
+ metadata.gz: 10af1c6c132173d66be7c554831cd2d86d289c401b5aa36ba16deaca62634ab6
4
+ data.tar.gz: b0a72cece6e644b76c1dfe4a4a8533936d1025b464a64cbcfa82640549209b66
5
5
  SHA512:
6
- metadata.gz: cb8417f6fabef1f7b852965b1c6b3bd0c88a97ee916f142e5fe88f8f088a70899130c2bb508427ca0c6659216d03a2b07e7f4b1c64ec2c36916b2e77d3375dfa
7
- data.tar.gz: 3231ef3590627ac0ab7897a58282dd3a432339d5adbebb900c25ad4871ca91259d3ec38459f26dd865849d679a7561cffbe70ec20b4a58676aaaab57332e9ebc
6
+ metadata.gz: ae2fc038218acbaced883355476dd1fcb77d325cda5db7dc7fc49eedc70d90a58b071f6efece38929d8ac292dd325ec6b663bc70cab31f73ee9f039d5e4847c5
7
+ data.tar.gz: daabf61d638a593ca324eade777e0d26e959f29a0883b8af67c34647efd6efe7da5e5af777fac6a6ea7e4197495fa08bfe76cf9aca593c7849564d8e6fa00431
data/bin/rpl CHANGED
@@ -8,9 +8,7 @@ require 'readline'
8
8
  require 'rpl'
9
9
 
10
10
  class RplRepl
11
- def initialize( interpreter )
12
- interpreter ||= Rpl.new
13
-
11
+ def initialize( interpreter: Rpl.new )
14
12
  @interpreter = interpreter
15
13
  end
16
14
 
@@ -51,11 +49,27 @@ class RplRepl
51
49
  end
52
50
 
53
51
  options = { run_REPL: ARGV.empty?,
52
+ persistence_filename: File.expand_path( '~/.local/state/rpl.rb/machine' ),
53
+ live_persistence: true,
54
54
  files: [],
55
55
  programs: [] }
56
56
 
57
+ Version = Rpl::VERSION
58
+
57
59
  OptionParser.new do |opts|
58
- opts.on('-c', '--code "program"', ' ') do |program|
60
+ opts.on('-s', "--state filename", "persist state in filename (default: #{options[:persistence_filename]}) (will be created if needed)") do |filename|
61
+ options[:persistence_filename] = File.expand_path( filename )
62
+ end
63
+
64
+ opts.on('-q', '--no-state', 'Do not load persisted state') do
65
+ options[:persistence_filename] = nil
66
+ end
67
+
68
+ opts.on('-d', '--no-persist', 'Do not persist state') do
69
+ options[:live_persistence] = false
70
+ end
71
+
72
+ opts.on('-c', '--code "program"', 'run provided "program"') do |program|
59
73
  options[:programs] << program
60
74
  end
61
75
 
@@ -69,11 +83,12 @@ OptionParser.new do |opts|
69
83
  end.parse!
70
84
 
71
85
  # Instantiate interpreter
72
- interpreter = Rpl.new
86
+ interpreter = Rpl.new( persistence_filename: options[:persistence_filename],
87
+ live_persistence: options[:live_persistence] )
73
88
 
74
89
  # first run provided files if any
75
90
  options[:files].each do |filename|
76
- interpreter.run "\"#{filename}\" feval"
91
+ interpreter.run "\"#{File.expand_path( filename )}\" feval"
77
92
  end
78
93
 
79
94
  # second run provided code if any
@@ -82,7 +97,8 @@ options[:programs].each do |program|
82
97
  end
83
98
 
84
99
  # third launch REPL if (explicitely or implicitely) asked
85
- RplRepl.new( interpreter ).run if options[:run_REPL]
86
-
87
- # last print defined vars and resulting stack on exit (formatted so that it can be fed back later to interpreter)
88
- pp "#{interpreter.export_vars} #{interpreter.export_stack}"
100
+ if options[:run_REPL]
101
+ RplRepl.new( interpreter: interpreter ).run
102
+ else
103
+ interpreter.persist_state
104
+ end
@@ -36,9 +36,7 @@ class Interpreter
36
36
 
37
37
  attr_accessor :precision
38
38
 
39
- def initialize( stack = [], dictionary = Rpl::Lang::Dictionary.new )
40
- @version = 0.91
41
-
39
+ def initialize( stack: [], dictionary: Dictionary.new )
42
40
  @dictionary = dictionary
43
41
  @stack = stack
44
42
 
@@ -100,12 +98,19 @@ class Interpreter
100
98
  end
101
99
 
102
100
  def export_vars
103
- @dictionary.vars
104
- .map { |name, value| "#{value} '#{name}' sto" }
105
- .join(' ')
101
+ vars_as_string = "@ variables:\n"
102
+ vars_as_string += @dictionary.vars
103
+ .map { |name, value| "#{value}\n'#{name}' sto\n" }
104
+ .join("\n")
105
+
106
+ vars_as_string
106
107
  end
107
108
 
108
109
  def export_stack
109
- @stack.map(&:to_s).join(' ')
110
+ stack_as_string = "@ stack:\n"
111
+ stack_as_string += @stack.map(&:to_s)
112
+ .join("\n")
113
+
114
+ stack_as_string
110
115
  end
111
116
  end
@@ -16,7 +16,7 @@ module RplLang
16
16
  proc do
17
17
  args = stack_extract( [[RplString]] )
18
18
 
19
- path = File.absolute_path( args[0].value )
19
+ path = File.expand_path( args[0].value )
20
20
 
21
21
  @stack << Types.new_object( RplString, "\"#{File.read( path )}\"" )
22
22
  end )
@@ -32,7 +32,7 @@ module RplLang
32
32
  proc do
33
33
  args = stack_extract( [[RplString], :any] )
34
34
 
35
- File.write( File.absolute_path( args[0].value ),
35
+ File.write( File.expand_path( args[0].value ),
36
36
  args[1].value )
37
37
  end )
38
38
  end
@@ -35,15 +35,13 @@ module RplLang
35
35
  category,
36
36
  '( -- n ) Pop the interpreter\'s version number',
37
37
  proc do
38
- @stack << Types.new_object( RplString, "\"#{@version}\"" )
38
+ @stack << Types.new_object( RplString, "\"#{Rpl::VERSION}\"" )
39
39
  end )
40
40
 
41
41
  @dictionary.add_word( ['uname'],
42
42
  category,
43
43
  '( -- s ) Pop the interpreter\'s complete indentification string',
44
- proc do
45
- @stack << Types.new_object( RplString, "\"Rpl Interpreter version #{@version}\"" )
46
- end )
44
+ Types.new_object( RplProgram, '« "Rpl Interpreter version " version + »' ) )
47
45
  end
48
46
  end
49
47
  end
data/lib/rpl.rb CHANGED
@@ -5,12 +5,49 @@ require 'rpl/types'
5
5
  require 'rpl/words'
6
6
 
7
7
  class Rpl < Interpreter
8
+ VERSION = '0.10.2'
9
+
8
10
  include Types
9
11
 
10
- def initialize( stack = [], dictionary = Dictionary.new )
11
- super
12
+ attr_accessor :live_persistence
13
+
14
+ def initialize( stack: [],
15
+ dictionary: Dictionary.new,
16
+ persistence_filename: nil,
17
+ live_persistence: true )
18
+ super( stack: stack, dictionary: dictionary )
19
+
20
+ @persistence_filename = persistence_filename
21
+ @live_persistence = live_persistence
12
22
 
13
23
  populate_dictionary if @dictionary.words.empty?
24
+
25
+ load_persisted_state
26
+ end
27
+
28
+ def load_persisted_state
29
+ return if @persistence_filename.nil?
30
+
31
+ FileUtils.mkdir_p( File.dirname( @persistence_filename ) )
32
+ FileUtils.touch( @persistence_filename )
33
+
34
+ run "\"#{@persistence_filename}\" feval"
35
+ end
36
+
37
+ def persist_state
38
+ return if @persistence_filename.nil?
39
+
40
+ File.open( @persistence_filename, 'w' ) do |persistence_file|
41
+ persistence_file.write "#{export_vars}\n#{export_stack}"
42
+ end
43
+ end
44
+
45
+ def run( input )
46
+ stack = super
47
+
48
+ persist_state if @live_persistence
49
+
50
+ stack
14
51
  end
15
52
 
16
53
  prepend RplLang::Words::Branch
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rpl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.10.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gwenhael Le Moine
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-04 00:00:00.000000000 Z
11
+ date: 2022-10-05 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A language inspired by HP's RPL and https://github.com/louisrubet/rpn/
14
14
  email: gwenhael@le-moine.org