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.
@@ -0,0 +1,387 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RplLang
4
+ module Core
5
+ module Operations
6
+ def populate_dictionary
7
+ super
8
+
9
+ # Usual operations on reals and complexes
10
+ @dictionary.add_word( ['+'],
11
+ 'Usual operations on reals and complexes',
12
+ '( a b -- c ) addition',
13
+ proc do
14
+ addable = %i[numeric string name list]
15
+ args = stack_extract( [addable, addable] )
16
+ # | + | 1 numeric | 1 string | 1 name | 1 list |
17
+ # |-----------+-----------+----------+--------+--------|
18
+ # | 0 numeric | numeric | string | name | list |
19
+ # | 0 string | string | string | string | list |
20
+ # | 0 name | string | string | name | list |
21
+ # | 0 list | list | list | list | list |
22
+
23
+ result = { type: case args[0][:type]
24
+ when :numeric
25
+ args[1][:type]
26
+
27
+ when :string
28
+ case args[1][:type]
29
+ when :list
30
+ :list
31
+ else
32
+ :string
33
+ end
34
+
35
+ when :name
36
+ case args[1][:type]
37
+ when :name
38
+ :name
39
+ when :list
40
+ :list
41
+ else
42
+ :string
43
+ end
44
+
45
+ when :list
46
+ :list
47
+
48
+ else
49
+ args[0][:type]
50
+ end }
51
+
52
+ if result[:type] == :list
53
+ args.each do |elt|
54
+ next unless elt[:type] != :list
55
+
56
+ elt_copy = Marshal.load(Marshal.dump( elt ))
57
+ elt[:type] = :list
58
+ elt[:value] = [elt_copy]
59
+ end
60
+ end
61
+
62
+ value_to_string = lambda do |e|
63
+ if e[:type] == :numeric
64
+ stringify( e )
65
+ else
66
+ e[:value].to_s
67
+ end
68
+ end
69
+
70
+ result[:value] = if %i[name string].include?( result[:type] )
71
+ "#{value_to_string.call( args[1] )}#{value_to_string.call( args[0] )}"
72
+ else
73
+ args[1][:value] + args[0][:value]
74
+ end
75
+
76
+ result[:base] = args[0][:base] if result[:type] == :numeric
77
+
78
+ @stack << result
79
+ end )
80
+
81
+ @dictionary.add_word( ['-'],
82
+ 'Usual operations on reals and complexes',
83
+ '( a b -- c ) subtraction',
84
+ proc do
85
+ args = stack_extract( [%i[numeric], %i[numeric]] )
86
+
87
+ @stack << { type: :numeric, base: infer_resulting_base( args ),
88
+ value: args[1][:value] - args[0][:value] }
89
+ end )
90
+
91
+ @dictionary.add_word( ['chs'],
92
+ 'Usual operations on reals and complexes',
93
+ '( a -- b ) negate',
94
+ proc do
95
+ run( '-1 *' )
96
+ end )
97
+
98
+ @dictionary.add_word( ['×', '*'],
99
+ 'Usual operations on reals and complexes',
100
+ '( a b -- c ) multiplication',
101
+ proc do
102
+ args = stack_extract( [%i[numeric], %i[numeric]] )
103
+
104
+ @stack << { type: :numeric, base: infer_resulting_base( args ),
105
+ value: args[1][:value] * args[0][:value] }
106
+ end )
107
+
108
+ @dictionary.add_word( ['÷', '/'],
109
+ 'Usual operations on reals and complexes',
110
+ '( a b -- c ) division',
111
+ proc do
112
+ args = stack_extract( [%i[numeric], %i[numeric]] )
113
+
114
+ @stack << { type: :numeric, base: infer_resulting_base( args ),
115
+ value: args[1][:value] / args[0][:value] }
116
+ end )
117
+
118
+ @dictionary.add_word( ['inv'],
119
+ 'Usual operations on reals and complexes',
120
+ '( a -- b ) invert numeric',
121
+ proc do
122
+ run( '1.0 swap /' )
123
+ end )
124
+
125
+ @dictionary.add_word( ['^'],
126
+ 'Usual operations on reals and complexes',
127
+ '( a b -- c ) a to the power of b',
128
+ proc do
129
+ args = stack_extract( [%i[numeric], %i[numeric]] )
130
+
131
+ @stack << { type: :numeric, base: infer_resulting_base( args ),
132
+ value: args[1][:value]**args[0][:value] }
133
+ end )
134
+
135
+ @dictionary.add_word( ['√', 'sqrt'],
136
+ 'Usual operations on reals and complexes',
137
+ '( a -- b ) square root',
138
+ proc do
139
+ args = stack_extract( [%i[numeric]] )
140
+
141
+ @stack << { type: :numeric, base: infer_resulting_base( args ),
142
+ value: BigMath.sqrt( BigDecimal( args[0][:value], precision ), precision ) }
143
+ end )
144
+
145
+ @dictionary.add_word( ['²', 'sq'],
146
+ 'Usual operations on reals and complexes',
147
+ '( a -- b ) square',
148
+ proc do
149
+ run( 'dup ×')
150
+ end )
151
+
152
+ @dictionary.add_word( ['abs'],
153
+ 'Usual operations on reals and complexes',
154
+ '( a -- b ) absolute value',
155
+ proc do
156
+ args = stack_extract( [%i[numeric]] )
157
+
158
+ @stack << { type: :numeric, base: infer_resulting_base( args ),
159
+ value: args[0][:value].abs }
160
+ end )
161
+
162
+ @dictionary.add_word( ['dec'],
163
+ 'Usual operations on reals and complexes',
164
+ '( a -- a ) set numeric\'s base to 10',
165
+ proc do
166
+ run( '10 base' )
167
+ end )
168
+
169
+ @dictionary.add_word( ['hex'],
170
+ 'Usual operations on reals and complexes',
171
+ '( a -- a ) set numeric\'s base to 16',
172
+ proc do
173
+ run( '16 base' )
174
+ end )
175
+
176
+ @dictionary.add_word( ['bin'],
177
+ 'Usual operations on reals and complexes',
178
+ '( a -- a ) set numeric\'s base to 2',
179
+ proc do
180
+ run( '2 base' )
181
+ end )
182
+
183
+ @dictionary.add_word( ['base'],
184
+ 'Usual operations on reals and complexes',
185
+ '( a b -- a ) set numeric\'s base to b',
186
+ proc do
187
+ args = stack_extract( [%i[numeric], %i[numeric]] )
188
+
189
+ args[1][:base] = args[0][:value]
190
+
191
+ @stack << args[1]
192
+ end )
193
+
194
+ @dictionary.add_word( ['sign'],
195
+ 'Usual operations on reals and complexes',
196
+ '( a -- b ) sign of element',
197
+ proc do
198
+ args = stack_extract( [%i[numeric]] )
199
+ value = if args[0][:value].positive?
200
+ 1
201
+ elsif args[0][:value].negative?
202
+ -1
203
+ else
204
+ 0
205
+ end
206
+
207
+ @stack << { type: :numeric, base: infer_resulting_base( args ),
208
+ value: value }
209
+ end )
210
+
211
+ # Operations on reals
212
+ @dictionary.add_word( ['%'],
213
+ 'Operations on reals',
214
+ '( a b -- c ) b% of a',
215
+ proc do
216
+ args = stack_extract( [%i[numeric], %i[numeric]] )
217
+
218
+ @stack << { type: :numeric,
219
+ base: infer_resulting_base( args ),
220
+ value: args[0][:value] * ( args[1][:value] / 100.0 ) }
221
+ end )
222
+
223
+ @dictionary.add_word( ['%CH'],
224
+ 'Operations on reals',
225
+ '( a b -- c ) b is c% of a',
226
+ proc do
227
+ args = stack_extract( [%i[numeric], %i[numeric]] )
228
+
229
+ @stack << { type: :numeric,
230
+ base: infer_resulting_base( args ),
231
+ value: 100.0 * ( args[0][:value] / args[1][:value] ) }
232
+ end )
233
+
234
+ @dictionary.add_word( ['mod'],
235
+ 'Operations on reals',
236
+ '( a b -- c ) modulo',
237
+ proc do
238
+ args = stack_extract( [%i[numeric], %i[numeric]] )
239
+
240
+ @stack << { type: :numeric,
241
+ base: infer_resulting_base( args ),
242
+ value: args[1][:value] % args[0][:value] }
243
+ end )
244
+
245
+ @dictionary.add_word( ['!', 'fact'],
246
+ 'Operations on reals',
247
+ '( a -- b ) factorial',
248
+ proc do
249
+ args = stack_extract( [%i[numeric]] )
250
+
251
+ @stack << { type: :numeric,
252
+ base: infer_resulting_base( args ),
253
+ value: Math.gamma( args[0][:value] ) }
254
+ end )
255
+
256
+ @dictionary.add_word( ['floor'],
257
+ 'Operations on reals',
258
+ '( a -- b ) highest integer under a',
259
+ proc do
260
+ args = stack_extract( [%i[numeric]] )
261
+
262
+ @stack << { type: :numeric,
263
+ base: infer_resulting_base( args ),
264
+ value: args[0][:value].floor }
265
+ end )
266
+
267
+ @dictionary.add_word( ['ceil'],
268
+ 'Operations on reals',
269
+ '( a -- b ) highest integer over a',
270
+ proc do
271
+ args = stack_extract( [%i[numeric]] )
272
+
273
+ @stack << { type: :numeric,
274
+ base: infer_resulting_base( args ),
275
+ value: args[0][:value].ceil }
276
+ end )
277
+
278
+ @dictionary.add_word( ['min'],
279
+ 'Operations on reals',
280
+ '( a b -- a/b ) leave lowest of a or b',
281
+ proc do
282
+ args = stack_extract( [%i[numeric], %i[numeric]] )
283
+
284
+ @stack << ( args[0][:value] < args[1][:value] ? args[0] : args[1] )
285
+ end )
286
+
287
+ @dictionary.add_word( ['max'],
288
+ 'Operations on reals',
289
+ '( a b -- a/b ) leave highest of a or b',
290
+ proc do
291
+ args = stack_extract( [%i[numeric], %i[numeric]] )
292
+
293
+ @stack << ( args[0][:value] > args[1][:value] ? args[0] : args[1] )
294
+ end )
295
+
296
+ # @dictionary.add_word( ['mant'],
297
+ # 'Operations on reals',
298
+ # 'mantissa of a real number',
299
+ # proc do
300
+
301
+ # end )
302
+
303
+ # @dictionary.add_word( ['xpon'],
304
+ # 'Operations on reals',
305
+ # 'exponant of a real number',
306
+ # proc do
307
+
308
+ # end )
309
+
310
+ @dictionary.add_word( ['ip'],
311
+ 'Operations on reals',
312
+ '( n -- i ) integer part',
313
+ proc do
314
+ run( 'dup fp -' )
315
+ end )
316
+
317
+ @dictionary.add_word( ['fp'],
318
+ 'Operations on reals',
319
+ '( n -- f ) fractional part',
320
+ proc do
321
+ args = stack_extract( [%i[numeric]] )
322
+
323
+ @stack << { type: :numeric,
324
+ base: infer_resulting_base( args ),
325
+ value: args[0][:value].frac }
326
+ end )
327
+
328
+ # Operations on complexes
329
+ # @dictionary.add_word( ['re'],
330
+ # 'Operations on complexes',
331
+ # 'complex real part',
332
+ # proc do
333
+
334
+ # end )
335
+
336
+ # @dictionary.add_word( 'im',
337
+ # 'Operations on complexes',
338
+ # 'complex imaginary part',
339
+ # proc do
340
+
341
+ # end )
342
+
343
+ # @dictionary.add_word( ['conj'],
344
+ # 'Operations on complexes',
345
+ # 'complex conjugate',
346
+ # proc do
347
+
348
+ # end )
349
+
350
+ # @dictionary.add_word( 'arg',
351
+ # 'Operations on complexes',
352
+ # 'complex argument in radians',
353
+ # proc do
354
+
355
+ # end )
356
+
357
+ # @dictionary.add_word( ['c→r', 'c->r'],
358
+ # 'Operations on complexes',
359
+ # 'transform a complex in 2 reals',
360
+ # proc do
361
+
362
+ # end )
363
+
364
+ # @dictionary.add_word( ['r→c', 'r->c'],
365
+ # 'Operations on complexes',
366
+ # 'transform 2 reals in a complex',
367
+ # proc do
368
+
369
+ # end )
370
+
371
+ # @dictionary.add_word( ['p→r', 'p->r'],
372
+ # 'Operations on complexes',
373
+ # 'cartesian to polar',
374
+ # proc do
375
+
376
+ # end )
377
+
378
+ # @dictionary.add_word( ['r→p', 'r->p'],
379
+ # 'Operations on complexes',
380
+ # 'polar to cartesian',
381
+ # proc do
382
+
383
+ # end )
384
+ end
385
+ end
386
+ end
387
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RplLang
4
+ module Core
5
+ module Program
6
+ def populate_dictionary
7
+ super
8
+
9
+ @dictionary.add_word( ['eval'],
10
+ 'Program',
11
+ '( a -- … ) interpret',
12
+ proc do
13
+ args = stack_extract( [:any] )
14
+
15
+ run( args[0][:value].to_s )
16
+ end )
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RplLang
4
+ module Core
5
+ module Stack
6
+ def populate_dictionary
7
+ super
8
+
9
+ @dictionary.add_word( ['swap'],
10
+ 'Stack',
11
+ '( a b -- b a ) swap 2 first stack elements',
12
+ proc do
13
+ args = stack_extract( %i[any any] )
14
+
15
+ @stack << args[0] << args[1]
16
+ end )
17
+
18
+ @dictionary.add_word( ['drop'],
19
+ 'Stack',
20
+ '( a -- ) drop first stack element',
21
+ proc do
22
+ run( '1 dropn' )
23
+ end )
24
+
25
+ @dictionary.add_word( ['drop2'],
26
+ 'Stack',
27
+ '( a b -- ) drop first two stack elements',
28
+ proc do
29
+ run( '2 dropn' )
30
+ end )
31
+
32
+ @dictionary.add_word( ['dropn'],
33
+ 'Stack',
34
+ '( a b … n -- ) drop first n stack elements',
35
+ proc do
36
+ args = stack_extract( [%i[numeric]] )
37
+
38
+ _args = stack_extract( %i[any] * args[0][:value] )
39
+ end )
40
+
41
+ @dictionary.add_word( ['del'],
42
+ 'Stack',
43
+ '( a b … -- ) drop all stack elements',
44
+ proc do
45
+ @stack = []
46
+ end)
47
+
48
+ @dictionary.add_word( ['rot'],
49
+ 'Stack',
50
+ '( a b c -- b c a ) rotate 3 first stack elements',
51
+ proc do
52
+ args = stack_extract( %i[any any any] )
53
+
54
+ @stack << args[1] << args[0] << args[2]
55
+ end )
56
+
57
+ @dictionary.add_word( ['dup'],
58
+ 'Stack',
59
+ '( a -- a a ) duplicate first stack element',
60
+ proc do
61
+ run( '1 dupn' )
62
+ end )
63
+
64
+ @dictionary.add_word( ['dup2'],
65
+ 'Stack',
66
+ '( a b -- a b a b ) duplicate first two stack elements',
67
+ proc do
68
+ run( '2 dupn' )
69
+ end )
70
+
71
+ @dictionary.add_word( ['dupn'],
72
+ 'Stack',
73
+ '( a b … n -- a b … a b … ) duplicate first n stack elements',
74
+ proc do
75
+ args = stack_extract( [%i[numeric]] )
76
+ n = args[0][:value].to_i
77
+ args = stack_extract( %i[any] * args[0][:value] )
78
+
79
+ args.reverse!
80
+
81
+ 2.times do
82
+ n.times.each do |i|
83
+ @stack << Marshal.load(Marshal.dump( args[i] ))
84
+ end
85
+ end
86
+ end )
87
+
88
+ @dictionary.add_word( ['pick'],
89
+ 'Stack',
90
+ '( … b … n -- … b … b ) push a copy of the given stack level onto the stack',
91
+ proc do
92
+ args = stack_extract( [%i[numeric]] )
93
+ n = args[0][:value].to_i
94
+ args = stack_extract( %i[any] * args[0][:value] )
95
+
96
+ args.reverse!
97
+
98
+ n.times.each do |i|
99
+ @stack << args[ i ]
100
+ end
101
+
102
+ @stack << args[0]
103
+ end )
104
+
105
+ @dictionary.add_word( ['depth'],
106
+ 'Stack',
107
+ '( … -- … n ) push stack depth onto the stack',
108
+ proc do
109
+ @stack << { type: :numeric, base: 10, value: BigDecimal( stack.size ) }
110
+ end )
111
+
112
+ @dictionary.add_word( ['roll'],
113
+ 'Stack',
114
+ '( … a -- a … ) move a stack element to the top of the stack',
115
+ proc do
116
+ args = stack_extract( [%i[numeric]] )
117
+ n = args[0][:value]
118
+ args = stack_extract( %i[any] * args[0][:value] )
119
+
120
+ args.reverse!
121
+
122
+ (1..(n - 1)).each do |i|
123
+ @stack << args[ i ]
124
+ end
125
+
126
+ @stack << args[0]
127
+ end )
128
+
129
+ @dictionary.add_word( ['rolld'],
130
+ 'Stack',
131
+ '( a … -- … a ) move the element on top of the stack to a higher stack position',
132
+ proc do
133
+ args = stack_extract( [%i[numeric]] )
134
+ n = args[0][:value]
135
+ args = stack_extract( %i[any] * args[0][:value] )
136
+
137
+ args.reverse!
138
+
139
+ @stack << args[n - 1]
140
+
141
+ (0..(n - 2)).each do |i|
142
+ @stack << args[ i ]
143
+ end
144
+ end )
145
+
146
+ @dictionary.add_word( ['over'],
147
+ 'Stack',
148
+ '( a b -- a b a ) push a copy of the element in stack level 2 onto the stack',
149
+ proc do
150
+ run( '2 pick' )
151
+ end )
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RplLang
4
+ module Core
5
+ module Store
6
+ def populate_dictionary
7
+ super
8
+
9
+ @dictionary.add_word( ['▶', 'sto'],
10
+ 'Store',
11
+ '( content name -- ) store to variable',
12
+ proc do
13
+ args = stack_extract( [%i[name], :any] )
14
+
15
+ @dictionary.add_var( args[0][:value],
16
+ args[1] )
17
+ end )
18
+
19
+ @dictionary.add_word( ['rcl'],
20
+ 'Store',
21
+ '( name -- … ) push content of variable name onto stack',
22
+ proc do
23
+ args = stack_extract( [%i[name]] )
24
+
25
+ content = @dictionary.lookup( args[0][:value] )
26
+
27
+ @stack << content unless content.nil?
28
+ end )
29
+
30
+ @dictionary.add_word( ['purge'],
31
+ 'Store',
32
+ '( name -- ) delete variable',
33
+ proc do
34
+ args = stack_extract( [%i[name]] )
35
+
36
+ @dictionary.remove_var( args[0][:value] )
37
+ end )
38
+
39
+ @dictionary.add_word( ['vars'],
40
+ 'Store',
41
+ '( -- […] ) list variables',
42
+ proc do
43
+ @stack << { type: :list,
44
+ value: (@dictionary.vars.keys + @dictionary.local_vars_layers.reduce([]) { |memo, layer| memo + layer.keys }).map { |name| { type: :name, value: name } } }
45
+ end )
46
+
47
+ @dictionary.add_word( ['clusr'],
48
+ 'Store',
49
+ '( -- ) delete all variables',
50
+ proc do
51
+ @dictionary.remove_all_vars
52
+ end )
53
+
54
+ @dictionary.add_word( ['sto+'],
55
+ 'Store',
56
+ '( a n -- ) add content to variable\'s value',
57
+ proc do
58
+ run( '
59
+ dup type "name" ==
60
+ « swap »
61
+ ift
62
+ over rcl + swap sto' )
63
+ end )
64
+
65
+ @dictionary.add_word( ['sto-'],
66
+ 'Store',
67
+ '( a n -- ) subtract content to variable\'s value',
68
+ proc do
69
+ run( '
70
+ dup type "name" ==
71
+ « swap »
72
+ ift
73
+ over rcl swap - swap sto' )
74
+ end )
75
+
76
+ @dictionary.add_word( ['sto×', 'sto*'],
77
+ 'Store',
78
+ '( a n -- ) multiply content of variable\'s value',
79
+ proc do
80
+ run( '
81
+ dup type "name" ==
82
+ « swap »
83
+ ift
84
+ over rcl * swap sto' )
85
+ end )
86
+
87
+ @dictionary.add_word( ['sto÷', 'sto/'],
88
+ 'Store',
89
+ '( a n -- ) divide content of variable\'s value',
90
+ proc do
91
+ run( '
92
+ dup type "name" ==
93
+ « swap »
94
+ ift
95
+ over rcl swap / swap sto' )
96
+ end )
97
+
98
+ @dictionary.add_word( ['sneg'],
99
+ 'Store',
100
+ '( a n -- ) negate content of variable\'s value',
101
+ proc do
102
+ run( 'dup rcl chs swap sto' )
103
+ end )
104
+
105
+ @dictionary.add_word( ['sinv'],
106
+ 'Store',
107
+ '( a n -- ) invert content of variable\'s value',
108
+ proc do
109
+ run( 'dup rcl inv swap sto' )
110
+ end )
111
+
112
+ @dictionary.add_word( ['↴', 'lsto'],
113
+ 'Program',
114
+ '( content name -- ) store to local variable',
115
+ proc do
116
+ args = stack_extract( [%i[name], :any] )
117
+
118
+ @dictionary.add_local_var( args[0][:value],
119
+ args[1] )
120
+ end )
121
+ end
122
+ end
123
+ end
124
+ end