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 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