rpl 0.1.0
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 +7 -0
- data/bin/rpl +51 -0
- data/lib/rpl/core/branch.rb +55 -0
- data/lib/rpl/core/filesystem.rb +40 -0
- data/lib/rpl/core/general.rb +57 -0
- data/lib/rpl/core/list.rb +33 -0
- data/lib/rpl/core/logarithm.rb +118 -0
- data/lib/rpl/core/mode.rb +44 -0
- data/lib/rpl/core/operations.rb +387 -0
- data/lib/rpl/core/program.rb +20 -0
- data/lib/rpl/core/stack.rb +155 -0
- data/lib/rpl/core/store.rb +124 -0
- data/lib/rpl/core/string.rb +114 -0
- data/lib/rpl/core/test.rb +127 -0
- data/lib/rpl/core/time-date.rb +38 -0
- data/lib/rpl/core/trig.rb +100 -0
- data/lib/rpl/dictionary.rb +75 -0
- data/lib/rpl/interpreter.rb +217 -0
- data/lib/rpl.rb +43 -0
- metadata +61 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b8843f4b55d77c8d3ec6c92cbe565ecb883361ba8cb47628097425b4b6f73da2
|
4
|
+
data.tar.gz: 430db66a68a4eeead6b16091e75aa9022a6a734004006067a38fb5283c3ec261
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7eff83ebc75b43ba473b913513590b82286932dd8b9628f9ae8970bb8d352ddd60a057e648d31fad7a5fefab974d2ddbcd9a03b18094c8c977e709bf1d910f56
|
7
|
+
data.tar.gz: 5fcd3aa9b3c9d918876fc5f69e3025a2f0339a4e0da8c2bc66432db11821ded06a149b3dcfe88d2d3d955c90ca42c86d0f2a4dc1257612bc5804380cf0638a4a
|
data/bin/rpl
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'readline'
|
5
|
+
|
6
|
+
require 'rpl'
|
7
|
+
|
8
|
+
class RplRepl
|
9
|
+
def initialize
|
10
|
+
@interpreter = Rpl.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
Readline.completion_proc = proc do |s|
|
15
|
+
( @interpreter.dictionary.words.keys + @interpreter.dictionary.vars.keys ).grep(/^#{Regexp.escape(s)}/)
|
16
|
+
end
|
17
|
+
Readline.completion_append_character = ' '
|
18
|
+
|
19
|
+
loop do
|
20
|
+
input = Readline.readline( ' ', true )
|
21
|
+
break if input.nil? || input == 'quit'
|
22
|
+
|
23
|
+
pp Readline::HISTORY if input == 'history'
|
24
|
+
|
25
|
+
# Remove blank lines from history
|
26
|
+
Readline::HISTORY.pop if input.empty?
|
27
|
+
|
28
|
+
begin
|
29
|
+
@interpreter.run( input )
|
30
|
+
rescue ArgumentError => e
|
31
|
+
p e
|
32
|
+
end
|
33
|
+
|
34
|
+
print_stack
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def format_element( elt )
|
39
|
+
@interpreter.stringify( elt )
|
40
|
+
end
|
41
|
+
|
42
|
+
def print_stack
|
43
|
+
stack_size = @interpreter.stack.size
|
44
|
+
|
45
|
+
@interpreter.stack.each_with_index do |elt, i|
|
46
|
+
puts "#{stack_size - i}: #{format_element( elt )}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
RplRepl.new.run
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RplLang
|
4
|
+
module Core
|
5
|
+
module Branch
|
6
|
+
def populate_dictionary
|
7
|
+
super
|
8
|
+
|
9
|
+
@dictionary.add_word( ['ift'],
|
10
|
+
'Branch',
|
11
|
+
'( t pt -- … ) eval pt or not based on the value of boolean t',
|
12
|
+
proc do
|
13
|
+
run( '« nop » ifte' )
|
14
|
+
end )
|
15
|
+
|
16
|
+
@dictionary.add_word( ['ifte'],
|
17
|
+
'Branch',
|
18
|
+
'( t pt pf -- … ) eval pt or pf based on the value of boolean t',
|
19
|
+
proc do
|
20
|
+
args = stack_extract( [:any, :any, %i[boolean]] )
|
21
|
+
|
22
|
+
run( args[ args[2][:value] ? 1 : 0 ][:value] )
|
23
|
+
end )
|
24
|
+
|
25
|
+
@dictionary.add_word( ['times'],
|
26
|
+
'Branch',
|
27
|
+
'( p n -- … ) eval p n times while pushing counter on stack before',
|
28
|
+
proc do
|
29
|
+
args = stack_extract( [%i[numeric], :any] )
|
30
|
+
|
31
|
+
args[0][:value].to_i.times do |i|
|
32
|
+
counter = { value: BigDecimal( i, @precision ), type: :numeric, base: 10 }
|
33
|
+
@stack << counter
|
34
|
+
|
35
|
+
run( args[1][:value] )
|
36
|
+
end
|
37
|
+
end )
|
38
|
+
|
39
|
+
@dictionary.add_word( ['loop'],
|
40
|
+
'Branch',
|
41
|
+
'( p n1 n2 -- … ) eval p looping from n1 to n2 while pushing counter on stack before',
|
42
|
+
proc do
|
43
|
+
args = stack_extract( [%i[numeric], %i[numeric], :any] )
|
44
|
+
|
45
|
+
((args[1][:value].to_i)..(args[0][:value].to_i)).each do |i|
|
46
|
+
counter = { value: BigDecimal( i, @precision ), type: :numeric, base: 10 }
|
47
|
+
@stack << counter
|
48
|
+
|
49
|
+
run( args[2][:value] )
|
50
|
+
end
|
51
|
+
end )
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RplLang
|
4
|
+
module Core
|
5
|
+
module FileSystem
|
6
|
+
def populate_dictionary
|
7
|
+
super
|
8
|
+
|
9
|
+
@dictionary.add_word( ['fread'],
|
10
|
+
'Filesystem',
|
11
|
+
'( filename -- content ) read file and put content on stack as string',
|
12
|
+
proc do
|
13
|
+
args = stack_extract( [%i[string]] )
|
14
|
+
|
15
|
+
path = File.absolute_path( args[0][:value] )
|
16
|
+
|
17
|
+
@stack << { type: :string,
|
18
|
+
value: File.read( path ) }
|
19
|
+
end )
|
20
|
+
|
21
|
+
@dictionary.add_word( ['feval'],
|
22
|
+
'Filesystem',
|
23
|
+
'( filename -- … ) read and run file',
|
24
|
+
proc do
|
25
|
+
run( 'fread eval' )
|
26
|
+
end )
|
27
|
+
|
28
|
+
@dictionary.add_word( ['fwrite'],
|
29
|
+
'Filesystem',
|
30
|
+
'( content filename -- ) write content into filename',
|
31
|
+
proc do
|
32
|
+
args = stack_extract( [%i[string], :any] )
|
33
|
+
|
34
|
+
File.write( File.absolute_path( args[0][:value] ),
|
35
|
+
args[1][:value] )
|
36
|
+
end )
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RplLang
|
4
|
+
module Core
|
5
|
+
module General
|
6
|
+
def populate_dictionary
|
7
|
+
super
|
8
|
+
|
9
|
+
@dictionary.add_word( ['nop'],
|
10
|
+
'General',
|
11
|
+
'( -- ) no operation',
|
12
|
+
proc {} )
|
13
|
+
|
14
|
+
@dictionary.add_word( ['help'],
|
15
|
+
'General',
|
16
|
+
'( w -- s ) pop help string of the given word',
|
17
|
+
proc do
|
18
|
+
args = stack_extract( [%i[name]] )
|
19
|
+
|
20
|
+
word = @dictionary.words[ args[0][:value] ]
|
21
|
+
|
22
|
+
@stack << { type: :string,
|
23
|
+
value: "#{args[0][:value]}: #{word.nil? ? 'not a core word' : word[:help]}" }
|
24
|
+
end )
|
25
|
+
|
26
|
+
@dictionary.add_word( ['quit'],
|
27
|
+
'General',
|
28
|
+
'( -- ) Stop and quit interpreter',
|
29
|
+
proc {} )
|
30
|
+
|
31
|
+
@dictionary.add_word( ['version'],
|
32
|
+
'General',
|
33
|
+
'( -- n ) Pop the interpreter\'s version number',
|
34
|
+
proc do
|
35
|
+
@stack += parse( @version.to_s )
|
36
|
+
end )
|
37
|
+
|
38
|
+
@dictionary.add_word( ['uname'],
|
39
|
+
'General',
|
40
|
+
'( -- s ) Pop the interpreter\'s complete indentification string',
|
41
|
+
proc do
|
42
|
+
@stack += parse( "\"Rpl Interpreter version #{@version}\"" )
|
43
|
+
end )
|
44
|
+
|
45
|
+
@dictionary.add_word( ['history'],
|
46
|
+
'REPL',
|
47
|
+
'',
|
48
|
+
proc {} )
|
49
|
+
|
50
|
+
@dictionary.add_word( ['.s'],
|
51
|
+
'REPL',
|
52
|
+
'DEBUG',
|
53
|
+
proc { pp @stack } )
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RplLang
|
4
|
+
module Core
|
5
|
+
module List
|
6
|
+
def populate_dictionary
|
7
|
+
super
|
8
|
+
|
9
|
+
@dictionary.add_word( ['→list', '->list'],
|
10
|
+
'Lists',
|
11
|
+
'( … x -- […] ) pack x stacks levels into a list',
|
12
|
+
proc do
|
13
|
+
args = stack_extract( [%i[numeric]] )
|
14
|
+
args = stack_extract( %i[any] * args[0][:value] )
|
15
|
+
|
16
|
+
@stack << { type: :list,
|
17
|
+
value: args.reverse }
|
18
|
+
end )
|
19
|
+
|
20
|
+
@dictionary.add_word( ['list→', 'list->'],
|
21
|
+
'Lists',
|
22
|
+
'( […] -- … ) unpack list on stack',
|
23
|
+
proc do
|
24
|
+
args = stack_extract( [%i[list]] )
|
25
|
+
|
26
|
+
args[0][:value].each do |elt|
|
27
|
+
@stack << elt
|
28
|
+
end
|
29
|
+
end )
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RplLang
|
4
|
+
module Core
|
5
|
+
module Logarithm
|
6
|
+
def populate_dictionary
|
7
|
+
super
|
8
|
+
|
9
|
+
@dictionary.add_word( ['ℇ', 'e'],
|
10
|
+
'Logs on reals and complexes',
|
11
|
+
'( … -- ℇ ) push ℇ',
|
12
|
+
proc do
|
13
|
+
@stack << { type: :numeric,
|
14
|
+
base: 10,
|
15
|
+
value: BigMath.E( @precision ) }
|
16
|
+
end )
|
17
|
+
|
18
|
+
# @dictionary.add_word( ['ln'],
|
19
|
+
# 'Logs on reals and complexes',
|
20
|
+
# 'logarithm base e',
|
21
|
+
# proc do
|
22
|
+
|
23
|
+
# end )
|
24
|
+
|
25
|
+
# @dictionary.add_word( ['lnp1'],
|
26
|
+
# 'Logs on reals and complexes',
|
27
|
+
# 'ln(1+x) which is useful when x is close to 0',
|
28
|
+
# proc do
|
29
|
+
|
30
|
+
# end )
|
31
|
+
|
32
|
+
# @dictionary.add_word( ['exp'],
|
33
|
+
# 'Logs on reals and complexes',
|
34
|
+
# 'exponential',
|
35
|
+
# proc do
|
36
|
+
|
37
|
+
# end )
|
38
|
+
|
39
|
+
# @dictionary.add_word( ['expm'],
|
40
|
+
# 'Logs on reals and complexes',
|
41
|
+
# 'exp(x)-1 which is useful when x is close to 0',
|
42
|
+
# proc do
|
43
|
+
|
44
|
+
# end )
|
45
|
+
|
46
|
+
# @dictionary.add_word( ['log10'],
|
47
|
+
# 'Logs on reals and complexes',
|
48
|
+
# 'logarithm base 10',
|
49
|
+
# proc do
|
50
|
+
|
51
|
+
# end )
|
52
|
+
|
53
|
+
# @dictionary.add_word( ['alog10'],
|
54
|
+
# 'Logs on reals and complexes',
|
55
|
+
# 'exponential base 10',
|
56
|
+
# proc do
|
57
|
+
|
58
|
+
# end )
|
59
|
+
|
60
|
+
# @dictionary.add_word( ['log2'],
|
61
|
+
# 'Logs on reals and complexes',
|
62
|
+
# 'logarithm base 2',
|
63
|
+
# proc do
|
64
|
+
|
65
|
+
# end )
|
66
|
+
|
67
|
+
# @dictionary.add_word( ['alog2'],
|
68
|
+
# 'Logs on reals and complexes',
|
69
|
+
# 'exponential base 2',
|
70
|
+
# proc do
|
71
|
+
|
72
|
+
# end )
|
73
|
+
|
74
|
+
# @dictionary.add_word( ['sinh'],
|
75
|
+
# 'Logs on reals and complexes',
|
76
|
+
# 'hyperbolic sine',
|
77
|
+
# proc do
|
78
|
+
|
79
|
+
# end )
|
80
|
+
|
81
|
+
# @dictionary.add_word( ['asinh'],
|
82
|
+
# 'Logs on reals and complexes',
|
83
|
+
# 'inverse hyperbolic sine',
|
84
|
+
# proc do
|
85
|
+
|
86
|
+
# end )
|
87
|
+
|
88
|
+
# @dictionary.add_word( ['cosh'],
|
89
|
+
# 'Logs on reals and complexes',
|
90
|
+
# 'hyperbolic cosine',
|
91
|
+
# proc do
|
92
|
+
|
93
|
+
# end )
|
94
|
+
|
95
|
+
# @dictionary.add_word( ['acosh'],
|
96
|
+
# 'Logs on reals and complexes',
|
97
|
+
# 'inverse hyperbolic cosine',
|
98
|
+
# proc do
|
99
|
+
|
100
|
+
# end )
|
101
|
+
|
102
|
+
# @dictionary.add_word( ['tanh'],
|
103
|
+
# 'Logs on reals and complexes',
|
104
|
+
# 'hyperbolic tangent',
|
105
|
+
# proc do
|
106
|
+
|
107
|
+
# end )
|
108
|
+
|
109
|
+
# @dictionary.add_word( ['atanh'],
|
110
|
+
# 'Logs on reals and complexes',
|
111
|
+
# 'inverse hyperbolic tangent',
|
112
|
+
# proc do
|
113
|
+
|
114
|
+
# end )
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RplLang
|
4
|
+
module Core
|
5
|
+
module Mode
|
6
|
+
def populate_dictionary
|
7
|
+
super
|
8
|
+
|
9
|
+
@dictionary.add_word( ['prec'],
|
10
|
+
'Mode',
|
11
|
+
'( a -- ) set precision to a',
|
12
|
+
proc do
|
13
|
+
args = stack_extract( [%i[numeric]] )
|
14
|
+
|
15
|
+
@precision = args[0][:value]
|
16
|
+
end )
|
17
|
+
@dictionary.add_word( ['default'],
|
18
|
+
'Mode',
|
19
|
+
'( -- ) set default precision',
|
20
|
+
proc do
|
21
|
+
@precision = default_precision
|
22
|
+
end )
|
23
|
+
@dictionary.add_word( ['type'],
|
24
|
+
'Mode',
|
25
|
+
'( a -- s ) type of a as a string',
|
26
|
+
proc do
|
27
|
+
args = stack_extract( [:any] )
|
28
|
+
|
29
|
+
@stack << { type: :string,
|
30
|
+
value: args[0][:type].to_s }
|
31
|
+
end )
|
32
|
+
|
33
|
+
# @dictionary.add_word( ['std'],
|
34
|
+
# proc { __todo } ) # standard floating numbers representation. ex: std
|
35
|
+
# @dictionary.add_word( ['fix'],
|
36
|
+
# proc { __todo } ) # fixed point representation. ex: 6 fix
|
37
|
+
# @dictionary.add_word( ['sci'],
|
38
|
+
# proc { __todo } ) # scientific floating point representation. ex: 20 sci
|
39
|
+
# @dictionary.add_word( ['round'],
|
40
|
+
# proc { __todo } ) # set float rounding mode. ex: ["nearest", "toward zero", "toward +inf", "toward -inf", "away from zero"] round
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|