rpl 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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