rpl.rb/lib/core/operations.rb
2022-02-11 15:46:47 +01:00

354 lines
16 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# frozen_string_literal: true
module RplLang
module Core
module Operations
def populate_dictionary
super
# Usual operations on reals and complexes
@dictionary.add_word( ['+'],
'Usual operations on reals and complexes',
'( a b -- c ) addition',
proc do
addable = %i[numeric string name list]
args = stack_extract( [addable, addable] )
# | + | 1 numeric | 1 string | 1 name | 1 list |
# |-----------+-----------+----------+--------+--------|
# | 0 numeric | numeric | string | name | list |
# | 0 string | string | string | string | list |
# | 0 name | string | string | name | list |
# | 0 list | list | list | list | list |
result = { type: case args[0][:type]
when :numeric
args[1][:type]
when :string
case args[1][:type]
when :list
:list
else
:string
end
when :name
case args[1][:type]
when :name
:name
when :list
:list
else
:string
end
when :list
:list
else
args[0][:type]
end }
if result[:type] == :list
args.each do |elt|
next unless elt[:type] != :list
elt_copy = Marshal.load(Marshal.dump( elt ))
elt[:type] = :list
elt[:value] = [elt_copy]
end
end
value_to_string = lambda do |e|
if e[:type] == :numeric
stringify( e )
else
e[:value].to_s
end
end
result[:value] = if %i[name string].include?( result[:type] )
"#{value_to_string.call( args[1] )}#{value_to_string.call( args[0] )}"
else
args[1][:value] + args[0][:value]
end
result[:base] = args[0][:base] if result[:type] == :numeric
@stack << result
end )
@dictionary.add_word( ['-'],
'Usual operations on reals and complexes',
'( a b -- c ) subtraction',
proc do
args = stack_extract( [%i[numeric], %i[numeric]] )
@stack << { type: :numeric, base: infer_resulting_base( args ),
value: args[1][:value] - args[0][:value] }
end )
@dictionary.add_word( ['chs'],
'Usual operations on reals and complexes',
'( a -- b ) negate',
proc do
run( '-1 *' )
end )
@dictionary.add_word( ['×', '*'],
'Usual operations on reals and complexes',
'( a b -- c ) multiplication',
proc do
args = stack_extract( [%i[numeric], %i[numeric]] )
@stack << { type: :numeric, base: infer_resulting_base( args ),
value: args[1][:value] * args[0][:value] }
end )
@dictionary.add_word( ['÷', '/'],
'Usual operations on reals and complexes',
'( a b -- c ) division',
proc do
args = stack_extract( [%i[numeric], %i[numeric]] )
@stack << { type: :numeric, base: infer_resulting_base( args ),
value: args[1][:value] / args[0][:value] }
end )
@dictionary.add_word( ['inv'],
'Usual operations on reals and complexes',
'( a -- b ) invert numeric',
proc do
run( '1.0 swap /' )
end )
@dictionary.add_word( ['^'],
'Usual operations on reals and complexes',
'( a b -- c ) a to the power of b',
proc do
args = stack_extract( [%i[numeric], %i[numeric]] )
@stack << { type: :numeric, base: infer_resulting_base( args ),
value: args[1][:value]**args[0][:value] }
end )
@dictionary.add_word( ['√', 'sqrt'],
'Usual operations on reals and complexes',
'( a -- b ) square root',
proc do
args = stack_extract( [%i[numeric]] )
@stack << { type: :numeric, base: infer_resulting_base( args ),
value: BigMath.sqrt( BigDecimal( args[0][:value], precision ), precision ) }
end )
@dictionary.add_word( ['²', 'sq'],
'Usual operations on reals and complexes',
'( a -- b ) square',
proc do
run( 'dup ×')
end )
@dictionary.add_word( ['abs'],
'Usual operations on reals and complexes',
'( a -- b ) absolute value',
proc do
args = stack_extract( [%i[numeric]] )
@stack << { type: :numeric, base: infer_resulting_base( args ),
value: args[0][:value].abs }
end )
@dictionary.add_word( ['dec'],
'Usual operations on reals and complexes',
'( a -- a ) set numeric\'s base to 10',
proc do
run( '10 base' )
end )
@dictionary.add_word( ['hex'],
'Usual operations on reals and complexes',
'( a -- a ) set numeric\'s base to 16',
proc do
run( '16 base' )
end )
@dictionary.add_word( ['bin'],
'Usual operations on reals and complexes',
'( a -- a ) set numeric\'s base to 2',
proc do
run( '2 base' )
end )
@dictionary.add_word( ['base'],
'Usual operations on reals and complexes',
'( a b -- a ) set numeric\'s base to b',
proc do
args = stack_extract( [%i[numeric], %i[numeric]] )
args[1][:base] = args[0][:value]
@stack << args[1]
end )
@dictionary.add_word( ['sign'],
'Usual operations on reals and complexes',
'( a -- b ) sign of element',
proc do
args = stack_extract( [%i[numeric]] )
value = if args[0][:value].positive?
1
elsif args[0][:value].negative?
-1
else
0
end
@stack << { type: :numeric, base: infer_resulting_base( args ),
value: value }
end )
# Operations on reals
@dictionary.add_word( ['%'],
'Operations on reals',
'( a b -- c ) b% of a',
proc do
args = stack_extract( [%i[numeric], %i[numeric]] )
@stack << { type: :numeric,
base: infer_resulting_base( args ),
value: args[0][:value] * ( args[1][:value] / 100.0 ) }
end )
@dictionary.add_word( ['%CH'],
'Operations on reals',
'( a b -- c ) b is c% of a',
proc do
args = stack_extract( [%i[numeric], %i[numeric]] )
@stack << { type: :numeric,
base: infer_resulting_base( args ),
value: 100.0 * ( args[0][:value] / args[1][:value] ) }
end )
@dictionary.add_word( ['mod'],
'Operations on reals',
'( a b -- c ) modulo',
proc do
args = stack_extract( [%i[numeric], %i[numeric]] )
@stack << { type: :numeric,
base: infer_resulting_base( args ),
value: args[1][:value] % args[0][:value] }
end )
@dictionary.add_word( ['!', 'fact'],
'Operations on reals',
'( a -- b ) factorial',
proc do
args = stack_extract( [%i[numeric]] )
@stack << { type: :numeric,
base: infer_resulting_base( args ),
value: Math.gamma( args[0][:value] ) }
end )
@dictionary.add_word( ['floor'],
'Operations on reals',
'( a -- b ) highest integer under a',
proc do
args = stack_extract( [%i[numeric]] )
@stack << { type: :numeric,
base: infer_resulting_base( args ),
value: args[0][:value].floor }
end )
@dictionary.add_word( ['ceil'],
'Operations on reals',
'( a -- b ) highest integer over a',
proc do
args = stack_extract( [%i[numeric]] )
@stack << { type: :numeric,
base: infer_resulting_base( args ),
value: args[0][:value].ceil }
end )
@dictionary.add_word( ['min'],
'Operations on reals',
'( a b -- a/b ) leave lowest of a or b',
proc do
args = stack_extract( [%i[numeric], %i[numeric]] )
@stack << ( args[0][:value] < args[1][:value] ? args[0] : args[1] )
end )
@dictionary.add_word( ['max'],
'Operations on reals',
'( a b -- a/b ) leave highest of a or b',
proc do
args = stack_extract( [%i[numeric], %i[numeric]] )
@stack << ( args[0][:value] > args[1][:value] ? args[0] : args[1] )
end )
# @dictionary.add_word( ['mant'],
# 'Operations on reals',
# '',
# proc { __todo } ) # mantissa of a real number
# @dictionary.add_word( ['xpon'],
# 'Operations on reals',
# '',
# proc { __todo } ) # exponant of a real number
@dictionary.add_word( ['ip'],
'Operations on reals',
'( n -- i ) integer part',
proc do
run( 'dup fp -' )
end )
@dictionary.add_word( ['fp'],
'Operations on reals',
'( n -- f ) fractional part',
proc do
args = stack_extract( [%i[numeric]] )
@stack << { type: :numeric,
base: infer_resulting_base( args ),
value: args[0][:value].frac }
end )
# OPERATIONS ON COMPLEXES
# @dictionary.add_word( ['re'],
# proc { __todo } ) # complex real part
# @dictionary.add_word( 'im',
# proc { __todo } ) # complex imaginary part
# @dictionary.add_word( ['conj'],
# proc { __todo } ) # complex conjugate
# @dictionary.add_word( 'arg',
# proc { __todo } ) # complex argument in radians
# @dictionary.add_word( ['c->r'],
# proc { __todo } ) # transform a complex in 2 reals
# @dictionary.add_word( 'c→r',
# proc { __todo } )
# @dictionary.add_word( ['r->c'],
# proc { __todo } ) # transform 2 reals in a complex
# @dictionary.add_word( 'r→c',
# proc { __todo } )
# @dictionary.add_word( ['p->r'],
# proc { __todo } ) # cartesian to polar
# @dictionary.add_word( 'p→r',
# proc { __todo } )
# @dictionary.add_word( ['r->p'],
# proc { __todo } ) # polar to cartesian
# @dictionary.add_word( 'r→p',
# proc { __todo } )
end
end
end
end