Compare commits
4 commits
ca6b79a8ad
...
d537087088
Author | SHA1 | Date | |
---|---|---|---|
|
d537087088 | ||
|
c6fc0b3bc8 | ||
|
ff48cef22a | ||
|
cfcbcc7ce5 |
34 changed files with 1228 additions and 1159 deletions
24
language.rb
Normal file
24
language.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require './lib/core'
|
||||
require './lib/dictionary'
|
||||
require './lib/parser'
|
||||
require './lib/runner'
|
||||
|
||||
module Rpl
|
||||
class Language
|
||||
attr_reader :stack
|
||||
|
||||
def initialize( stack = [] )
|
||||
@stack = stack
|
||||
@dictionary = Rpl::Lang::Dictionary.new
|
||||
@parser = Rpl::Lang::Parser.new
|
||||
@runner = Rpl::Lang::Runner.new
|
||||
end
|
||||
|
||||
def run( input )
|
||||
@stack, @dictionary = @runner.run_input( @parser.parse_input( input ),
|
||||
@stack, @dictionary )
|
||||
end
|
||||
end
|
||||
end
|
27
lib/core.rb
27
lib/core.rb
|
@ -1,18 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'bigdecimal/math'
|
||||
|
||||
require_relative './language/branch'
|
||||
require_relative './language/general'
|
||||
require_relative './language/mode'
|
||||
require_relative './language/operations'
|
||||
require_relative './language/program'
|
||||
require_relative './language/stack'
|
||||
require_relative './language/string'
|
||||
require_relative './language/test'
|
||||
require_relative './language/time-date'
|
||||
require_relative './language/trig'
|
||||
require_relative './language/logs'
|
||||
require_relative './core/branch'
|
||||
require_relative './core/general'
|
||||
require_relative './core/mode'
|
||||
require_relative './core/operations'
|
||||
require_relative './core/program'
|
||||
require_relative './core/stack'
|
||||
require_relative './core/store'
|
||||
require_relative './core/string'
|
||||
require_relative './core/test'
|
||||
require_relative './core/time-date'
|
||||
require_relative './core/trig'
|
||||
require_relative './core/logs'
|
||||
|
||||
module Rpl
|
||||
module Lang
|
||||
module Core
|
||||
module_function
|
||||
|
||||
|
@ -46,4 +50,5 @@ module Rpl
|
|||
stack
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
23
lib/core/branch.rb
Normal file
23
lib/core/branch.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Rpl
|
||||
module Lang
|
||||
module Core
|
||||
module_function
|
||||
|
||||
# similar to if-then-end, <test-instruction> <true-instruction> ift
|
||||
def ift( stack, dictionary )
|
||||
ifte( stack << { type: :word, value: 'nop' }, dictionary )
|
||||
end
|
||||
|
||||
# similar to if-then-else-end, <test-instruction> <true-instruction> <false-instruction> ifte
|
||||
def ifte( stack, dictionary )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[program word], %i[program word], %i[boolean]] )
|
||||
|
||||
stack << args[ args[2][:value] ? 1 : 0 ]
|
||||
|
||||
Rpl::Lang::Core.eval( stack, dictionary )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
14
lib/core/general.rb
Normal file
14
lib/core/general.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Rpl
|
||||
module Lang
|
||||
module Core
|
||||
module_function
|
||||
|
||||
# no operation
|
||||
def nop( stack )
|
||||
stack
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
35
lib/core/mode.rb
Normal file
35
lib/core/mode.rb
Normal file
|
@ -0,0 +1,35 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Rpl
|
||||
module Lang
|
||||
module Core
|
||||
module_function
|
||||
|
||||
# set float precision in bits. ex: 256 prec
|
||||
def prec( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
Rpl::Lang::Core.precision = args[0][:value]
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# set float representation and precision to default
|
||||
def default( stack )
|
||||
Rpl::Lang::Core.precision = 12
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# show type of stack first entry
|
||||
def type( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [:any] )
|
||||
|
||||
stack << args[0]
|
||||
stack << { type: :string,
|
||||
value: args[0][:type].to_s }
|
||||
stack
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
246
lib/core/operations.rb
Normal file
246
lib/core/operations.rb
Normal file
|
@ -0,0 +1,246 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Rpl
|
||||
module Lang
|
||||
module Core
|
||||
module_function
|
||||
|
||||
# addition
|
||||
def add( stack )
|
||||
addable = %i[numeric string name]
|
||||
stack, args = Rpl::Core.stack_extract( stack, [addable, addable] )
|
||||
|
||||
result = { type: case args[1][:type]
|
||||
when :name
|
||||
:name
|
||||
when :string
|
||||
:string
|
||||
when :numeric
|
||||
if args[0][: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[1][:value]}#{args[0][:value]}'"
|
||||
when :string
|
||||
"\"#{args[1][:value]}#{args[0][:value]}\""
|
||||
when :numeric
|
||||
args[1][:value] + args[0][:value]
|
||||
end
|
||||
|
||||
result[:base] = 10 if result[:type] == :numeric # TODO: what if operands have other bases ?
|
||||
|
||||
stack << result
|
||||
end
|
||||
|
||||
# substraction
|
||||
def subtract( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: args[1][:value] - args[0][:value] }
|
||||
end
|
||||
|
||||
# negation
|
||||
def negate( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: args[0][:value] * -1 }
|
||||
end
|
||||
|
||||
# multiplication
|
||||
def multiply( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: args[1][:value] * args[0][:value] }
|
||||
end
|
||||
|
||||
# division
|
||||
def divide( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
raise 'Division by 0' if args[0][:value].zero?
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: args[1][:value] / args[0][:value] }
|
||||
end
|
||||
|
||||
# inverse
|
||||
def inverse( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
raise 'Division by 0' if args[0][:value].zero?
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: 1.0 / args[0][:value] }
|
||||
end
|
||||
|
||||
# power
|
||||
def power( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: args[1][:value]**args[0][:value] }
|
||||
end
|
||||
|
||||
# rpn_square root
|
||||
def sqrt( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: BigMath.sqrt( BigDecimal( args[0][:value] ), Rpl::Core.precision ) }
|
||||
end
|
||||
|
||||
# rpn_square
|
||||
def sq( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: args[0][:value] * args[0][:value] }
|
||||
end
|
||||
|
||||
# absolute value
|
||||
def abs( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: args[0][:value].abs }
|
||||
end
|
||||
|
||||
# decimal representation
|
||||
def dec( stack )
|
||||
base( stack << { type: :numeric, base: 10, value: 10 } )
|
||||
end
|
||||
|
||||
# hexadecimal representation
|
||||
def hex( stack )
|
||||
base( stack << { type: :numeric, base: 10, value: 16 } )
|
||||
end
|
||||
|
||||
# binary representation
|
||||
def bin( stack )
|
||||
base( stack << { type: :numeric, base: 10, value: 2 } )
|
||||
end
|
||||
|
||||
# arbitrary base representation
|
||||
def base( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
args[1][:base] = args[0][:value]
|
||||
|
||||
stack << args[1]
|
||||
end
|
||||
|
||||
# 1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0
|
||||
def sign( stack )
|
||||
stack, args = Rpl::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, base: 10,
|
||||
value: value }
|
||||
end
|
||||
|
||||
# OPERATIONS ON REALS
|
||||
|
||||
# percent
|
||||
def percent( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: args[0][:value] * ( args[1][:value] / 100.0 ) }
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# inverse percent
|
||||
def inverse_percent( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: 100.0 * ( args[0][:value] / args[1][:value] ) }
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# modulo
|
||||
def mod( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: args[1][:value] % args[0][:value] }
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# n! for integer n or Gamma(x+1) for fractional x
|
||||
def fact( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: Math.gamma( args[0][:value] ) }
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# largest number <=
|
||||
def floor( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: args[0][:value].floor }
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# smallest number >=
|
||||
def ceil( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: args[0][:value].ceil }
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# min of 2 real numbers
|
||||
def min( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
stack << ( args[0][:value] < args[1][:value] ? args[0] : args[1] )
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# max of 2 real numbers
|
||||
def max( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
stack << ( args[0][:value] > args[1][:value] ? args[0] : args[1] )
|
||||
|
||||
stack
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
24
lib/core/program.rb
Normal file
24
lib/core/program.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Rpl
|
||||
module Lang
|
||||
module Core
|
||||
module_function
|
||||
|
||||
# evaluate (run) a program, or recall a variable. ex: 'my_prog' eval
|
||||
def eval( stack, dictionary )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[program word name]] )
|
||||
|
||||
# we trim enclosing «»
|
||||
preparsed_input = args[0][:type] == :word ? args[0][:value] : args[0][:value][1..-2]
|
||||
parsed_input = Rpl::Lang::Parser.new.parse_input( preparsed_input )
|
||||
|
||||
stack, _dictionary = Rpl::Lang::Runner.new.run_input( parsed_input,
|
||||
stack, dictionary )
|
||||
# TODO: check that STO actually updates dictionary
|
||||
|
||||
stack
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
132
lib/core/stack.rb
Normal file
132
lib/core/stack.rb
Normal file
|
@ -0,0 +1,132 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Rpl
|
||||
module Lang
|
||||
module Core
|
||||
module_function
|
||||
|
||||
# swap 2 first stack entries
|
||||
def swap( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, %i[any any] )
|
||||
|
||||
stack << args[0] << args[1]
|
||||
end
|
||||
|
||||
# drop first stack entry
|
||||
def drop( stack )
|
||||
dropn( stack << { type: :numeric, base: 10, value: 1 } )
|
||||
end
|
||||
|
||||
# drop 2 first stack entries
|
||||
def drop2( stack )
|
||||
dropn( stack << { type: :numeric, base: 10, value: 2 } )
|
||||
end
|
||||
|
||||
# drop n first stack entries
|
||||
def dropn( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[numeric]] )
|
||||
stack, _args = Rpl::Lang::Core.stack_extract( stack, %i[any] * args[0][:value] )
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# drop all stack entries
|
||||
def del( _stack )
|
||||
[]
|
||||
end
|
||||
|
||||
# rotate 3 first stack entries
|
||||
def rot( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, %i[any any any] )
|
||||
|
||||
stack << args[1] << args[0] << args[2]
|
||||
end
|
||||
|
||||
# duplicate first stack entry
|
||||
def dup( stack )
|
||||
dupn( stack << { type: :numeric, base: 10, value: 1 } )
|
||||
end
|
||||
|
||||
# duplicate 2 first stack entries
|
||||
def dup2( stack )
|
||||
dupn( stack << { type: :numeric, base: 10, value: 2 } )
|
||||
end
|
||||
|
||||
# duplicate n first stack entries
|
||||
def dupn( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[numeric]] )
|
||||
n = args[0][:value]
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, %i[any] * args[0][:value] )
|
||||
|
||||
args.reverse!
|
||||
|
||||
2.times do
|
||||
n.times.each do |i|
|
||||
stack << args[ i ]
|
||||
end
|
||||
end
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# push a copy of the given stack level onto the stack
|
||||
def pick( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[numeric]] )
|
||||
n = args[0][:value]
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, %i[any] * args[0][:value] )
|
||||
|
||||
args.reverse!
|
||||
|
||||
n.times.each do |i|
|
||||
stack << args[ i ]
|
||||
end
|
||||
stack << args[0]
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# give stack depth
|
||||
def depth( stack )
|
||||
stack << { type: :numeric, base: 10, value: stack.size }
|
||||
end
|
||||
|
||||
# move a stack entry to the top of the stack
|
||||
def roll( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[numeric]] )
|
||||
n = args[0][:value]
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, %i[any] * args[0][:value] )
|
||||
|
||||
args.reverse!
|
||||
|
||||
(1..(n - 1)).each do |i|
|
||||
stack << args[ i ]
|
||||
end
|
||||
stack << args[0]
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# move the element on top of the stack to a higher stack position
|
||||
def rolld( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[numeric]] )
|
||||
n = args[0][:value]
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, %i[any] * args[0][:value] )
|
||||
|
||||
args.reverse!
|
||||
|
||||
stack << args[n - 1]
|
||||
|
||||
(0..(n - 2)).each do |i|
|
||||
stack << args[ i ]
|
||||
end
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# push a copy of the element in stack level 2 onto the stack
|
||||
def over( stack )
|
||||
pick( stack << { type: :numeric, base: 10, value: 2 } )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
69
lib/core/string.rb
Normal file
69
lib/core/string.rb
Normal file
|
@ -0,0 +1,69 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Rpl
|
||||
module Lang
|
||||
module Core
|
||||
module_function
|
||||
|
||||
# convert an object into a string
|
||||
def to_string( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [:any] )
|
||||
|
||||
stack << { type: :string,
|
||||
value: args[0][:value].to_s }
|
||||
end
|
||||
|
||||
# convert a string into an object
|
||||
def from_string( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[string]] )
|
||||
|
||||
parsed_input = Rpl::Lang::Parser.new.parse_input( args[0][:value] )
|
||||
|
||||
stack + parsed_input
|
||||
end
|
||||
|
||||
# convert ASCII character code in stack level 1 into a string
|
||||
def chr( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
stack << { type: :string,
|
||||
value: args[0][:value].chr }
|
||||
end
|
||||
|
||||
# return ASCII code of the first character of the string in stack level 1 as a real number
|
||||
def num( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[string]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: args[0][:value].ord }
|
||||
end
|
||||
|
||||
# return the length of the string
|
||||
def size( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[string]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: args[0][:value].length }
|
||||
end
|
||||
|
||||
# search for the string in level 1 within the string in level 2
|
||||
def pos( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[string], %i[string]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: args[1][:value].index( args[0][:value] ) }
|
||||
end
|
||||
|
||||
# return a substring of the string in level 3
|
||||
def sub( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[numeric], %i[numeric], %i[string]] )
|
||||
|
||||
stack << { type: :string,
|
||||
value: args[2][:value][args[1][:value]..args[0][:value]] }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
113
lib/core/test.rb
Normal file
113
lib/core/test.rb
Normal file
|
@ -0,0 +1,113 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Rpl
|
||||
module Lang
|
||||
module Core
|
||||
module_function
|
||||
|
||||
# binary operator >
|
||||
def greater_than( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, %i[any any] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] > args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# binary operator >=
|
||||
def greater_or_equal_than( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, %i[any any] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] >= args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# binary operator <
|
||||
def less_than( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, %i[any any] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] < args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# binary operator <=
|
||||
def less_or_equal_than( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, %i[any any] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] <= args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# boolean operator != (different)
|
||||
def different( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, %i[any any] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] != args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# boolean operator and
|
||||
def and( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[boolean], %i[boolean]] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] && args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# boolean operator or
|
||||
def or( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[boolean], %i[boolean]] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] || args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# boolean operator xor
|
||||
def xor( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[boolean], %i[boolean]] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] ^ args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# boolean operator not
|
||||
def not( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, [%i[boolean]] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: !args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# boolean operator same (equal)
|
||||
def same( stack )
|
||||
stack, args = Rpl::Lang::Core.stack_extract( stack, %i[any any] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] == args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# true boolean
|
||||
def true( stack )
|
||||
stack << { type: :boolean,
|
||||
value: true }
|
||||
stack
|
||||
end
|
||||
|
||||
# false boolean
|
||||
def false( stack )
|
||||
stack << { type: :boolean,
|
||||
value: false }
|
||||
stack
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
32
lib/core/time-date.rb
Normal file
32
lib/core/time-date.rb
Normal file
|
@ -0,0 +1,32 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'date'
|
||||
|
||||
module Rpl
|
||||
module Lang
|
||||
module Core
|
||||
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,
|
||||
base: 10,
|
||||
value: now.to_i * 10_000_000 + now.nsec / 100 - ticks_since_epoch }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,192 +1,193 @@
|
|||
# coding: utf-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Rpl
|
||||
module Lang
|
||||
class Dictionary
|
||||
def initialize
|
||||
@parser = Parser.new
|
||||
@words = {}
|
||||
|
||||
# GENERAL
|
||||
add( 'nop', proc { |stack| Rpl::Core.nop( stack ) } )
|
||||
add( 'help', proc { |stack| Rpl::Core.__todo( stack ) } ) # this help message
|
||||
add( 'quit', proc { |stack| Rpl::Core.__todo( stack ) } ) # quit software
|
||||
add( 'version', proc { |stack| Rpl::Core.__todo( stack ) } ) # show rpn version
|
||||
add( 'uname', proc { |stack| Rpl::Core.__todo( stack ) } ) # show rpn complete identification string
|
||||
add( 'history', proc { |stack| Rpl::Core.__todo( stack ) } ) # see commands history
|
||||
add( 'nop', proc { |stack| Rpl::Lang::Core.nop( stack ) } )
|
||||
add( 'help', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # this help message
|
||||
add( 'quit', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # quit software
|
||||
add( 'version', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # show rpn version
|
||||
add( 'uname', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # show rpn complete identification string
|
||||
add( 'history', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # see commands history
|
||||
|
||||
# STACK
|
||||
add( 'swap', proc { |stack| Rpl::Core.swap( stack ) } )
|
||||
add( 'drop', proc { |stack| Rpl::Core.drop( stack ) } )
|
||||
add( 'drop2', proc { |stack| Rpl::Core.drop2( stack ) } )
|
||||
add( 'dropn', proc { |stack| Rpl::Core.dropn( stack ) } )
|
||||
add( 'del', proc { |stack| Rpl::Core.del( stack ) } )
|
||||
add( 'rot', proc { |stack| Rpl::Core.rot( stack ) } )
|
||||
add( 'dup', proc { |stack| Rpl::Core.dup( stack ) } )
|
||||
add( 'dup2', proc { |stack| Rpl::Core.dup2( stack ) } )
|
||||
add( 'dupn', proc { |stack| Rpl::Core.dupn( stack ) } )
|
||||
add( 'pick', proc { |stack| Rpl::Core.pick( stack ) } )
|
||||
add( 'depth', proc { |stack| Rpl::Core.depth( stack ) } )
|
||||
add( 'roll', proc { |stack| Rpl::Core.roll( stack ) } )
|
||||
add( 'rolld', proc { |stack| Rpl::Core.rolld( stack ) } )
|
||||
add( 'over', proc { |stack| Rpl::Core.over( stack ) } )
|
||||
add( 'swap', proc { |stack| Rpl::Lang::Core.swap( stack ) } )
|
||||
add( 'drop', proc { |stack| Rpl::Lang::Core.drop( stack ) } )
|
||||
add( 'drop2', proc { |stack| Rpl::Lang::Core.drop2( stack ) } )
|
||||
add( 'dropn', proc { |stack| Rpl::Lang::Core.dropn( stack ) } )
|
||||
add( 'del', proc { |stack| Rpl::Lang::Core.del( stack ) } )
|
||||
add( 'rot', proc { |stack| Rpl::Lang::Core.rot( stack ) } )
|
||||
add( 'dup', proc { |stack| Rpl::Lang::Core.dup( stack ) } )
|
||||
add( 'dup2', proc { |stack| Rpl::Lang::Core.dup2( stack ) } )
|
||||
add( 'dupn', proc { |stack| Rpl::Lang::Core.dupn( stack ) } )
|
||||
add( 'pick', proc { |stack| Rpl::Lang::Core.pick( stack ) } )
|
||||
add( 'depth', proc { |stack| Rpl::Lang::Core.depth( stack ) } )
|
||||
add( 'roll', proc { |stack| Rpl::Lang::Core.roll( stack ) } )
|
||||
add( 'rolld', proc { |stack| Rpl::Lang::Core.rolld( stack ) } )
|
||||
add( 'over', proc { |stack| Rpl::Lang::Core.over( stack ) } )
|
||||
|
||||
# USUAL OPERATIONS ON REALS AND COMPLEXES
|
||||
add( '+', proc { |stack| Rpl::Core.add( stack ) } )
|
||||
add( '-', proc { |stack| Rpl::Core.subtract( stack ) } )
|
||||
add( 'chs', proc { |stack| Rpl::Core.negate( stack ) } )
|
||||
add( '*', proc { |stack| Rpl::Core.multiply( stack ) } )
|
||||
add( '×', proc { |stack| Rpl::Core.multiply( stack ) } ) # alias
|
||||
add( '/', proc { |stack| Rpl::Core.divide( stack ) } )
|
||||
add( '÷', proc { |stack| Rpl::Core.divide( stack ) } ) # alias
|
||||
add( 'inv', proc { |stack| Rpl::Core.inverse( stack ) } )
|
||||
add( '^', proc { |stack| Rpl::Core.power( stack ) } )
|
||||
add( 'sqrt', proc { |stack| Rpl::Core.sqrt( stack ) } )
|
||||
add( 'sq', proc { |stack| Rpl::Core.sq( stack ) } )
|
||||
add( 'abs', proc { |stack| Rpl::Core.abs( stack ) } )
|
||||
add( 'dec', proc { |stack| Rpl::Core.dec( stack ) } )
|
||||
add( 'hex', proc { |stack| Rpl::Core.hex( stack ) } )
|
||||
add( 'bin', proc { |stack| Rpl::Core.bin( stack ) } )
|
||||
add( 'base', proc { |stack| Rpl::Core.base( stack ) } )
|
||||
add( 'sign', proc { |stack| Rpl::Core.sign( stack ) } )
|
||||
add( '+', proc { |stack| Rpl::Lang::Core.add( stack ) } )
|
||||
add( '-', proc { |stack| Rpl::Lang::Core.subtract( stack ) } )
|
||||
add( 'chs', proc { |stack| Rpl::Lang::Core.negate( stack ) } )
|
||||
add( '*', proc { |stack| Rpl::Lang::Core.multiply( stack ) } )
|
||||
add( '×', proc { |stack| Rpl::Lang::Core.multiply( stack ) } ) # alias
|
||||
add( '/', proc { |stack| Rpl::Lang::Core.divide( stack ) } )
|
||||
add( '÷', proc { |stack| Rpl::Lang::Core.divide( stack ) } ) # alias
|
||||
add( 'inv', proc { |stack| Rpl::Lang::Core.inverse( stack ) } )
|
||||
add( '^', proc { |stack| Rpl::Lang::Core.power( stack ) } )
|
||||
add( 'sqrt', proc { |stack| Rpl::Lang::Core.sqrt( stack ) } )
|
||||
add( 'sq', proc { |stack| Rpl::Lang::Core.sq( stack ) } )
|
||||
add( 'abs', proc { |stack| Rpl::Lang::Core.abs( stack ) } )
|
||||
add( 'dec', proc { |stack| Rpl::Lang::Core.dec( stack ) } )
|
||||
add( 'hex', proc { |stack| Rpl::Lang::Core.hex( stack ) } )
|
||||
add( 'bin', proc { |stack| Rpl::Lang::Core.bin( stack ) } )
|
||||
add( 'base', proc { |stack| Rpl::Lang::Core.base( stack ) } )
|
||||
add( 'sign', proc { |stack| Rpl::Lang::Core.sign( stack ) } )
|
||||
|
||||
# OPERATIONS ON REALS
|
||||
add( '%', proc { |stack| Rpl::Core.percent( stack ) } )
|
||||
add( '%CH', proc { |stack| Rpl::Core.inverse_percent( stack ) } )
|
||||
add( 'mod', proc { |stack| Rpl::Core.mod( stack ) } )
|
||||
add( 'fact', proc { |stack| Rpl::Core.fact( stack ) } )
|
||||
add( 'mant', proc { |stack| Rpl::Core.__todo( stack ) } ) # mantissa of a real number
|
||||
add( 'xpon', proc { |stack| Rpl::Core.__todo( stack ) } ) # exponant of a real number
|
||||
add( 'floor', proc { |stack| Rpl::Core.floor( stack ) } )
|
||||
add( 'ceil', proc { |stack| Rpl::Core.ceil( stack ) } )
|
||||
add( 'ip', proc { |stack| Rpl::Core.__todo( stack ) } ) # integer part
|
||||
add( 'fp', proc { |stack| Rpl::Core.__todo( stack ) } ) # fractional part
|
||||
add( 'min', proc { |stack| Rpl::Core.min( stack ) } )
|
||||
add( 'max', proc { |stack| Rpl::Core.max( stack ) } )
|
||||
add( '%', proc { |stack| Rpl::Lang::Core.percent( stack ) } )
|
||||
add( '%CH', proc { |stack| Rpl::Lang::Core.inverse_percent( stack ) } )
|
||||
add( 'mod', proc { |stack| Rpl::Lang::Core.mod( stack ) } )
|
||||
add( 'fact', proc { |stack| Rpl::Lang::Core.fact( stack ) } )
|
||||
add( 'mant', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # mantissa of a real number
|
||||
add( 'xpon', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # exponant of a real number
|
||||
add( 'floor', proc { |stack| Rpl::Lang::Core.floor( stack ) } )
|
||||
add( 'ceil', proc { |stack| Rpl::Lang::Core.ceil( stack ) } )
|
||||
add( 'ip', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # integer part
|
||||
add( 'fp', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # fractional part
|
||||
add( 'min', proc { |stack| Rpl::Lang::Core.min( stack ) } )
|
||||
add( 'max', proc { |stack| Rpl::Lang::Core.max( stack ) } )
|
||||
|
||||
# OPERATIONS ON COMPLEXES
|
||||
add( 're', proc { |stack| Rpl::Core.__todo( stack ) } ) # complex real part
|
||||
add( 'im', proc { |stack| Rpl::Core.__todo( stack ) } ) # complex imaginary part
|
||||
add( 'conj', proc { |stack| Rpl::Core.__todo( stack ) } ) # complex conjugate
|
||||
add( 'arg', proc { |stack| Rpl::Core.__todo( stack ) } ) # complex argument in radians
|
||||
add( 'c->r', proc { |stack| Rpl::Core.__todo( stack ) } ) # transform a complex in 2 reals
|
||||
add( 'c→r', proc { |stack| Rpl::Core.__todo( stack ) } ) # alias
|
||||
add( 'r->c', proc { |stack| Rpl::Core.__todo( stack ) } ) # transform 2 reals in a complex
|
||||
add( 'r→c', proc { |stack| Rpl::Core.__todo( stack ) } ) # alias
|
||||
add( 'p->r', proc { |stack| Rpl::Core.__todo( stack ) } ) # cartesian to polar
|
||||
add( 'p→r', proc { |stack| Rpl::Core.__todo( stack ) } ) # alias
|
||||
add( 'r->p', proc { |stack| Rpl::Core.__todo( stack ) } ) # polar to cartesian
|
||||
add( 'r→p', proc { |stack| Rpl::Core.__todo( stack ) } ) # alias
|
||||
add( 're', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # complex real part
|
||||
add( 'im', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # complex imaginary part
|
||||
add( 'conj', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # complex conjugate
|
||||
add( 'arg', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # complex argument in radians
|
||||
add( 'c->r', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # transform a complex in 2 reals
|
||||
add( 'c→r', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # alias
|
||||
add( 'r->c', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # transform 2 reals in a complex
|
||||
add( 'r→c', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # alias
|
||||
add( 'p->r', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # cartesian to polar
|
||||
add( 'p→r', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # alias
|
||||
add( 'r->p', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # polar to cartesian
|
||||
add( 'r→p', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # alias
|
||||
|
||||
# MODE
|
||||
add( 'std', proc { |stack| Rpl::Core.__todo( stack ) } ) # standard floating numbers representation. ex: std
|
||||
add( 'fix', proc { |stack| Rpl::Core.__todo( stack ) } ) # fixed point representation. ex: 6 fix
|
||||
add( 'sci', proc { |stack| Rpl::Core.__todo( stack ) } ) # scientific floating point representation. ex: 20 sci
|
||||
add( 'prec', proc { |stack| Rpl::Core.prec( stack ) } )
|
||||
add( 'round', proc { |stack| Rpl::Core.__todo( stack ) } ) # set float rounding mode. ex: ["nearest", "toward zero", "toward +inf", "toward -inf", "away from zero"] round
|
||||
add( 'default', proc { |stack| Rpl::Core.default( stack ) } )
|
||||
add( 'type', proc { |stack| Rpl::Core.type( stack ) } )
|
||||
add( 'std', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # standard floating numbers representation. ex: std
|
||||
add( 'fix', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # fixed point representation. ex: 6 fix
|
||||
add( 'sci', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # scientific floating point representation. ex: 20 sci
|
||||
add( 'prec', proc { |stack| Rpl::Lang::Core.prec( stack ) } )
|
||||
add( 'round', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # set float rounding mode. ex: ["nearest", "toward zero", "toward +inf", "toward -inf", "away from zero"] round
|
||||
add( 'default', proc { |stack| Rpl::Lang::Core.default( stack ) } )
|
||||
add( 'type', proc { |stack| Rpl::Lang::Core.type( stack ) } )
|
||||
|
||||
# TEST
|
||||
add( '>', proc { |stack| Rpl::Core.greater_than( stack ) } )
|
||||
add( '>=', proc { |stack| Rpl::Core.greater_or_equal_than( stack ) } )
|
||||
add( '≥', proc { |stack| Rpl::Core.greater_or_equal_than( stack ) } ) # alias
|
||||
add( '<', proc { |stack| Rpl::Core.less_than( stack ) } )
|
||||
add( '<=', proc { |stack| Rpl::Core.less_or_equal_than( stack ) } )
|
||||
add( '≤', proc { |stack| Rpl::Core.less_or_equal_than( stack ) } ) # alias
|
||||
add( '!=', proc { |stack| Rpl::Core.different( stack ) } )
|
||||
add( '≠', proc { |stack| Rpl::Core.different( stack ) } ) # alias
|
||||
add( '==', proc { |stack| Rpl::Core.same( stack ) } ) # alias
|
||||
add( 'and', proc { |stack| Rpl::Core.and( stack ) } )
|
||||
add( 'or', proc { |stack| Rpl::Core.or( stack ) } )
|
||||
add( 'xor', proc { |stack| Rpl::Core.xor( stack ) } )
|
||||
add( 'not', proc { |stack| Rpl::Core.not( stack ) } )
|
||||
add( 'same', proc { |stack| Rpl::Core.same( stack ) } )
|
||||
add( 'true', proc { |stack| Rpl::Core.true( stack ) } ) # specific
|
||||
add( 'false', proc { |stack| Rpl::Core.false( stack ) } ) # specific
|
||||
add( '>', proc { |stack| Rpl::Lang::Core.greater_than( stack ) } )
|
||||
add( '>=', proc { |stack| Rpl::Lang::Core.greater_or_equal_than( stack ) } )
|
||||
add( '≥', proc { |stack| Rpl::Lang::Core.greater_or_equal_than( stack ) } ) # alias
|
||||
add( '<', proc { |stack| Rpl::Lang::Core.less_than( stack ) } )
|
||||
add( '<=', proc { |stack| Rpl::Lang::Core.less_or_equal_than( stack ) } )
|
||||
add( '≤', proc { |stack| Rpl::Lang::Core.less_or_equal_than( stack ) } ) # alias
|
||||
add( '!=', proc { |stack| Rpl::Lang::Core.different( stack ) } )
|
||||
add( '≠', proc { |stack| Rpl::Lang::Core.different( stack ) } ) # alias
|
||||
add( '==', proc { |stack| Rpl::Lang::Core.same( stack ) } ) # alias
|
||||
add( 'and', proc { |stack| Rpl::Lang::Core.and( stack ) } )
|
||||
add( 'or', proc { |stack| Rpl::Lang::Core.or( stack ) } )
|
||||
add( 'xor', proc { |stack| Rpl::Lang::Core.xor( stack ) } )
|
||||
add( 'not', proc { |stack| Rpl::Lang::Core.not( stack ) } )
|
||||
add( 'same', proc { |stack| Rpl::Lang::Core.same( stack ) } )
|
||||
add( 'true', proc { |stack| Rpl::Lang::Core.true( stack ) } ) # specific
|
||||
add( 'false', proc { |stack| Rpl::Lang::Core.false( stack ) } ) # specific
|
||||
|
||||
# STRING
|
||||
add( '->str', proc { |stack| Rpl::Core.to_string( stack ) } )
|
||||
add( '→str', proc { |stack| Rpl::Core.to_string( stack ) } ) # alias
|
||||
add( 'str->', proc { |stack| Rpl::Core.from_string( stack ) } )
|
||||
add( 'str→', proc { |stack| Rpl::Core.from_string( stack ) } ) # alias
|
||||
add( 'chr', proc { |stack| Rpl::Core.chr( stack ) } )
|
||||
add( 'num', proc { |stack| Rpl::Core.num( stack ) } )
|
||||
add( 'size', proc { |stack| Rpl::Core.size( stack ) } )
|
||||
add( 'pos', proc { |stack| Rpl::Core.pos( stack ) } )
|
||||
add( 'sub', proc { |stack| Rpl::Core.sub( stack ) } )
|
||||
add( '->str', proc { |stack| Rpl::Lang::Core.to_string( stack ) } )
|
||||
add( '→str', proc { |stack| Rpl::Lang::Core.to_string( stack ) } ) # alias
|
||||
add( 'str->', proc { |stack| Rpl::Lang::Core.from_string( stack ) } )
|
||||
add( 'str→', proc { |stack| Rpl::Lang::Core.from_string( stack ) } ) # alias
|
||||
add( 'chr', proc { |stack| Rpl::Lang::Core.chr( stack ) } )
|
||||
add( 'num', proc { |stack| Rpl::Lang::Core.num( stack ) } )
|
||||
add( 'size', proc { |stack| Rpl::Lang::Core.size( stack ) } )
|
||||
add( 'pos', proc { |stack| Rpl::Lang::Core.pos( stack ) } )
|
||||
add( 'sub', proc { |stack| Rpl::Lang::Core.sub( stack ) } )
|
||||
|
||||
# BRANCH
|
||||
add( 'if', proc { |stack| Rpl::Core.__todo( stack ) } ) # if <test-instruction> then <true-instructions> else <false-instructions> end
|
||||
add( 'then', proc { |stack| Rpl::Core.__todo( stack ) } ) # used with if
|
||||
add( 'else', proc { |stack| Rpl::Core.__todo( stack ) } ) # used with if
|
||||
add( 'end', proc { |stack| Rpl::Core.__todo( stack ) } ) # used with various branch instructions
|
||||
add( 'start', proc { |stack| Rpl::Core.__todo( stack ) } ) # <start> <end> start <instructions> next|<step> step
|
||||
add( 'for', proc { |stack| Rpl::Core.__todo( stack ) } ) # <start> <end> for <variable> <instructions> next|<step> step
|
||||
add( 'next', proc { |stack| Rpl::Core.__todo( stack ) } ) # used with start and for
|
||||
add( 'step', proc { |stack| Rpl::Core.__todo( stack ) } ) # used with start and for
|
||||
add( 'ift', proc { |stack| Rpl::Core.ift( stack, self ) } )
|
||||
add( 'ifte', proc { |stack| Rpl::Core.ifte( stack, self ) } )
|
||||
add( 'do', proc { |stack| Rpl::Core.__todo( stack ) } ) # do <instructions> until <condition> end
|
||||
add( 'until', proc { |stack| Rpl::Core.__todo( stack ) } ) # used with do
|
||||
add( 'while', proc { |stack| Rpl::Core.__todo( stack ) } ) # while <test-instruction> repeat <loop-instructions> end
|
||||
add( 'repeat', proc { |stack| Rpl::Core.__todo( stack ) } ) # used with while
|
||||
add( 'if', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # if <test-instruction> then <true-instructions> else <false-instructions> end
|
||||
add( 'then', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # used with if
|
||||
add( 'else', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # used with if
|
||||
add( 'end', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # used with various branch instructions
|
||||
add( 'start', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # <start> <end> start <instructions> next|<step> step
|
||||
add( 'for', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # <start> <end> for <variable> <instructions> next|<step> step
|
||||
add( 'next', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # used with start and for
|
||||
add( 'step', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # used with start and for
|
||||
add( 'ift', proc { |stack| Rpl::Lang::Core.ift( stack, self ) } )
|
||||
add( 'ifte', proc { |stack| Rpl::Lang::Core.ifte( stack, self ) } )
|
||||
add( 'do', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # do <instructions> until <condition> end
|
||||
add( 'until', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # used with do
|
||||
add( 'while', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # while <test-instruction> repeat <loop-instructions> end
|
||||
add( 'repeat', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # used with while
|
||||
|
||||
# STORE
|
||||
add( 'sto', proc { |stack| Rpl::Core.__todo( stack ) } ) # store a variable. ex: 1 'name' sto
|
||||
add( '▶', proc { |stack| Rpl::Core.sto( stack ) } ) # alias
|
||||
add( 'rcl', proc { |stack| Rpl::Core.__todo( stack ) } ) # recall a variable. ex: 'name' rcl
|
||||
add( 'purge', proc { |stack| Rpl::Core.__todo( stack ) } ) # delete a variable. ex: 'name' purge
|
||||
add( 'vars', proc { |stack| Rpl::Core.__todo( stack ) } ) # list all variables
|
||||
add( 'clusr', proc { |stack| Rpl::Core.__todo( stack ) } ) # erase all variables
|
||||
add( 'edit', proc { |stack| Rpl::Core.__todo( stack ) } ) # edit a variable content
|
||||
add( 'sto+', proc { |stack| Rpl::Core.__todo( stack ) } ) # add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+
|
||||
add( 'sto-', proc { |stack| Rpl::Core.__todo( stack ) } ) # substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-
|
||||
add( 'sto*', proc { |stack| Rpl::Core.__todo( stack ) } ) # multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*
|
||||
add( 'sto/', proc { |stack| Rpl::Core.__todo( stack ) } ) # divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/
|
||||
add( 'sneg', proc { |stack| Rpl::Core.__todo( stack ) } ) # negate a variable. ex: 'name' sneg
|
||||
add( 'sinv', proc { |stack| Rpl::Core.__todo( stack ) } ) # inverse a variable. ex: 1 'name' sinv
|
||||
add( 'sto', proc { |stack| Rpl::Lang::Core.sto( stack ) } ) # store a variable. ex: 1 'name' sto
|
||||
add( '▶', proc { |stack| Rpl::Lang::Core.sto( stack ) } ) # alias
|
||||
add( 'rcl', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # recall a variable. ex: 'name' rcl
|
||||
add( 'purge', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # delete a variable. ex: 'name' purge
|
||||
add( 'vars', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # list all variables
|
||||
add( 'clusr', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # erase all variables
|
||||
add( 'edit', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # edit a variable content
|
||||
add( 'sto+', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+
|
||||
add( 'sto-', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-
|
||||
add( 'sto*', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*
|
||||
add( 'sto/', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/
|
||||
add( 'sneg', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # negate a variable. ex: 'name' sneg
|
||||
add( 'sinv', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # inverse a variable. ex: 1 'name' sinv
|
||||
|
||||
# PROGRAM
|
||||
add( 'eval', proc { |stack| Rpl::Core.eval( stack, self ) } )
|
||||
add( '->', proc { |stack| Rpl::Core.__todo( stack ) } ) # load program local variables. ex: << -> n m << 0 n m for i i + next >> >>
|
||||
add( '→', proc { |stack| Rpl::Core.__todo( stack ) } ) # alias
|
||||
add( 'eval', proc { |stack| Rpl::Lang::Core.eval( stack, self ) } )
|
||||
add( '->', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # load program local variables. ex: << -> n m << 0 n m for i i + next >> >>
|
||||
add( '→', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # alias
|
||||
|
||||
# TRIG ON REALS AND COMPLEXES
|
||||
add( 'pi', proc { |stack| Rpl::Core.pi( stack ) } )
|
||||
add( '𝛑', proc { |stack| Rpl::Core.pi( stack ) } ) # alias
|
||||
add( 'sin', proc { |stack| Rpl::Core.__todo( stack ) } ) # sinus
|
||||
add( 'asin', proc { |stack| Rpl::Core.__todo( stack ) } ) # arg sinus
|
||||
add( 'cos', proc { |stack| Rpl::Core.__todo( stack ) } ) # cosinus
|
||||
add( 'acos', proc { |stack| Rpl::Core.__todo( stack ) } ) # arg cosinus
|
||||
add( 'tan', proc { |stack| Rpl::Core.__todo( stack ) } ) # tangent
|
||||
add( 'atan', proc { |stack| Rpl::Core.__todo( stack ) } ) # arg tangent
|
||||
add( 'd->r', proc { |stack| Rpl::Core.__todo( stack ) } ) # convert degrees to radians
|
||||
add( 'd→r', proc { |stack| Rpl::Core.__todo( stack ) } ) # alias
|
||||
add( 'r->d', proc { |stack| Rpl::Core.__todo( stack ) } ) # convert radians to degrees
|
||||
add( 'r→d', proc { |stack| Rpl::Core.__todo( stack ) } ) # alias
|
||||
add( 'pi', proc { |stack| Rpl::Lang::Core.pi( stack ) } )
|
||||
add( '𝛑', proc { |stack| Rpl::Lang::Core.pi( stack ) } ) # alias
|
||||
add( 'sin', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # sinus
|
||||
add( 'asin', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # arg sinus
|
||||
add( 'cos', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # cosinus
|
||||
add( 'acos', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # arg cosinus
|
||||
add( 'tan', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # tangent
|
||||
add( 'atan', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # arg tangent
|
||||
add( 'd->r', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # convert degrees to radians
|
||||
add( 'd→r', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # alias
|
||||
add( 'r->d', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # convert radians to degrees
|
||||
add( 'r→d', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # alias
|
||||
|
||||
# LOGS ON REALS AND COMPLEXES
|
||||
add( 'e', proc { |stack| Rpl::Core.e( stack ) } )
|
||||
add( 'ℇ', proc { |stack| Rpl::Core.e( stack ) } ) # alias
|
||||
add( 'ln', proc { |stack| Rpl::Core.__todo( stack ) } ) # logarithm base e
|
||||
add( 'lnp1', proc { |stack| Rpl::Core.__todo( stack ) } ) # ln(1+x) which is useful when x is close to 0
|
||||
add( 'exp', proc { |stack| Rpl::Core.__todo( stack ) } ) # exponential
|
||||
add( 'expm', proc { |stack| Rpl::Core.__todo( stack ) } ) # exp(x)-1 which is useful when x is close to 0
|
||||
add( 'log10', proc { |stack| Rpl::Core.__todo( stack ) } ) # logarithm base 10
|
||||
add( 'alog10', proc { |stack| Rpl::Core.__todo( stack ) } ) # exponential base 10
|
||||
add( 'log2', proc { |stack| Rpl::Core.__todo( stack ) } ) # logarithm base 2
|
||||
add( 'alog2', proc { |stack| Rpl::Core.__todo( stack ) } ) # exponential base 2
|
||||
add( 'sinh', proc { |stack| Rpl::Core.__todo( stack ) } ) # hyperbolic sine
|
||||
add( 'asinh', proc { |stack| Rpl::Core.__todo( stack ) } ) # inverse hyperbolic sine
|
||||
add( 'cosh', proc { |stack| Rpl::Core.__todo( stack ) } ) # hyperbolic cosine
|
||||
add( 'acosh', proc { |stack| Rpl::Core.__todo( stack ) } ) # inverse hyperbolic cosine
|
||||
add( 'tanh', proc { |stack| Rpl::Core.__todo( stack ) } ) # hyperbolic tangent
|
||||
add( 'atanh', proc { |stack| Rpl::Core.__todo( stack ) } ) # inverse hyperbolic tangent
|
||||
add( 'e', proc { |stack| Rpl::Lang::Core.e( stack ) } )
|
||||
add( 'ℇ', proc { |stack| Rpl::Lang::Core.e( stack ) } ) # alias
|
||||
add( 'ln', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # logarithm base e
|
||||
add( 'lnp1', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # ln(1+x) which is useful when x is close to 0
|
||||
add( 'exp', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # exponential
|
||||
add( 'expm', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # exp(x)-1 which is useful when x is close to 0
|
||||
add( 'log10', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # logarithm base 10
|
||||
add( 'alog10', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # exponential base 10
|
||||
add( 'log2', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # logarithm base 2
|
||||
add( 'alog2', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # exponential base 2
|
||||
add( 'sinh', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # hyperbolic sine
|
||||
add( 'asinh', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # inverse hyperbolic sine
|
||||
add( 'cosh', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # hyperbolic cosine
|
||||
add( 'acosh', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # inverse hyperbolic cosine
|
||||
add( 'tanh', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # hyperbolic tangent
|
||||
add( 'atanh', proc { |stack| Rpl::Lang::Core.__todo( stack ) } ) # inverse hyperbolic tangent
|
||||
|
||||
# TIME AND DATE
|
||||
add( 'time', proc { |stack| Rpl::Core.time( stack ) } )
|
||||
add( 'date', proc { |stack| Rpl::Core.date( stack ) } )
|
||||
add( 'ticks', proc { |stack| Rpl::Core.ticks( stack ) } )
|
||||
add( 'time', proc { |stack| Rpl::Lang::Core.time( stack ) } )
|
||||
add( 'date', proc { |stack| Rpl::Lang::Core.date( stack ) } )
|
||||
add( 'ticks', proc { |stack| Rpl::Lang::Core.ticks( stack ) } )
|
||||
end
|
||||
|
||||
def add( name, implementation )
|
||||
|
@ -199,4 +200,5 @@ module Rpl
|
|||
|
||||
# TODO: alias
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
module Rpl
|
||||
module Core
|
||||
module_function
|
||||
|
||||
# similar to if-then-end, <test-instruction> <true-instruction> ift
|
||||
def ift( stack, dictionary )
|
||||
ifte( stack << { type: :word, value: 'nop' }, dictionary )
|
||||
end
|
||||
|
||||
# similar to if-then-else-end, <test-instruction> <true-instruction> <false-instruction> ifte
|
||||
def ifte( stack, dictionary )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[program word], %i[program word], %i[boolean]] )
|
||||
|
||||
stack << args[ args[2][:value] ? 1 : 0 ]
|
||||
|
||||
Rpl::Core.eval( stack, dictionary )
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,10 +0,0 @@
|
|||
module Rpl
|
||||
module Core
|
||||
module_function
|
||||
|
||||
# no operation
|
||||
def nop( stack )
|
||||
stack
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,31 +0,0 @@
|
|||
module Rpl
|
||||
module Core
|
||||
module_function
|
||||
|
||||
# set float precision in bits. ex: 256 prec
|
||||
def prec( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
Rpl::Core.precision = args[0][:value]
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# set float representation and precision to default
|
||||
def default( stack )
|
||||
Rpl::Core.precision = 12
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# show type of stack first entry
|
||||
def type( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [:any] )
|
||||
|
||||
stack << args[0]
|
||||
stack << { type: :string,
|
||||
value: args[0][:type].to_s }
|
||||
stack
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,242 +0,0 @@
|
|||
module Rpl
|
||||
module Core
|
||||
module_function
|
||||
|
||||
# addition
|
||||
def add( stack )
|
||||
addable = %i[numeric string name]
|
||||
stack, args = Rpl::Core.stack_extract( stack, [addable, addable] )
|
||||
|
||||
result = { type: case args[1][:type]
|
||||
when :name
|
||||
:name
|
||||
when :string
|
||||
:string
|
||||
when :numeric
|
||||
if args[0][: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[1][:value]}#{args[0][:value]}'"
|
||||
when :string
|
||||
"\"#{args[1][:value]}#{args[0][:value]}\""
|
||||
when :numeric
|
||||
args[1][:value] + args[0][:value]
|
||||
end
|
||||
|
||||
result[:base] = 10 if result[:type] == :numeric # TODO: what if operands have other bases ?
|
||||
|
||||
stack << result
|
||||
end
|
||||
|
||||
# substraction
|
||||
def subtract( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: args[1][:value] - args[0][:value] }
|
||||
end
|
||||
|
||||
# negation
|
||||
def negate( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: args[0][:value] * -1 }
|
||||
end
|
||||
|
||||
# multiplication
|
||||
def multiply( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: args[1][:value] * args[0][:value] }
|
||||
end
|
||||
|
||||
# division
|
||||
def divide( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
raise 'Division by 0' if args[0][:value].zero?
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: args[1][:value] / args[0][:value] }
|
||||
end
|
||||
|
||||
# inverse
|
||||
def inverse( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
raise 'Division by 0' if args[0][:value].zero?
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: 1.0 / args[0][:value] }
|
||||
end
|
||||
|
||||
# power
|
||||
def power( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: args[1][:value]**args[0][:value] }
|
||||
end
|
||||
|
||||
# rpn_square root
|
||||
def sqrt( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: BigMath.sqrt( BigDecimal( args[0][:value] ), Rpl::Core.precision ) }
|
||||
end
|
||||
|
||||
# rpn_square
|
||||
def sq( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: args[0][:value] * args[0][:value] }
|
||||
end
|
||||
|
||||
# absolute value
|
||||
def abs( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
stack << { type: :numeric, base: 10,
|
||||
value: args[0][:value].abs }
|
||||
end
|
||||
|
||||
# decimal representation
|
||||
def dec( stack )
|
||||
base( stack << { type: :numeric, base: 10, value: 10 } )
|
||||
end
|
||||
|
||||
# hexadecimal representation
|
||||
def hex( stack )
|
||||
base( stack << { type: :numeric, base: 10, value: 16 } )
|
||||
end
|
||||
|
||||
# binary representation
|
||||
def bin( stack )
|
||||
base( stack << { type: :numeric, base: 10, value: 2 } )
|
||||
end
|
||||
|
||||
# arbitrary base representation
|
||||
def base( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
args[1][:base] = args[0][:value]
|
||||
|
||||
stack << args[1]
|
||||
end
|
||||
|
||||
# 1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0
|
||||
def sign( stack )
|
||||
stack, args = Rpl::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, base: 10,
|
||||
value: value }
|
||||
end
|
||||
|
||||
# OPERATIONS ON REALS
|
||||
|
||||
# percent
|
||||
def percent( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: args[0][:value] * ( args[1][:value] / 100.0 ) }
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# inverse percent
|
||||
def inverse_percent( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: 100.0 * ( args[0][:value] / args[1][:value] ) }
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# modulo
|
||||
def mod( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: args[1][:value] % args[0][:value] }
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# n! for integer n or Gamma(x+1) for fractional x
|
||||
def fact( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: Math.gamma( args[0][:value] ) }
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# largest number <=
|
||||
def floor( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: args[0][:value].floor }
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# smallest number >=
|
||||
def ceil( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: args[0][:value].ceil }
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# min of 2 real numbers
|
||||
def min( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
stack << ( args[0][:value] < args[1][:value] ? args[0] : args[1] )
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# max of 2 real numbers
|
||||
def max( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
|
||||
|
||||
stack << ( args[0][:value] > args[1][:value] ? args[0] : args[1] )
|
||||
|
||||
stack
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,19 +0,0 @@
|
|||
module Rpl
|
||||
module Core
|
||||
module_function
|
||||
|
||||
# evaluate (run) a program, or recall a variable. ex: 'my_prog' eval
|
||||
def eval( stack, dictionary )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[program word name]] )
|
||||
|
||||
# we trim enclosing «»
|
||||
preparsed_input = args[0][:type] == :word ? args[0][:value] : args[0][:value][1..-2]
|
||||
parsed_input = Rpl::Parser.new.parse_input( preparsed_input )
|
||||
|
||||
stack, _dictionary = Rpl::Runner.new.run_input( stack, dictionary, parsed_input )
|
||||
# TODO: check that STO actually updates dictionary
|
||||
|
||||
stack
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,128 +0,0 @@
|
|||
module Rpl
|
||||
module Core
|
||||
module_function
|
||||
|
||||
# swap 2 first stack entries
|
||||
def swap( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, %i[any any] )
|
||||
|
||||
stack << args[0] << args[1]
|
||||
end
|
||||
|
||||
# drop first stack entry
|
||||
def drop( stack )
|
||||
dropn( stack << { type: :numeric, base: 10, value: 1 } )
|
||||
end
|
||||
|
||||
# drop 2 first stack entries
|
||||
def drop2( stack )
|
||||
dropn( stack << { type: :numeric, base: 10, value: 2 } )
|
||||
end
|
||||
|
||||
# drop n first stack entries
|
||||
def dropn( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
stack, _args = Rpl::Core.stack_extract( stack, %i[any] * args[0][:value] )
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# drop all stack entries
|
||||
def del( _stack )
|
||||
[]
|
||||
end
|
||||
|
||||
# rotate 3 first stack entries
|
||||
def rot( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, %i[any any any] )
|
||||
|
||||
stack << args[1] << args[0] << args[2]
|
||||
end
|
||||
|
||||
# duplicate first stack entry
|
||||
def dup( stack )
|
||||
dupn( stack << { type: :numeric, base: 10, value: 1 } )
|
||||
end
|
||||
|
||||
# duplicate 2 first stack entries
|
||||
def dup2( stack )
|
||||
dupn( stack << { type: :numeric, base: 10, value: 2 } )
|
||||
end
|
||||
|
||||
# duplicate n first stack entries
|
||||
def dupn( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
n = args[0][:value]
|
||||
stack, args = Rpl::Core.stack_extract( stack, %i[any] * args[0][:value] )
|
||||
|
||||
args.reverse!
|
||||
|
||||
2.times do
|
||||
n.times.each do |i|
|
||||
stack << args[ i ]
|
||||
end
|
||||
end
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# push a copy of the given stack level onto the stack
|
||||
def pick( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
n = args[0][:value]
|
||||
stack, args = Rpl::Core.stack_extract( stack, %i[any] * args[0][:value] )
|
||||
|
||||
args.reverse!
|
||||
|
||||
n.times.each do |i|
|
||||
stack << args[ i ]
|
||||
end
|
||||
stack << args[0]
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# give stack depth
|
||||
def depth( stack )
|
||||
stack << { type: :numeric, base: 10, value: stack.size }
|
||||
end
|
||||
|
||||
# move a stack entry to the top of the stack
|
||||
def roll( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
n = args[0][:value]
|
||||
stack, args = Rpl::Core.stack_extract( stack, %i[any] * args[0][:value] )
|
||||
|
||||
args.reverse!
|
||||
|
||||
(1..(n - 1)).each do |i|
|
||||
stack << args[ i ]
|
||||
end
|
||||
stack << args[0]
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# move the element on top of the stack to a higher stack position
|
||||
def rolld( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
n = args[0][:value]
|
||||
stack, args = Rpl::Core.stack_extract( stack, %i[any] * args[0][:value] )
|
||||
|
||||
args.reverse!
|
||||
|
||||
stack << args[n - 1]
|
||||
|
||||
(0..(n - 2)).each do |i|
|
||||
stack << args[ i ]
|
||||
end
|
||||
|
||||
stack
|
||||
end
|
||||
|
||||
# push a copy of the element in stack level 2 onto the stack
|
||||
def over( stack )
|
||||
pick( stack << { type: :numeric, base: 10, value: 2 } )
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,65 +0,0 @@
|
|||
module Rpl
|
||||
module Core
|
||||
module_function
|
||||
|
||||
# convert an object into a string
|
||||
def to_string( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [:any] )
|
||||
|
||||
stack << { type: :string,
|
||||
value: args[0][:value].to_s }
|
||||
end
|
||||
|
||||
# convert a string into an object
|
||||
def from_string( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[string]] )
|
||||
|
||||
parsed_input = Rpl::Parser.new.parse_input( args[0][:value] )
|
||||
|
||||
stack + parsed_input
|
||||
end
|
||||
|
||||
# convert ASCII character code in stack level 1 into a string
|
||||
def chr( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric]] )
|
||||
|
||||
stack << { type: :string,
|
||||
value: args[0][:value].chr }
|
||||
end
|
||||
|
||||
# return ASCII code of the first character of the string in stack level 1 as a real number
|
||||
def num( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[string]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: args[0][:value].ord }
|
||||
end
|
||||
|
||||
# return the length of the string
|
||||
def size( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[string]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: args[0][:value].length }
|
||||
end
|
||||
|
||||
# search for the string in level 1 within the string in level 2
|
||||
def pos( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[string], %i[string]] )
|
||||
|
||||
stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: args[1][:value].index( args[0][:value] ) }
|
||||
end
|
||||
|
||||
# return a substring of the string in level 3
|
||||
def sub( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric], %i[string]] )
|
||||
|
||||
stack << { type: :string,
|
||||
value: args[2][:value][args[1][:value]..args[0][:value]] }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,109 +0,0 @@
|
|||
module Rpl
|
||||
module Core
|
||||
module_function
|
||||
|
||||
# binary operator >
|
||||
def greater_than( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, %i[any any] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] > args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# binary operator >=
|
||||
def greater_or_equal_than( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, %i[any any] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] >= args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# binary operator <
|
||||
def less_than( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, %i[any any] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] < args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# binary operator <=
|
||||
def less_or_equal_than( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, %i[any any] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] <= args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# boolean operator != (different)
|
||||
def different( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, %i[any any] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] != args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# boolean operator and
|
||||
def and( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[boolean], %i[boolean]] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] && args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# boolean operator or
|
||||
def or( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[boolean], %i[boolean]] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] || args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# boolean operator xor
|
||||
def xor( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[boolean], %i[boolean]] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] ^ args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# boolean operator not
|
||||
def not( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, [%i[boolean]] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: !args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# boolean operator same (equal)
|
||||
def same( stack )
|
||||
stack, args = Rpl::Core.stack_extract( stack, %i[any any] )
|
||||
|
||||
stack << { type: :boolean,
|
||||
value: args[1][:value] == args[0][:value] }
|
||||
stack
|
||||
end
|
||||
|
||||
# true boolean
|
||||
def true( stack )
|
||||
stack << { type: :boolean,
|
||||
value: true }
|
||||
stack
|
||||
end
|
||||
|
||||
# false boolean
|
||||
def false( stack )
|
||||
stack << { type: :boolean,
|
||||
value: false }
|
||||
stack
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,28 +0,0 @@
|
|||
require 'date'
|
||||
|
||||
module Rpl
|
||||
module Core
|
||||
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,
|
||||
base: 10,
|
||||
value: now.to_i * 10_000_000 + now.nsec / 100 - ticks_since_epoch }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,7 @@
|
|||
# coding: utf-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Rpl
|
||||
module Lang
|
||||
class Parser
|
||||
def initialize; end
|
||||
|
||||
|
@ -85,4 +86,5 @@ module Rpl
|
|||
parsed_tree
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
# coding: utf-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Rpl
|
||||
module Lang
|
||||
class Runner
|
||||
def initialize; end
|
||||
|
||||
def run_input( stack, dictionary, input )
|
||||
def run_input( input, stack, dictionary )
|
||||
input.each do |elt|
|
||||
case elt[:type]
|
||||
when :word
|
||||
|
@ -23,4 +24,5 @@ module Rpl
|
|||
[stack, dictionary]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
24
repl.rb
24
repl.rb
|
@ -1,20 +1,12 @@
|
|||
# coding: utf-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'readline'
|
||||
|
||||
require './lib/core'
|
||||
require './lib/dictionary'
|
||||
require './lib/parser'
|
||||
require './lib/runner'
|
||||
require './language'
|
||||
|
||||
module Rpl
|
||||
class Repl
|
||||
class RplRepl
|
||||
def initialize
|
||||
@stack = []
|
||||
@dictionary = Dictionary.new
|
||||
@parser = Parser.new
|
||||
@runner = Runner.new
|
||||
@lang = Rpl::Language.new
|
||||
end
|
||||
|
||||
def run
|
||||
|
@ -34,8 +26,7 @@ module Rpl
|
|||
# Remove blank lines from history
|
||||
Readline::HISTORY.pop if input.empty?
|
||||
|
||||
@stack, @dictionary = @runner.run_input( @stack, @dictionary,
|
||||
@parser.parse_input( input ) )
|
||||
@lang.run( input )
|
||||
|
||||
print_stack
|
||||
end
|
||||
|
@ -60,13 +51,12 @@ module Rpl
|
|||
end
|
||||
|
||||
def print_stack
|
||||
stack_size = @stack.size
|
||||
stack_size = @lang.stack.size
|
||||
|
||||
@stack.each_with_index do |elt, i|
|
||||
@lang.stack.each_with_index do |elt, i|
|
||||
puts "#{stack_size - i}: #{format_element( elt )}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Rpl::Repl.new.run
|
||||
RplRepl.new.run
|
||||
|
|
|
@ -7,7 +7,7 @@ require_relative '../lib/core'
|
|||
|
||||
class TestParser < Test::Unit::TestCase
|
||||
def test_stack_extract
|
||||
stack, args = Rpl::Core.stack_extract [{ value: 1, type: :numeric },
|
||||
stack, args = Rpl::Lang::Core.stack_extract [{ value: 1, type: :numeric },
|
||||
{ value: 2, type: :numeric }],
|
||||
[:any]
|
||||
assert_equal [{ value: 1, type: :numeric }],
|
||||
|
@ -15,7 +15,7 @@ class TestParser < Test::Unit::TestCase
|
|||
assert_equal [{ value: 2, type: :numeric }],
|
||||
args
|
||||
|
||||
stack, args = Rpl::Core.stack_extract [{ value: 'test', type: :string },
|
||||
stack, args = Rpl::Lang::Core.stack_extract [{ value: 'test', type: :string },
|
||||
{ value: 2, type: :numeric }],
|
||||
[[:numeric], :any]
|
||||
assert_equal [],
|
||||
|
|
|
@ -10,18 +10,18 @@ require_relative '../lib/runner'
|
|||
|
||||
class TestLanguageBranch < Test::Unit::TestCase
|
||||
def test_ifte
|
||||
stack = Rpl::Core.ifte( [{ type: :boolean, value: true },
|
||||
stack = Rpl::Lang::Core.ifte( [{ type: :boolean, value: true },
|
||||
{ type: :program, value: '« 2 3 + »' },
|
||||
{ type: :program, value: '« 2 3 - »' }],
|
||||
Rpl::Dictionary.new )
|
||||
Rpl::Lang::Dictionary.new )
|
||||
|
||||
assert_equal [{ value: 5, type: :numeric, base: 10 }],
|
||||
stack
|
||||
|
||||
stack = Rpl::Core.ifte( [{ type: :boolean, value: false },
|
||||
stack = Rpl::Lang::Core.ifte( [{ type: :boolean, value: false },
|
||||
{ type: :program, value: '« 2 3 + »' },
|
||||
{ type: :program, value: '« 2 3 - »' }],
|
||||
Rpl::Dictionary.new )
|
||||
Rpl::Lang::Dictionary.new )
|
||||
|
||||
assert_equal [{ value: -1, type: :numeric, base: 10 }],
|
||||
stack
|
||||
|
|
|
@ -7,155 +7,155 @@ require_relative '../lib/core'
|
|||
|
||||
class TesttLanguageOperations < Test::Unit::TestCase
|
||||
def test_add
|
||||
stack = Rpl::Core.add [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.add [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 }]
|
||||
assert_equal [{ value: 3, type: :numeric, base: 10 }],
|
||||
stack
|
||||
|
||||
stack = Rpl::Core.add [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.add [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: '"a"', type: :string }]
|
||||
assert_equal [{ value: '"1a"', type: :string }],
|
||||
stack
|
||||
|
||||
stack = Rpl::Core.add [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.add [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: "'a'", type: :name }]
|
||||
assert_equal [{ value: '"1a"', type: :string }],
|
||||
stack
|
||||
|
||||
stack = Rpl::Core.add [{ value: "'a'", type: :name },
|
||||
stack = Rpl::Lang::Core.add [{ value: "'a'", type: :name },
|
||||
{ value: 1, type: :numeric, base: 10 }]
|
||||
assert_equal [{ value: "'a1'", type: :name }],
|
||||
stack
|
||||
|
||||
stack = Rpl::Core.add [{ value: "'a'", type: :name },
|
||||
stack = Rpl::Lang::Core.add [{ value: "'a'", type: :name },
|
||||
{ value: '"b"', type: :string }]
|
||||
assert_equal [{ value: "'ab'", type: :name }],
|
||||
stack
|
||||
|
||||
stack = Rpl::Core.add [{ value: "'a'", type: :name },
|
||||
stack = Rpl::Lang::Core.add [{ value: "'a'", type: :name },
|
||||
{ value: "'b'", type: :name }]
|
||||
assert_equal [{ value: "'ab'", type: :name }],
|
||||
stack
|
||||
|
||||
stack = Rpl::Core.add [{ value: '"a"', type: :string },
|
||||
stack = Rpl::Lang::Core.add [{ value: '"a"', type: :string },
|
||||
{ value: '"b"', type: :string }]
|
||||
assert_equal [{ value: '"ab"', type: :string }],
|
||||
stack
|
||||
|
||||
stack = Rpl::Core.add [{ value: '"a"', type: :string },
|
||||
stack = Rpl::Lang::Core.add [{ value: '"a"', type: :string },
|
||||
{ value: "'b'", type: :name }]
|
||||
assert_equal [{ value: '"ab"', type: :string }],
|
||||
stack
|
||||
|
||||
stack = Rpl::Core.add [{ value: '"a"', type: :string },
|
||||
stack = Rpl::Lang::Core.add [{ value: '"a"', type: :string },
|
||||
{ value: 1, type: :numeric, base: 10 }]
|
||||
assert_equal [{ value: '"a1"', type: :string }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_subtract
|
||||
stack = Rpl::Core.subtract [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.subtract [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 }]
|
||||
assert_equal [{ value: -1, type: :numeric, base: 10 }],
|
||||
stack
|
||||
|
||||
stack = Rpl::Core.subtract [{ value: 2, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.subtract [{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 1, type: :numeric, base: 10 }]
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_negate
|
||||
stack = Rpl::Core.negate [{ value: -1, type: :numeric, base: 10 }]
|
||||
stack = Rpl::Lang::Core.negate [{ value: -1, type: :numeric, base: 10 }]
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
stack
|
||||
|
||||
stack = Rpl::Core.negate [{ value: 1, type: :numeric, base: 10 }]
|
||||
stack = Rpl::Lang::Core.negate [{ value: 1, type: :numeric, base: 10 }]
|
||||
|
||||
assert_equal [{ value: -1, type: :numeric, base: 10 }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_multiply
|
||||
stack = Rpl::Core.multiply [{ value: 3, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.multiply [{ value: 3, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 }]
|
||||
assert_equal [{ value: 12, type: :numeric, base: 10 }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_divide
|
||||
stack = Rpl::Core.divide [{ value: 3.0, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.divide [{ value: 3.0, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 }]
|
||||
assert_equal [{ value: 0.75, type: :numeric, base: 10 }],
|
||||
stack
|
||||
|
||||
# stack = Rpl::Core.divide [{ value: 3, type: :numeric, base: 10 },
|
||||
# stack = Rpl::Lang::Core.divide [{ value: 3, type: :numeric, base: 10 },
|
||||
# { value: 4, type: :numeric, base: 10 }]
|
||||
# assert_equal [{ value: 0.75, type: :numeric, base: 10 }],
|
||||
# stack
|
||||
end
|
||||
|
||||
def test_inverse
|
||||
stack = Rpl::Core.inverse [{ value: 4, type: :numeric, base: 10 }]
|
||||
stack = Rpl::Lang::Core.inverse [{ value: 4, type: :numeric, base: 10 }]
|
||||
assert_equal [{ value: 0.25, type: :numeric, base: 10 }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_power
|
||||
stack = Rpl::Core.power [{ value: 3, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.power [{ value: 3, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 }]
|
||||
assert_equal [{ value: 81, type: :numeric, base: 10 }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_sqrt
|
||||
stack = Rpl::Core.sqrt [{ value: 16, type: :numeric, base: 10 }]
|
||||
stack = Rpl::Lang::Core.sqrt [{ value: 16, type: :numeric, base: 10 }]
|
||||
assert_equal [{ value: 4, type: :numeric, base: 10 }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_sq
|
||||
stack = Rpl::Core.sq [{ value: 4, type: :numeric, base: 10 }]
|
||||
stack = Rpl::Lang::Core.sq [{ value: 4, type: :numeric, base: 10 }]
|
||||
assert_equal [{ value: 16, type: :numeric, base: 10 }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_abs
|
||||
stack = Rpl::Core.abs [{ value: -1, type: :numeric, base: 10 }]
|
||||
stack = Rpl::Lang::Core.abs [{ value: -1, type: :numeric, base: 10 }]
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
stack
|
||||
|
||||
stack = Rpl::Core.abs [{ value: 1, type: :numeric, base: 10 }]
|
||||
stack = Rpl::Lang::Core.abs [{ value: 1, type: :numeric, base: 10 }]
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_dec
|
||||
stack = Rpl::Core.dec [{ value: 1, type: :numeric, base: 16 }]
|
||||
stack = Rpl::Lang::Core.dec [{ value: 1, type: :numeric, base: 16 }]
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_hex
|
||||
stack = Rpl::Core.hex [{ value: 1, type: :numeric, base: 10 }]
|
||||
stack = Rpl::Lang::Core.hex [{ value: 1, type: :numeric, base: 10 }]
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 16 }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_bin
|
||||
stack = Rpl::Core.bin [{ value: 1, type: :numeric, base: 10 }]
|
||||
stack = Rpl::Lang::Core.bin [{ value: 1, type: :numeric, base: 10 }]
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 2 }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_base
|
||||
stack = Rpl::Core.base [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.base [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 31, type: :numeric, base: 10 }]
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 31 }],
|
||||
|
@ -163,16 +163,16 @@ class TesttLanguageOperations < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_sign
|
||||
stack = Rpl::Core.sign [{ value: -10, type: :numeric, base: 10 }]
|
||||
stack = Rpl::Lang::Core.sign [{ value: -10, type: :numeric, base: 10 }]
|
||||
|
||||
assert_equal [{ value: -1, type: :numeric, base: 10 }],
|
||||
stack
|
||||
|
||||
stack = Rpl::Core.sign [{ value: 10, type: :numeric, base: 10 }]
|
||||
stack = Rpl::Lang::Core.sign [{ value: 10, type: :numeric, base: 10 }]
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
stack
|
||||
stack = Rpl::Core.sign [{ value: 0, type: :numeric, base: 10 }]
|
||||
stack = Rpl::Lang::Core.sign [{ value: 0, type: :numeric, base: 10 }]
|
||||
|
||||
assert_equal [{ value: 0, type: :numeric, base: 10 }],
|
||||
stack
|
||||
|
|
|
@ -10,24 +10,31 @@ require_relative '../lib/runner'
|
|||
|
||||
class TestLanguageProgram < Test::Unit::TestCase
|
||||
def test_eval
|
||||
stack = Rpl::Core.eval( [{ value: '« 2 dup * dup »', type: :program }], Rpl::Dictionary.new )
|
||||
stack = Rpl::Lang::Core.eval( [{ value: '« 2 dup * dup »', type: :program }], Rpl::Lang::Dictionary.new )
|
||||
|
||||
assert_equal [{ value: 4, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 }],
|
||||
stack
|
||||
|
||||
stack = Rpl::Core.eval( [{ value: 4, type: :numeric, base: 10 },
|
||||
{ value: "'dup'", type: :name }], Rpl::Dictionary.new )
|
||||
stack = Rpl::Lang::Core.eval( [{ value: 4, type: :numeric, base: 10 },
|
||||
{ value: "'dup'", type: :name }], Rpl::Lang::Dictionary.new )
|
||||
|
||||
assert_equal [{ value: 4, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 }],
|
||||
stack
|
||||
|
||||
stack = Rpl::Core.eval( [{ value: 4, type: :numeric, base: 10 },
|
||||
{ value: 'dup', type: :word }], Rpl::Dictionary.new )
|
||||
stack = Rpl::Lang::Core.eval( [{ value: 4, type: :numeric, base: 10 },
|
||||
{ value: 'dup', type: :word }], Rpl::Lang::Dictionary.new )
|
||||
|
||||
assert_equal [{ value: 4, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_sto
|
||||
stack = Rpl::Lang::Core.sto( [{ value: '« 2 dup »', type: :program },
|
||||
{ value: "'quatre'", type: :name }], Rpl::Lang::Dictionary.new )
|
||||
|
||||
assert_equal [], stack
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,7 +7,7 @@ require_relative '../lib/core'
|
|||
|
||||
class TestLanguageStack < Test::Unit::TestCase
|
||||
def test_swap
|
||||
stack = Rpl::Core.swap [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.swap [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 }]
|
||||
assert_equal [{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 1, type: :numeric, base: 10 }],
|
||||
|
@ -15,21 +15,21 @@ class TestLanguageStack < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_drop
|
||||
stack = Rpl::Core.drop [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.drop [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 }]
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_drop2
|
||||
stack = Rpl::Core.drop2 [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.drop2 [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 }]
|
||||
assert_equal [],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_dropn
|
||||
stack = Rpl::Core.dropn [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.dropn [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 3, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 },
|
||||
|
@ -39,14 +39,14 @@ class TestLanguageStack < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_del
|
||||
stack = Rpl::Core.del [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.del [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 }]
|
||||
assert_equal [],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_rot
|
||||
stack = Rpl::Core.rot [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.rot [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 3, type: :numeric, base: 10 }]
|
||||
assert_equal [{ value: 2, type: :numeric, base: 10 },
|
||||
|
@ -56,7 +56,7 @@ class TestLanguageStack < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_dup
|
||||
stack = Rpl::Core.dup [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.dup [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 }]
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
|
@ -65,7 +65,7 @@ class TestLanguageStack < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_dup2
|
||||
stack = Rpl::Core.dup2 [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.dup2 [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 }]
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
|
@ -75,7 +75,7 @@ class TestLanguageStack < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_dupn
|
||||
stack = Rpl::Core.dupn [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.dupn [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 3, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 },
|
||||
|
@ -91,7 +91,7 @@ class TestLanguageStack < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_pick
|
||||
stack = Rpl::Core.pick [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.pick [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 3, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 },
|
||||
|
@ -105,11 +105,11 @@ class TestLanguageStack < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_depth
|
||||
stack = Rpl::Core.depth []
|
||||
stack = Rpl::Lang::Core.depth []
|
||||
assert_equal [{ value: 0, type: :numeric, base: 10 }],
|
||||
stack
|
||||
|
||||
stack = Rpl::Core.depth [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.depth [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 }]
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
|
@ -118,7 +118,7 @@ class TestLanguageStack < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_roll
|
||||
stack = Rpl::Core.roll [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.roll [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 3, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 },
|
||||
|
@ -131,7 +131,7 @@ class TestLanguageStack < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_rolld
|
||||
stack = Rpl::Core.rolld [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.rolld [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 },
|
||||
{ value: 3, type: :numeric, base: 10 },
|
||||
|
@ -144,7 +144,7 @@ class TestLanguageStack < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_over
|
||||
stack = Rpl::Core.over [{ value: 1, type: :numeric, base: 10 },
|
||||
stack = Rpl::Lang::Core.over [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 3, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 }]
|
||||
|
|
|
@ -8,19 +8,19 @@ require_relative '../lib/parser'
|
|||
|
||||
class TestLanguageString < Test::Unit::TestCase
|
||||
def test_to_string
|
||||
stack = Rpl::Core.to_string( [{ value: 2, type: :numeric, base: 10 }] )
|
||||
stack = Rpl::Lang::Core.to_string( [{ value: 2, type: :numeric, base: 10 }] )
|
||||
|
||||
assert_equal [{ value: '2', type: :string }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_from_string
|
||||
stack = Rpl::Core.from_string( [{ value: '2', type: :string }] )
|
||||
stack = Rpl::Lang::Core.from_string( [{ value: '2', type: :string }] )
|
||||
|
||||
assert_equal [{ value: 2, type: :numeric, base: 10 }],
|
||||
stack
|
||||
|
||||
stack = Rpl::Core.from_string( [{ value: "« 2 dup * » 'carré' sto", type: :string }] )
|
||||
stack = Rpl::Lang::Core.from_string( [{ value: "« 2 dup * » 'carré' sto", type: :string }] )
|
||||
|
||||
assert_equal [{ value: '« 2 dup * »', type: :program },
|
||||
{ value: "'carré'", type: :name },
|
||||
|
@ -29,28 +29,28 @@ class TestLanguageString < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_chr
|
||||
stack = Rpl::Core.chr( [{ value: 71, type: :numeric, base: 10 }] )
|
||||
stack = Rpl::Lang::Core.chr( [{ value: 71, type: :numeric, base: 10 }] )
|
||||
|
||||
assert_equal [{ value: 'G', type: :string }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_num
|
||||
stack = Rpl::Core.num( [{ value: 'G', type: :string }] )
|
||||
stack = Rpl::Lang::Core.num( [{ value: 'G', type: :string }] )
|
||||
|
||||
assert_equal [{ value: 71, type: :numeric, base: 10 }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_size
|
||||
stack = Rpl::Core.size( [{ value: 'test', type: :string }] )
|
||||
stack = Rpl::Lang::Core.size( [{ value: 'test', type: :string }] )
|
||||
|
||||
assert_equal [{ value: 4, type: :numeric, base: 10 }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_pos
|
||||
stack = Rpl::Core.pos( [{ value: 'test of POS', type: :string },
|
||||
stack = Rpl::Lang::Core.pos( [{ value: 'test of POS', type: :string },
|
||||
{ value: 'of', type: :string }] )
|
||||
|
||||
assert_equal [{ value: 5, type: :numeric, base: 10 }],
|
||||
|
@ -58,7 +58,7 @@ class TestLanguageString < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_sub
|
||||
stack = Rpl::Core.sub( [{ value: 'test', type: :string },
|
||||
stack = Rpl::Lang::Core.sub( [{ value: 'test', type: :string },
|
||||
{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 }] )
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ require_relative '../lib/core'
|
|||
class TestLanguageTimeDate < Test::Unit::TestCase
|
||||
def test_time
|
||||
now = Time.now.to_s
|
||||
stack = Rpl::Core.time( [] )
|
||||
stack = Rpl::Lang::Core.time( [] )
|
||||
|
||||
assert_equal [{ value: now, type: :string }],
|
||||
stack
|
||||
|
@ -16,14 +16,14 @@ class TestLanguageTimeDate < Test::Unit::TestCase
|
|||
|
||||
def test_date
|
||||
now = Date.today.to_s
|
||||
stack = Rpl::Core.date( [] )
|
||||
stack = Rpl::Lang::Core.date( [] )
|
||||
|
||||
assert_equal [{ value: now, type: :string }],
|
||||
stack
|
||||
end
|
||||
|
||||
def test_ticks
|
||||
stack = Rpl::Core.ticks( [] )
|
||||
stack = Rpl::Lang::Core.ticks( [] )
|
||||
|
||||
# TODO: better test, but how?
|
||||
assert_equal :numeric,
|
||||
|
|
|
@ -7,76 +7,76 @@ require_relative '../lib/parser'
|
|||
|
||||
class TestParser < Test::Unit::TestCase
|
||||
def test_number
|
||||
result = Rpl::Parser.new.parse_input( '1' )
|
||||
result = Rpl::Lang::Parser.new.parse_input( '1' )
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }], result
|
||||
end
|
||||
|
||||
def test_word
|
||||
result = Rpl::Parser.new.parse_input( 'dup' )
|
||||
result = Rpl::Lang::Parser.new.parse_input( 'dup' )
|
||||
assert_equal [{ value: 'dup', type: :word }], result
|
||||
end
|
||||
|
||||
def test_string
|
||||
result = Rpl::Parser.new.parse_input( '"test"' )
|
||||
result = Rpl::Lang::Parser.new.parse_input( '"test"' )
|
||||
assert_equal [{ value: '"test"', type: :string }], result
|
||||
|
||||
result = Rpl::Parser.new.parse_input( '" test"' )
|
||||
result = Rpl::Lang::Parser.new.parse_input( '" test"' )
|
||||
assert_equal [{ value: '" test"', type: :string }], result
|
||||
|
||||
result = Rpl::Parser.new.parse_input( '"test "' )
|
||||
result = Rpl::Lang::Parser.new.parse_input( '"test "' )
|
||||
assert_equal [{ value: '"test "', type: :string }], result
|
||||
|
||||
result = Rpl::Parser.new.parse_input( '" test "' )
|
||||
result = Rpl::Lang::Parser.new.parse_input( '" test "' )
|
||||
assert_equal [{ value: '" test "', type: :string }], result
|
||||
end
|
||||
|
||||
def test_name
|
||||
result = Rpl::Parser.new.parse_input( "'test'" )
|
||||
result = Rpl::Lang::Parser.new.parse_input( "'test'" )
|
||||
assert_equal [{ value: "'test'", type: :name }], result
|
||||
end
|
||||
|
||||
def test_program
|
||||
result = Rpl::Parser.new.parse_input( '« test »' )
|
||||
result = Rpl::Lang::Parser.new.parse_input( '« test »' )
|
||||
assert_equal [{ value: '« test »', type: :program }], result
|
||||
|
||||
result = Rpl::Parser.new.parse_input( '«test »' )
|
||||
result = Rpl::Lang::Parser.new.parse_input( '«test »' )
|
||||
assert_equal [{ value: '« test »', type: :program }], result
|
||||
|
||||
result = Rpl::Parser.new.parse_input( '« test»' )
|
||||
result = Rpl::Lang::Parser.new.parse_input( '« test»' )
|
||||
assert_equal [{ value: '« test »', type: :program }], result
|
||||
|
||||
result = Rpl::Parser.new.parse_input( '«test»' )
|
||||
result = Rpl::Lang::Parser.new.parse_input( '«test»' )
|
||||
assert_equal [{ value: '« test »', type: :program }], result
|
||||
|
||||
result = Rpl::Parser.new.parse_input( '« test test »' )
|
||||
result = Rpl::Lang::Parser.new.parse_input( '« test test »' )
|
||||
assert_equal [{ value: '« test test »', type: :program }], result
|
||||
|
||||
result = Rpl::Parser.new.parse_input( '« test « test » »' )
|
||||
result = Rpl::Lang::Parser.new.parse_input( '« test « test » »' )
|
||||
assert_equal [{ value: '« test « test » »', type: :program }], result
|
||||
|
||||
result = Rpl::Parser.new.parse_input( '« test "test" test »' )
|
||||
result = Rpl::Lang::Parser.new.parse_input( '« test "test" test »' )
|
||||
assert_equal [{ value: '« test "test" test »', type: :program }], result
|
||||
end
|
||||
|
||||
def test_number_number
|
||||
result = Rpl::Parser.new.parse_input( '2 3' )
|
||||
result = Rpl::Lang::Parser.new.parse_input( '2 3' )
|
||||
assert_equal [{ value: 2, type: :numeric, base: 10 }, { value: 3, type: :numeric, base: 10 }], result
|
||||
end
|
||||
|
||||
def test_number_number_word
|
||||
result = Rpl::Parser.new.parse_input( '2 3 +' )
|
||||
result = Rpl::Lang::Parser.new.parse_input( '2 3 +' )
|
||||
assert_equal [{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 3, type: :numeric, base: 10 },
|
||||
{ value: '+', type: :word }], result
|
||||
end
|
||||
|
||||
def test_number_string
|
||||
result = Rpl::Parser.new.parse_input( '4 "test"' )
|
||||
result = Rpl::Lang::Parser.new.parse_input( '4 "test"' )
|
||||
assert_equal [{ value: 4, type: :numeric, base: 10 }, { value: '"test"', type: :string }], result
|
||||
end
|
||||
|
||||
def test_program_name
|
||||
result = Rpl::Parser.new.parse_input( "« 2 dup * » 'carré' sto" )
|
||||
result = Rpl::Lang::Parser.new.parse_input( "« 2 dup * » 'carré' sto" )
|
||||
|
||||
assert_equal [{ value: '« 2 dup * »', type: :program },
|
||||
{ value: "'carré'", type: :name },
|
||||
|
|
Loading…
Reference in a new issue