rpl.rb/lib/language/operations.rb
Gwenhael Le Moine 655a14e36e
implement SIGN
2021-11-18 15:58:59 +01:00

132 lines
3.8 KiB
Ruby

module Rpn
module Core
module Operations
module_function
# addition
def add( stack )
addable = %i[numeric string name]
stack, args = Rpn::Core.stack_extract( stack, [addable, addable] )
result = { type: case args[0][:type]
when :name
:name
when :string
:string
when :numeric
if args[1][:type] == :numeric
:numeric
else
:string
end
end }
args.each do |elt|
elt[:value] = elt[:value][1..-2] unless elt[:type] == :numeric
end
result[:value] = case result[:type]
when :name
"'#{args[0][:value]}#{args[1][:value]}'"
when :string
"\"#{args[0][:value]}#{args[1][:value]}\""
when :numeric
args[0][:value] + args[1][:value]
end
stack << result
end
# substraction
def subtract( stack )
stack, args = Rpn::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
stack << { type: :numeric,
value: args[0][:value] - args[1][:value] }
end
# negation
def negate( stack )
stack, args = Rpn::Core.stack_extract( stack, [%i[numeric]] )
stack << { type: :numeric,
value: args[0][:value] * -1 }
end
# multiplication
def multiply( stack )
stack, args = Rpn::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
stack << { type: :numeric,
value: args[0][:value] * args[1][:value] }
end
# division
def divide( stack )
stack, args = Rpn::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
raise 'Division by 0' if args[0][:value].zero?
stack << { type: :numeric,
value: args[0][:value] / args[1][:value] }
end
# inverse
def inverse( stack )
stack, args = Rpn::Core.stack_extract( stack, [%i[numeric]] )
raise 'Division by 0' if args[0][:value].zero?
stack << { type: :numeric,
value: 1.0 / args[0][:value] }
end
# power
def power( stack )
stack, args = Rpn::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
stack << { type: :numeric,
value: args[0][:value]**args[1][:value] }
end
# rpn_square root
def sqrt( stack )
stack, args = Rpn::Core.stack_extract( stack, [%i[numeric]] )
stack << { type: :numeric,
value: BigMath.sqrt( BigDecimal( args[0][:value] ), Rpn::Core.precision ) }
end
# rpn_square
def sq( stack )
stack, args = Rpn::Core.stack_extract( stack, [%i[numeric]] )
stack << { type: :numeric,
value: args[0][:value] * args[0][:value] }
end
# absolute value
def abs( stack )
stack, args = Rpn::Core.stack_extract( stack, [%i[numeric]] )
stack << { type: :numeric,
value: args[0][:value].abs }
end
# 1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0
def sign( stack )
stack, args = Rpn::Core.stack_extract( stack, [%i[numeric]] )
value = if args[0][:value].positive?
1
elsif args[0][:value].negative?
-1
else
0
end
stack << { type: :numeric,
value: value }
end
end
end
end