implements SQRT PREC DEFAULT TYPE TIME DATE TICKS
This commit is contained in:
parent
db02abb114
commit
1e4dafb1d4
7 changed files with 129 additions and 7 deletions
18
lib/core.rb
18
lib/core.rb
|
@ -1,12 +1,30 @@
|
|||
require 'bigdecimal/math'
|
||||
|
||||
require_relative './language/general'
|
||||
require_relative './language/mode'
|
||||
require_relative './language/operations'
|
||||
require_relative './language/program'
|
||||
require_relative './language/stack'
|
||||
require_relative './language/time-date'
|
||||
|
||||
module Rpn
|
||||
module Core
|
||||
module_function
|
||||
|
||||
include BigMath
|
||||
|
||||
def precision
|
||||
@precision
|
||||
end
|
||||
|
||||
def precision=( value )
|
||||
@precision = value
|
||||
end
|
||||
|
||||
def init
|
||||
@precision = 12 # default precision for math operations
|
||||
end
|
||||
|
||||
def stack_extract( stack, needs )
|
||||
raise 'Not enough elements' if stack.size < needs.size
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ module Rpn
|
|||
add( '/', proc { |stack| Rpn::Core::Operations.divide( stack ) } )
|
||||
add( 'inv', proc { |stack| Rpn::Core::Operations.inverse( stack ) } )
|
||||
add( '^', proc { |stack| Rpn::Core::Operations.power( stack ) } )
|
||||
add( 'sqrt', proc { |stack| Rpn::Core.__todo( stack ) } ) # rpn_square root
|
||||
add( 'sqrt', proc { |stack| Rpn::Core::Operations.sqrt( stack ) } )
|
||||
add( 'sq', proc { |stack| Rpn::Core.__todo( stack ) } ) # rpn_square
|
||||
add( 'abs', proc { |stack| Rpn::Core.__todo( stack ) } ) # absolute value
|
||||
add( 'dec', proc { |stack| Rpn::Core.__todo( stack ) } ) # decimal representation
|
||||
|
@ -75,10 +75,10 @@ module Rpn
|
|||
add( 'std', proc { |stack| Rpn::Core.__todo( stack ) } ) # standard floating numbers representation. ex: std
|
||||
add( 'fix', proc { |stack| Rpn::Core.__todo( stack ) } ) # fixed point representation. ex: 6 fix
|
||||
add( 'sci', proc { |stack| Rpn::Core.__todo( stack ) } ) # scientific floating point representation. ex: 20 sci
|
||||
add( 'prec', proc { |stack| Rpn::Core.__todo( stack ) } ) # set float precision in bits. ex: 256 prec
|
||||
add( 'prec', proc { |stack| Rpn::Core::Mode.prec( stack ) } )
|
||||
add( 'round', proc { |stack| Rpn::Core.__todo( stack ) } ) # set float rounding mode. ex: ["nearest", "toward zero", "toward +inf", "toward -inf", "away from zero"] round
|
||||
add( 'default', proc { |stack| Rpn::Core.__todo( stack ) } ) # set float representation and precision to default
|
||||
add( 'type', proc { |stack| Rpn::Core.__todo( stack ) } ) # show type of stack first entry
|
||||
add( 'default', proc { |stack| Rpn::Core::Mode.default( stack ) } )
|
||||
add( 'type', proc { |stack| Rpn::Core::Mode.type( stack ) } )
|
||||
|
||||
# TEST
|
||||
add( '>', proc { |stack| Rpn::Core.__todo( stack ) } ) # binary operator >
|
||||
|
@ -165,9 +165,9 @@ module Rpn
|
|||
add( 'atanh', proc { |stack| Rpn::Core.__todo( stack ) } ) # inverse hyperbolic tangent
|
||||
|
||||
# TIME AND DATE
|
||||
add( 'time', proc { |stack| Rpn::Core.__todo( stack ) } ) # time in local format
|
||||
add( 'date', proc { |stack| Rpn::Core.__todo( stack ) } ) # date in local format
|
||||
add( 'ticks', proc { |stack| Rpn::Core.__todo( stack ) } ) # system tick in µs
|
||||
add( 'time', proc { |stack| Rpn::Core::TimeDate.time( stack ) } )
|
||||
add( 'date', proc { |stack| Rpn::Core::TimeDate.date( stack ) } )
|
||||
add( 'ticks', proc { |stack| Rpn::Core::TimeDate.ticks( stack ) } )
|
||||
end
|
||||
|
||||
def add( name, implementation )
|
||||
|
|
33
lib/language/mode.rb
Normal file
33
lib/language/mode.rb
Normal file
|
@ -0,0 +1,33 @@
|
|||
module Rpn
|
||||
module Core
|
||||
module Mode
|
||||
module_function
|
||||
|
||||
# set float precision in bits. ex: 256 prec
|
||||
def prec( stack )
|
||||
stack, args = Rpn::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
Rpn::Core.precision = args[0][:value]
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# set float representation and precision to default
|
||||
def default( stack )
|
||||
Rpn::Core.precision = 12
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# show type of stack first entry
|
||||
def type( stack )
|
||||
stack, args = Rpn::Core.stack_extract( stack, [:any] )
|
||||
|
||||
stack << args[0]
|
||||
stack << { type: :string,
|
||||
value: args[0][:type].to_s }
|
||||
stack
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -88,6 +88,14 @@ module Rpn
|
|||
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
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
29
lib/language/time-date.rb
Normal file
29
lib/language/time-date.rb
Normal file
|
@ -0,0 +1,29 @@
|
|||
require 'date'
|
||||
|
||||
module Rpn
|
||||
module Core
|
||||
module TimeDate
|
||||
module_function
|
||||
|
||||
# time in local format
|
||||
def time( stack )
|
||||
stack << { type: :string,
|
||||
value: Time.now.to_s }
|
||||
end
|
||||
|
||||
# date in local format
|
||||
def date( stack )
|
||||
stack << { type: :string,
|
||||
value: Date.today.to_s }
|
||||
end
|
||||
|
||||
# system tick in µs
|
||||
def ticks( stack )
|
||||
ticks_since_epoch = Time.utc( 1, 1, 1 ).to_i * 10_000_000
|
||||
now = Time.now
|
||||
stack << { type: :numeric,
|
||||
value: now.to_i * 10_000_000 + now.nsec / 100 - ticks_since_epoch }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
2
repl.rb
2
repl.rb
|
@ -15,6 +15,8 @@ module Rpn
|
|||
@dictionary = Dictionary.new
|
||||
@parser = Parser.new
|
||||
@runner = Runner.new
|
||||
|
||||
Rpn::Core.init
|
||||
end
|
||||
|
||||
def run
|
||||
|
|
32
spec/language_time-date_spec.rb
Normal file
32
spec/language_time-date_spec.rb
Normal file
|
@ -0,0 +1,32 @@
|
|||
# coding: utf-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'test/unit'
|
||||
|
||||
require_relative '../lib/core'
|
||||
|
||||
class TestParser < Test::Unit::TestCase
|
||||
def test_time
|
||||
now = Time.now.to_s
|
||||
stack = Rpn::Core::TimeDate.time( [] )
|
||||
|
||||
assert_equal [{ value: now, type: :string }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_date
|
||||
now = Date.today.to_s
|
||||
stack = Rpn::Core::TimeDate.date( [] )
|
||||
|
||||
assert_equal [{ value: now, type: :string }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_ticks
|
||||
stack = Rpn::Core::TimeDate.ticks( [] )
|
||||
|
||||
# TODO: better test, but how?
|
||||
assert_equal :numeric,
|
||||
stack[0][:type]
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue