[WIP] almost there
This commit is contained in:
parent
02f322744b
commit
fcb809d797
35 changed files with 609 additions and 996 deletions
4
bin/rpl
4
bin/rpl
|
@ -45,7 +45,7 @@ class RplRepl
|
|||
stack_size = @interpreter.stack.size
|
||||
|
||||
@interpreter.stack.each_with_index do |elt, i|
|
||||
puts "#{stack_size - i}: #{@interpreter.stringify( elt )}"
|
||||
puts "#{stack_size - i}: #{elt}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -85,4 +85,4 @@ end
|
|||
RplRepl.new( interpreter ).run if options[:run_REPL]
|
||||
|
||||
# last print resulting stack on exit (formatted so that it can be fed back later to interpreter)
|
||||
pp interpreter.stack.map { |elt| interpreter.stringify( elt ) }.join(' ')
|
||||
pp interpreter.export_stack
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rpl/types'
|
||||
|
||||
require 'rpl/interpreter'
|
||||
|
||||
require 'rpl/types'
|
||||
require 'rpl/words'
|
||||
|
||||
class Rpl < Interpreter
|
||||
include Types
|
||||
|
||||
def initialize( stack = [], dictionary = Dictionary.new )
|
||||
super
|
||||
|
||||
|
|
|
@ -5,9 +5,11 @@ require 'bigdecimal/math'
|
|||
require 'bigdecimal/util'
|
||||
|
||||
require 'rpl/dictionary'
|
||||
require 'rpl/types'
|
||||
|
||||
class Interpreter
|
||||
include BigMath
|
||||
include Types
|
||||
|
||||
attr_reader :stack,
|
||||
:dictionary,
|
||||
|
@ -16,171 +18,34 @@ class Interpreter
|
|||
attr_accessor :precision
|
||||
|
||||
def initialize( stack = [], dictionary = Rpl::Lang::Dictionary.new )
|
||||
@version = 0.1
|
||||
|
||||
@precision = default_precision
|
||||
@version = 0.6
|
||||
|
||||
@dictionary = dictionary
|
||||
@stack = stack
|
||||
end
|
||||
|
||||
def default_precision
|
||||
12
|
||||
end
|
||||
|
||||
def parse( input )
|
||||
is_numeric = lambda do |elt|
|
||||
!Float(elt).nil?
|
||||
rescue ArgumentError
|
||||
begin
|
||||
!Integer(elt).nil?
|
||||
rescue ArgumentError
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
unless input.index("\n").nil?
|
||||
input = input.split("\n")
|
||||
.map do |line|
|
||||
comment_begin_index = line.index('#')
|
||||
|
||||
if comment_begin_index.nil?
|
||||
line
|
||||
elsif comment_begin_index.zero?
|
||||
''
|
||||
else
|
||||
line[0..(comment_begin_index - 1)]
|
||||
end
|
||||
end
|
||||
.join(' ')
|
||||
end
|
||||
|
||||
splitted_input = input.split(' ')
|
||||
|
||||
# 2-passes:
|
||||
# 1. regroup strings and programs
|
||||
opened_programs = 0
|
||||
closed_programs = 0
|
||||
opened_lists = 0
|
||||
closed_lists = 0
|
||||
string_delimiters = 0
|
||||
name_delimiters = 0
|
||||
regrouping = false
|
||||
|
||||
regrouped_input = []
|
||||
splitted_input.each do |elt|
|
||||
if elt[0] == '«'
|
||||
opened_programs += 1
|
||||
elt.gsub!( '«', '« ') if elt.length > 1 && elt[1] != ' '
|
||||
elsif elt[0] == '{'
|
||||
opened_lists += 1
|
||||
elt.gsub!( '{', '{ ') if elt.length > 1 && elt[1] != ' '
|
||||
elsif elt[0] == '"' && elt.length > 1
|
||||
string_delimiters += 1
|
||||
elsif elt[0] == "'" && elt.length > 1
|
||||
name_delimiters += 1
|
||||
end
|
||||
|
||||
elt = "#{regrouped_input.pop} #{elt}".strip if regrouping
|
||||
|
||||
regrouped_input << elt
|
||||
|
||||
case elt[-1]
|
||||
when '»'
|
||||
closed_programs += 1
|
||||
elt.gsub!( '»', ' »') if elt.length > 1 && elt[-2] != ' '
|
||||
when '}'
|
||||
closed_lists += 1
|
||||
elt.gsub!( '}', ' }') if elt.length > 1 && elt[-2] != ' '
|
||||
when '"'
|
||||
string_delimiters += 1
|
||||
when "'"
|
||||
name_delimiters += 1
|
||||
end
|
||||
|
||||
regrouping = string_delimiters.odd? || name_delimiters.odd? || (opened_programs > closed_programs ) || (opened_lists > closed_lists )
|
||||
end
|
||||
|
||||
# 2. parse
|
||||
# TODO: parse ∞, <NaN> as numerics
|
||||
parsed_tree = []
|
||||
regrouped_input.each do |elt|
|
||||
parsed_entry = { value: elt }
|
||||
|
||||
parsed_entry[:type] = case elt[0]
|
||||
when '«'
|
||||
:program
|
||||
when '{'
|
||||
:list
|
||||
when '"'
|
||||
:string
|
||||
when "'"
|
||||
:name
|
||||
else
|
||||
if is_numeric.call( elt )
|
||||
:numeric
|
||||
else
|
||||
:word
|
||||
end
|
||||
end
|
||||
|
||||
if %I[string name].include?( parsed_entry[:type] )
|
||||
parsed_entry[:value] = parsed_entry[:value][1..-2]
|
||||
|
||||
elsif %I[program].include?( parsed_entry[:type] )
|
||||
parsed_entry[:value] = parsed_entry[:value][2..-3]
|
||||
|
||||
elsif %I[list].include?( parsed_entry[:type] )
|
||||
parsed_entry[:value] = parse( parsed_entry[:value][2..-3] )
|
||||
|
||||
elsif %I[numeric].include?( parsed_entry[:type] )
|
||||
underscore_position = parsed_entry[:value].index('_')
|
||||
|
||||
if parsed_entry[:value][0] == '0' && ( %w[b o x].include?( parsed_entry[:value][1] ) || !underscore_position.nil? )
|
||||
if parsed_entry[:value][1] == 'x'
|
||||
parsed_entry[:base] = 16
|
||||
elsif parsed_entry[:value][1] == 'b'
|
||||
parsed_entry[:base] = 2
|
||||
elsif parsed_entry[:value][1] == 'o'
|
||||
parsed_entry[:base] = 8
|
||||
parsed_entry[:value] = parsed_entry[:value][2..-1]
|
||||
elsif !underscore_position.nil?
|
||||
parsed_entry[:base] = parsed_entry[:value][1..(underscore_position - 1)].to_i
|
||||
parsed_entry[:value] = parsed_entry[:value][(underscore_position + 1)..-1]
|
||||
end
|
||||
else
|
||||
parsed_entry[:base] = 10
|
||||
end
|
||||
|
||||
parsed_entry[:value] = parsed_entry[:value].to_i( parsed_entry[:base] ) unless parsed_entry[:base] == 10
|
||||
parsed_entry[:value] = BigDecimal( parsed_entry[:value], @precision )
|
||||
end
|
||||
|
||||
parsed_tree << parsed_entry
|
||||
end
|
||||
|
||||
parsed_tree
|
||||
end
|
||||
|
||||
def run( input )
|
||||
@dictionary.add_local_vars_layer
|
||||
|
||||
parse( input.to_s ).each do |elt|
|
||||
case elt[:type]
|
||||
when :word
|
||||
break if %w[break quit exit].include?( elt[:value] )
|
||||
|
||||
command = @dictionary.lookup( elt[:value] )
|
||||
|
||||
if command.nil?
|
||||
# if there isn't a command by that name then it's a name
|
||||
elt[:type] = :name
|
||||
Parser.parse( input.to_s ).each do |elt|
|
||||
if elt.instance_of?( RplName )
|
||||
break if %w[break quit exit].include?( elt.value )
|
||||
|
||||
if elt.not_to_evaluate
|
||||
@stack << elt
|
||||
elsif command.is_a?( Proc )
|
||||
command.call
|
||||
else
|
||||
run( command[:value] )
|
||||
command = @dictionary.lookup( elt.value )
|
||||
|
||||
if command.nil?
|
||||
# if there isn't a command by that name then it's a name
|
||||
# elt[:type] = :name
|
||||
|
||||
@stack << elt
|
||||
elsif command.is_a?( Proc )
|
||||
command.call
|
||||
else
|
||||
run( command.value )
|
||||
end
|
||||
end
|
||||
else
|
||||
@stack << elt
|
||||
|
@ -199,7 +64,7 @@ class Interpreter
|
|||
needs.each_with_index do |need, index|
|
||||
stack_index = (index + 1) * -1
|
||||
|
||||
raise ArgumentError, "Type Error, needed #{need} got #{@stack[stack_index]}" unless need == :any || need.include?( @stack[stack_index][:type] )
|
||||
raise ArgumentError, "Type Error, needed #{need} got #{@stack[stack_index]}" unless need == :any || need.include?( @stack[stack_index].class )
|
||||
end
|
||||
|
||||
args = []
|
||||
|
@ -210,52 +75,7 @@ class Interpreter
|
|||
args
|
||||
end
|
||||
|
||||
def stringify( elt )
|
||||
case elt[:type]
|
||||
when :numeric
|
||||
prefix = case elt[:base]
|
||||
when 2
|
||||
'0b'
|
||||
when 8
|
||||
'0o'
|
||||
when 10
|
||||
''
|
||||
when 16
|
||||
'0x'
|
||||
else
|
||||
"0#{elt[:base]}_"
|
||||
end
|
||||
|
||||
if elt[:value].infinite?
|
||||
suffix = elt[:value].infinite?.positive? ? '∞' : '-∞'
|
||||
elsif elt[:value].nan?
|
||||
suffix = '<NaN>'
|
||||
else
|
||||
suffix = if elt[:value].to_i == elt[:value]
|
||||
elt[:value].to_i
|
||||
else
|
||||
elt[:value].to_s('F')
|
||||
end
|
||||
suffix = elt[:value].to_s( elt[:base] ) unless elt[:base] == 10
|
||||
end
|
||||
|
||||
"#{prefix}#{suffix}"
|
||||
when :list
|
||||
"{ #{elt[:value].map { |e| stringify( e ) }.join(' ')} }"
|
||||
when :program
|
||||
"« #{elt[:value]} »"
|
||||
when :string
|
||||
"\"#{elt[:value]}\""
|
||||
when :name
|
||||
"'#{elt[:value]}'"
|
||||
else
|
||||
elt[:value]
|
||||
end
|
||||
end
|
||||
|
||||
def infer_resulting_base( numerics )
|
||||
10 if numerics.length.zero?
|
||||
|
||||
numerics.last[:base]
|
||||
def export_stack
|
||||
@stack.map(&:to_s).join(' ')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -23,5 +23,10 @@ module Types
|
|||
|
||||
%w[TrueClass FalseClass].include?( value.class.to_s )
|
||||
end
|
||||
|
||||
def ==( other )
|
||||
other.class == RplBoolean and
|
||||
other.value == value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,8 +9,12 @@ module Types
|
|||
def initialize( value )
|
||||
raise RplTypeError unless self.class.can_parse?( value )
|
||||
|
||||
# we systematicalyl trim enclosing { }
|
||||
@value = Parser.parse( value[2..-3] )
|
||||
@value = if value.instance_of?( Array )
|
||||
value
|
||||
else
|
||||
# we systematicalyl trim enclosing { }
|
||||
Parser.parse( value[2..-3] )
|
||||
end
|
||||
end
|
||||
|
||||
def to_s
|
||||
|
@ -18,7 +22,13 @@ module Types
|
|||
end
|
||||
|
||||
def self.can_parse?( value )
|
||||
value[0..1] == '{ ' && value[-2..-1] == ' }'
|
||||
value.instance_of?( Array ) or
|
||||
value[0..1] == '{ ' && value[-2..-1] == ' }'
|
||||
end
|
||||
|
||||
def ==( other )
|
||||
other.class == RplList and
|
||||
other.value == value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,8 +25,14 @@ module Types
|
|||
|
||||
def self.can_parse?( value )
|
||||
( value.length > 2 and value[0] == "'" and value[-1] == "'" ) or
|
||||
# it's not any other type
|
||||
[RplBoolean, RplList, RplProgram, RplString, RplNumeric].reduce( true ) { |memo, type_class| memo && !type_class.can_parse?( value ) }
|
||||
( value != "''" and !value.match?(/^[0-9']+$/) and
|
||||
# it's not any other type
|
||||
[RplBoolean, RplList, RplProgram, RplString, RplNumeric].reduce( true ) { |memo, type_class| memo && !type_class.can_parse?( value ) } )
|
||||
end
|
||||
|
||||
def ==( other )
|
||||
other.class == RplName and
|
||||
other.value == value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,11 +7,23 @@ module Types
|
|||
attr_accessor :value,
|
||||
:base
|
||||
|
||||
@@precision = 12 # rubocop:disable Style/ClassVars
|
||||
|
||||
def self.default_precision
|
||||
@@precision = 12 # rubocop:disable Style/ClassVars
|
||||
end
|
||||
|
||||
def self.precision
|
||||
@@precision
|
||||
end
|
||||
|
||||
def self.precision=( precision )
|
||||
@@precision = precision.to_i # rubocop:disable Style/ClassVars
|
||||
end
|
||||
|
||||
def initialize( value, base = 10 )
|
||||
raise RplTypeError unless self.class.can_parse?( value )
|
||||
|
||||
@@precision = 12 # rubocop:disable Style/ClassVars
|
||||
|
||||
@base = base
|
||||
|
||||
case value
|
||||
|
@ -53,12 +65,6 @@ module Types
|
|||
end
|
||||
end
|
||||
|
||||
def self.precision=( precision )
|
||||
raise RplTypeError unless precision.is_a? RplNumeric
|
||||
|
||||
@@precision = precision.value.to_i # rubocop:disable Style/ClassVars
|
||||
end
|
||||
|
||||
def to_s
|
||||
prefix = case @base
|
||||
when 2
|
||||
|
@ -105,11 +111,5 @@ module Types
|
|||
other.base == base and
|
||||
other.value == value
|
||||
end
|
||||
|
||||
def self.infer_resulting_base( numerics )
|
||||
10 if numerics.length.zero?
|
||||
|
||||
numerics.last.base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,5 +18,10 @@ module Types
|
|||
def self.can_parse?( value )
|
||||
value.length > 4 && value[0..1] == '« ' && value[-2..-1] == ' »' && !value[2..-3].strip.empty?
|
||||
end
|
||||
|
||||
def ==( other )
|
||||
other.class == RplProgram and
|
||||
other.value == value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,5 +18,10 @@ module Types
|
|||
def self.can_parse?( value )
|
||||
value[0] == '"' && value[-1] == '"'
|
||||
end
|
||||
|
||||
def ==( other )
|
||||
other.class == RplString and
|
||||
other.value == value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,36 +3,35 @@
|
|||
module RplLang
|
||||
module Words
|
||||
module Branch
|
||||
include Types
|
||||
|
||||
def populate_dictionary
|
||||
super
|
||||
|
||||
@dictionary.add_word( ['ift'],
|
||||
'Branch',
|
||||
'( t pt -- … ) eval pt or not based on the value of boolean t',
|
||||
proc do
|
||||
run( '« nop » ifte' )
|
||||
end )
|
||||
RplProgram.new( '« « nop » ifte »' ) )
|
||||
|
||||
@dictionary.add_word( ['ifte'],
|
||||
'Branch',
|
||||
'( t pt pf -- … ) eval pt or pf based on the value of boolean t',
|
||||
proc do
|
||||
args = stack_extract( [:any, :any, %i[boolean]] )
|
||||
args = stack_extract( [:any, :any, [RplBoolean]] )
|
||||
|
||||
run( args[ args[2][:value] ? 1 : 0 ][:value] )
|
||||
run( args[ args[2].value ? 1 : 0 ].value )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['times'],
|
||||
'Branch',
|
||||
'( p n -- … ) eval p n times while pushing counter on stack before',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric], :any] )
|
||||
args = stack_extract( [[RplNumeric], :any] )
|
||||
|
||||
args[0][:value].to_i.times do |i|
|
||||
counter = { value: BigDecimal( i, @precision ), type: :numeric, base: 10 }
|
||||
@stack << counter
|
||||
args[0].value.to_i.times do |counter|
|
||||
@stack << RplNumeric.new( counter )
|
||||
|
||||
run( args[1][:value] )
|
||||
run( args[1].value )
|
||||
end
|
||||
end )
|
||||
|
||||
|
@ -40,13 +39,12 @@ module RplLang
|
|||
'Branch',
|
||||
'( p n1 n2 -- … ) eval p looping from n1 to n2 while pushing counter on stack before',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric], %i[numeric], :any] )
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric], :any] )
|
||||
|
||||
((args[1][:value].to_i)..(args[0][:value].to_i)).each do |i|
|
||||
counter = { value: BigDecimal( i, @precision ), type: :numeric, base: 10 }
|
||||
@stack << counter
|
||||
((args[1].value.to_i)..(args[0].value.to_i)).each do |counter|
|
||||
@stack << RplNumeric.new( counter )
|
||||
|
||||
run( args[2][:value] )
|
||||
run( args[2].value )
|
||||
end
|
||||
end )
|
||||
end
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
module RplLang
|
||||
module Words
|
||||
module FileSystem
|
||||
include Types
|
||||
|
||||
def populate_dictionary
|
||||
super
|
||||
|
||||
|
@ -10,29 +12,26 @@ module RplLang
|
|||
'Filesystem',
|
||||
'( filename -- content ) read file and put content on stack as string',
|
||||
proc do
|
||||
args = stack_extract( [%i[string]] )
|
||||
args = stack_extract( [[RplString]] )
|
||||
|
||||
path = File.absolute_path( args[0][:value] )
|
||||
path = File.absolute_path( args[0].value )
|
||||
|
||||
@stack << { type: :string,
|
||||
value: File.read( path ) }
|
||||
@stack << RplString.new( "\"#{File.read( path )}\"" )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['feval'],
|
||||
'Filesystem',
|
||||
'( filename -- … ) read and run file',
|
||||
proc do
|
||||
run( 'fread eval' )
|
||||
end )
|
||||
RplProgram.new( '« fread eval »' ) )
|
||||
|
||||
@dictionary.add_word( ['fwrite'],
|
||||
'Filesystem',
|
||||
'( content filename -- ) write content into filename',
|
||||
proc do
|
||||
args = stack_extract( [%i[string], :any] )
|
||||
args = stack_extract( [[RplString], :any] )
|
||||
|
||||
File.write( File.absolute_path( args[0][:value] ),
|
||||
args[1][:value] )
|
||||
File.write( File.absolute_path( args[0].value ),
|
||||
args[1].value )
|
||||
end )
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
module RplLang
|
||||
module Words
|
||||
module General
|
||||
include Types
|
||||
|
||||
def populate_dictionary
|
||||
super
|
||||
|
||||
|
@ -15,12 +17,11 @@ module RplLang
|
|||
'General',
|
||||
'( w -- s ) pop help string of the given word',
|
||||
proc do
|
||||
args = stack_extract( [%i[name]] )
|
||||
args = stack_extract( [[RplName]] )
|
||||
|
||||
word = @dictionary.words[ args[0][:value] ]
|
||||
word = @dictionary.words[ args[0].value ]
|
||||
|
||||
@stack << { type: :string,
|
||||
value: "#{args[0][:value]}: #{word.nil? ? 'not a core word' : word[:help]}" }
|
||||
@stack << RplString.new( "\"#{args[0].value}: #{word.nil? ? 'not a core word' : word[:help]}\"" )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['words'],
|
||||
|
@ -45,14 +46,14 @@ module RplLang
|
|||
'General',
|
||||
'( -- n ) Pop the interpreter\'s version number',
|
||||
proc do
|
||||
@stack += parse( @version.to_s )
|
||||
@stack += Parser.parse( @version.to_s )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['uname'],
|
||||
'General',
|
||||
'( -- s ) Pop the interpreter\'s complete indentification string',
|
||||
proc do
|
||||
@stack += parse( "\"Rpl Interpreter version #{@version}\"" )
|
||||
@stack += Parser.parse( "\"Rpl Interpreter version #{@version}\"" )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['history'],
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
module RplLang
|
||||
module Words
|
||||
module Logarithm
|
||||
include Types
|
||||
|
||||
def populate_dictionary
|
||||
super
|
||||
|
||||
|
@ -10,9 +12,7 @@ module RplLang
|
|||
'Logs on reals and complexes',
|
||||
'( … -- ℇ ) push ℇ',
|
||||
proc do
|
||||
@stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: BigMath.E( @precision ) }
|
||||
@stack << RplNumeric.new( BigMath.E( RplNumeric.precision ) )
|
||||
end )
|
||||
|
||||
# @dictionary.add_word( ['ln'],
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
module RplLang
|
||||
module Words
|
||||
module Mode
|
||||
include Types
|
||||
|
||||
def populate_dictionary
|
||||
super
|
||||
|
||||
|
@ -10,15 +12,15 @@ module RplLang
|
|||
'Mode',
|
||||
'( a -- ) set precision to a',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
@precision = args[0][:value]
|
||||
RplNumeric.precision = args[0].value
|
||||
end )
|
||||
@dictionary.add_word( ['default'],
|
||||
'Mode',
|
||||
'( -- ) set default precision',
|
||||
proc do
|
||||
@precision = default_precision
|
||||
RplNumeric.default_precision
|
||||
end )
|
||||
@dictionary.add_word( ['type'],
|
||||
'Mode',
|
||||
|
@ -26,8 +28,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [:any] )
|
||||
|
||||
@stack << { type: :string,
|
||||
value: args[0][:type].to_s }
|
||||
@stack << RplString.new( "\"#{args[0].class.to_s[10..-1]}\"" )
|
||||
end )
|
||||
|
||||
# @dictionary.add_word( ['std'],
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
module RplLang
|
||||
module Words
|
||||
module Operations
|
||||
include Types
|
||||
|
||||
def populate_dictionary
|
||||
super
|
||||
|
||||
|
@ -11,69 +13,70 @@ module RplLang
|
|||
'Usual operations on reals and complexes',
|
||||
'( a b -- c ) addition',
|
||||
proc do
|
||||
addable = %i[numeric string name list]
|
||||
addable = [RplNumeric, RplString, RplName, RplList]
|
||||
args = stack_extract( [addable, addable] )
|
||||
# | + | 1 numeric | 1 string | 1 name | 1 list |
|
||||
# | + | 1 numeric | 1 string | 1 name |v1 list |
|
||||
# |-----------+-----------+----------+--------+--------|
|
||||
# | 0 numeric | numeric | string | name | list |
|
||||
# | 0 string | string | string | string | list |
|
||||
# | 0 name | string | string | name | list |
|
||||
# | 0 list | list | list | list | list |
|
||||
# | 0 numeric | numeric | string | name |vlist |
|
||||
# |v0 string |vstring |vstring |vstring |vlist |
|
||||
# |v0 name |vstring |vstring |vname |vlist |
|
||||
# |v0 list |vlist |vlist |vlist |vlist |
|
||||
|
||||
result = { type: case args[0][:type]
|
||||
when :numeric
|
||||
args[1][:type]
|
||||
args.reverse!
|
||||
|
||||
when :string
|
||||
case args[1][:type]
|
||||
when :list
|
||||
:list
|
||||
else
|
||||
:string
|
||||
end
|
||||
result = if args[0].instance_of?( RplList )
|
||||
if args[1].instance_of?( RplList )
|
||||
args[0].value.concat( args[1].value )
|
||||
else
|
||||
args[0].value << args[1]
|
||||
end
|
||||
args[0]
|
||||
|
||||
when :name
|
||||
case args[1][:type]
|
||||
when :name
|
||||
:name
|
||||
when :list
|
||||
:list
|
||||
else
|
||||
:string
|
||||
end
|
||||
elsif args[1].instance_of?( RplList )
|
||||
if args[0].instance_of?( RplList )
|
||||
args[0].value.concat( args[1].value )
|
||||
args[0]
|
||||
else
|
||||
args[1].value.unshift( args[0] )
|
||||
args[1]
|
||||
end
|
||||
|
||||
when :list
|
||||
:list
|
||||
elsif args[0].instance_of?( RplString )
|
||||
args[0].value = if args[1].instance_of?( RplString ) ||
|
||||
args[1].instance_of?( RplName )
|
||||
"#{args[0].value}#{args[1].value}"
|
||||
else
|
||||
"#{args[0].value}#{args[1]}"
|
||||
end
|
||||
args[0]
|
||||
|
||||
else
|
||||
args[0][:type]
|
||||
end }
|
||||
elsif args[0].instance_of?( RplName )
|
||||
|
||||
if result[:type] == :list
|
||||
args.each do |elt|
|
||||
next unless elt[:type] != :list
|
||||
if args[1].instance_of?( RplName )
|
||||
args[0].value = "#{args[0].value}#{args[1].value}"
|
||||
args[0]
|
||||
else
|
||||
if args[1].instance_of?( RplString )
|
||||
RplString.new( "\"#{args[0].value}#{args[1].value}\"" )
|
||||
elsif args[1].instance_of?( RplNumeric )
|
||||
args[0].value = "#{args[0].value}#{args[1]}"
|
||||
args[0]
|
||||
else
|
||||
RplString.new( "\"#{args[0]}#{args[1]}\"" )
|
||||
end
|
||||
end
|
||||
|
||||
elt_copy = Marshal.load(Marshal.dump( elt ))
|
||||
elt[:type] = :list
|
||||
elt[:value] = [elt_copy]
|
||||
end
|
||||
end
|
||||
elsif args[0].instance_of?( RplNumeric )
|
||||
if args[1].instance_of?( RplNumeric )
|
||||
args[0].value += args[1].value
|
||||
args[0]
|
||||
|
||||
value_to_string = lambda do |e|
|
||||
if e[:type] == :numeric
|
||||
stringify( e )
|
||||
else
|
||||
e[:value].to_s
|
||||
end
|
||||
end
|
||||
|
||||
result[:value] = if %i[name string].include?( result[:type] )
|
||||
"#{value_to_string.call( args[1] )}#{value_to_string.call( args[0] )}"
|
||||
else
|
||||
args[1][:value] + args[0][:value]
|
||||
end
|
||||
|
||||
result[:base] = args[0][:base] if result[:type] == :numeric
|
||||
elsif args[1].instance_of?( RplString ) ||
|
||||
args[1].instance_of?( RplName )
|
||||
args[1].value = "#{args[0]}#{args[1].value}"
|
||||
args[1]
|
||||
end
|
||||
end
|
||||
|
||||
@stack << result
|
||||
end )
|
||||
|
@ -82,11 +85,11 @@ module RplLang
|
|||
'Usual operations on reals and complexes',
|
||||
'( a b -- c ) subtraction',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric], %i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: args[1][:value] - args[0][:value] }
|
||||
args[1].value = args[1].value - args[0].value
|
||||
|
||||
@stack << args[1]
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['chs'],
|
||||
|
@ -100,22 +103,22 @@ module RplLang
|
|||
'Usual operations on reals and complexes',
|
||||
'( a b -- c ) multiplication',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric], %i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: args[1][:value] * args[0][:value] }
|
||||
args[1].value = args[1].value * args[0].value
|
||||
|
||||
@stack << args[1]
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['÷', '/'],
|
||||
'Usual operations on reals and complexes',
|
||||
'( a b -- c ) division',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric], %i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: args[1][:value] / args[0][:value] }
|
||||
args[1].value = args[1].value / args[0].value
|
||||
|
||||
@stack << args[1]
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['inv'],
|
||||
|
@ -129,22 +132,22 @@ module RplLang
|
|||
'Usual operations on reals and complexes',
|
||||
'( a b -- c ) a to the power of b',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric], %i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: args[1][:value]**args[0][:value] }
|
||||
args[1].value = args[1].value**args[0].value
|
||||
|
||||
@stack << args[1]
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['√', 'sqrt'],
|
||||
'Usual operations on reals and complexes',
|
||||
'( a -- b ) square root',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: BigMath.sqrt( BigDecimal( args[0][:value], precision ), precision ) }
|
||||
args[0].value = BigMath.sqrt( args[0].value, RplNumeric.precision )
|
||||
|
||||
@stack << args[0]
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['²', 'sq'],
|
||||
|
@ -158,11 +161,11 @@ module RplLang
|
|||
'Usual operations on reals and complexes',
|
||||
'( a -- b ) absolute value',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: args[0][:value].abs }
|
||||
args[0].value = args[0].value.abs
|
||||
|
||||
@stack << args[0]
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['dec'],
|
||||
|
@ -190,9 +193,9 @@ module RplLang
|
|||
'Usual operations on reals and complexes',
|
||||
'( a b -- a ) set numeric\'s base to b',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric], %i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
args[1][:base] = args[0][:value]
|
||||
args[1].base = args[0].value
|
||||
|
||||
@stack << args[1]
|
||||
end )
|
||||
|
@ -201,18 +204,16 @@ module RplLang
|
|||
'Usual operations on reals and complexes',
|
||||
'( a -- b ) sign of element',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
value = if args[0][:value].positive?
|
||||
1
|
||||
elsif args[0][:value].negative?
|
||||
-1
|
||||
else
|
||||
0
|
||||
end
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
args[0].value = if args[0].value.positive?
|
||||
1
|
||||
elsif args[0].value.negative?
|
||||
-1
|
||||
else
|
||||
0
|
||||
end
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: value }
|
||||
@stack << args[0]
|
||||
end )
|
||||
|
||||
# Operations on reals
|
||||
|
@ -220,106 +221,104 @@ module RplLang
|
|||
'Operations on reals',
|
||||
'( a b -- c ) b% of a',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric], %i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: args[0][:value] * ( args[1][:value] / 100.0 ) }
|
||||
args[1].value = args[0].value * ( args[1].value / 100.0 )
|
||||
|
||||
@stack << args[1]
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['%CH'],
|
||||
'Operations on reals',
|
||||
'( a b -- c ) b is c% of a',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric], %i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: 100.0 * ( args[0][:value] / args[1][:value] ) }
|
||||
args[1].value = 100.0 * ( args[0].value / args[1].value )
|
||||
|
||||
@stack << args[1]
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['mod'],
|
||||
'Operations on reals',
|
||||
'( a b -- c ) modulo',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric], %i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: args[1][:value] % args[0][:value] }
|
||||
args[1].value = args[1].value % args[0].value
|
||||
|
||||
@stack << args[1]
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['!', 'fact'],
|
||||
'Operations on reals',
|
||||
'( a -- b ) factorial',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: Math.gamma( args[0][:value] ) }
|
||||
args[0].value = Math.gamma( args[0].value )
|
||||
|
||||
@stack << args[0]
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['floor'],
|
||||
'Operations on reals',
|
||||
'( a -- b ) highest integer under a',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: args[0][:value].floor }
|
||||
args[0].value = args[0].value.floor
|
||||
|
||||
@stack << args[0]
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['ceil'],
|
||||
'Operations on reals',
|
||||
'( a -- b ) highest integer over a',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: args[0][:value].ceil }
|
||||
args[0].value = args[0].value.ceil
|
||||
|
||||
@stack << args[0]
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['min'],
|
||||
'Operations on reals',
|
||||
'( a b -- a/b ) leave lowest of a or b',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric], %i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
@stack << ( args[0][:value] < args[1][:value] ? args[0] : args[1] )
|
||||
@stack << ( args[0].value < args[1].value ? args[0] : args[1] )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['max'],
|
||||
'Operations on reals',
|
||||
'( a b -- a/b ) leave highest of a or b',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric], %i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
@stack << ( args[0][:value] > args[1][:value] ? args[0] : args[1] )
|
||||
@stack << ( args[0].value > args[1].value ? args[0] : args[1] )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['mant'],
|
||||
'Operations on reals',
|
||||
'mantissa of a real number',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: BigDecimal( args[0][:value].to_s.split('e').first.to_f.abs, @precision ) }
|
||||
@stack << RplNumeric.new( args[0].value.to_s.split('e').first.to_f.abs )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['xpon'],
|
||||
'Operations on reals',
|
||||
'exponant of a real number',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: args[0][:value].exponent }
|
||||
args[0].value = args[0].value.exponent
|
||||
|
||||
@stack << args[0]
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['ip'],
|
||||
|
@ -333,11 +332,11 @@ module RplLang
|
|||
'Operations on reals',
|
||||
'( n -- f ) fractional part',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: args[0][:value].frac }
|
||||
args[0].value = args[0].value.frac
|
||||
|
||||
@stack << args[0]
|
||||
end )
|
||||
|
||||
# Operations on complexes
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
module RplLang
|
||||
module Words
|
||||
module Program
|
||||
include Types
|
||||
|
||||
def populate_dictionary
|
||||
super
|
||||
|
||||
|
@ -12,10 +14,10 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [:any] )
|
||||
|
||||
if %i[list numeric boolean].include?( args[0][:type] )
|
||||
if [RplList, RplNumeric, RplBoolean].include?( args[0].class )
|
||||
@stack << args[0] # these types evaluate to themselves
|
||||
else
|
||||
run( args[0][:value].to_s )
|
||||
run( args[0].value.to_s )
|
||||
end
|
||||
end )
|
||||
end
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
module RplLang
|
||||
module Words
|
||||
module Stack
|
||||
include Types
|
||||
|
||||
def populate_dictionary
|
||||
super
|
||||
|
||||
|
@ -18,9 +20,7 @@ module RplLang
|
|||
@dictionary.add_word( ['drop'],
|
||||
'Stack',
|
||||
'( a -- ) drop first stack element',
|
||||
proc do
|
||||
run( '1 dropn' )
|
||||
end )
|
||||
RplProgram.new( '« 1 dropn »' ) )
|
||||
|
||||
@dictionary.add_word( ['drop2'],
|
||||
'Stack',
|
||||
|
@ -33,9 +33,9 @@ module RplLang
|
|||
'Stack',
|
||||
'( a b … n -- ) drop first n stack elements',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
_args = stack_extract( %i[any] * args[0][:value] )
|
||||
_args = stack_extract( %i[any] * args[0].value )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['del'],
|
||||
|
@ -57,24 +57,20 @@ module RplLang
|
|||
@dictionary.add_word( ['dup'],
|
||||
'Stack',
|
||||
'( a -- a a ) duplicate first stack element',
|
||||
proc do
|
||||
run( '1 dupn' )
|
||||
end )
|
||||
RplProgram.new( '« 1 dupn »' ) )
|
||||
|
||||
@dictionary.add_word( ['dup2'],
|
||||
'Stack',
|
||||
'( a b -- a b a b ) duplicate first two stack elements',
|
||||
proc do
|
||||
run( '2 dupn' )
|
||||
end )
|
||||
RplProgram.new( '« 2 dupn »' ) )
|
||||
|
||||
@dictionary.add_word( ['dupn'],
|
||||
'Stack',
|
||||
'( a b … n -- a b … a b … ) duplicate first n stack elements',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
n = args[0][:value].to_i
|
||||
args = stack_extract( %i[any] * args[0][:value] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
n = args[0].value.to_i
|
||||
args = stack_extract( %i[any] * args[0].value )
|
||||
|
||||
args.reverse!
|
||||
|
||||
|
@ -89,9 +85,9 @@ module RplLang
|
|||
'Stack',
|
||||
'( … b … n -- … b … b ) push a copy of the given stack level onto the stack',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
n = args[0][:value].to_i
|
||||
args = stack_extract( %i[any] * args[0][:value] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
n = args[0].value.to_i
|
||||
args = stack_extract( %i[any] * args[0].value )
|
||||
|
||||
args.reverse!
|
||||
|
||||
|
@ -106,16 +102,16 @@ module RplLang
|
|||
'Stack',
|
||||
'( … -- … n ) push stack depth onto the stack',
|
||||
proc do
|
||||
@stack << { type: :numeric, base: 10, value: BigDecimal( stack.size ) }
|
||||
@stack << RplNumeric.new( stack.size )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['roll'],
|
||||
'Stack',
|
||||
'( … a -- a … ) move a stack element to the top of the stack',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
n = args[0][:value]
|
||||
args = stack_extract( %i[any] * args[0][:value] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
n = args[0].value
|
||||
args = stack_extract( %i[any] * args[0].value )
|
||||
|
||||
args.reverse!
|
||||
|
||||
|
@ -130,9 +126,9 @@ module RplLang
|
|||
'Stack',
|
||||
'( a … -- … a ) move the element on top of the stack to a higher stack position',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
n = args[0][:value]
|
||||
args = stack_extract( %i[any] * args[0][:value] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
n = args[0].value
|
||||
args = stack_extract( %i[any] * args[0].value )
|
||||
|
||||
args.reverse!
|
||||
|
||||
|
@ -146,9 +142,7 @@ module RplLang
|
|||
@dictionary.add_word( ['over'],
|
||||
'Stack',
|
||||
'( a b -- a b a ) push a copy of the element in stack level 2 onto the stack',
|
||||
proc do
|
||||
run( '2 pick' )
|
||||
end )
|
||||
RplProgram.new( '« 2 pick »' ) )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
module RplLang
|
||||
module Words
|
||||
module Store
|
||||
include Types
|
||||
|
||||
def populate_dictionary
|
||||
super
|
||||
|
||||
|
@ -10,9 +12,9 @@ module RplLang
|
|||
'Store',
|
||||
'( content name -- ) store to variable',
|
||||
proc do
|
||||
args = stack_extract( [%i[name], :any] )
|
||||
args = stack_extract( [[RplName], :any] )
|
||||
|
||||
@dictionary.add_var( args[0][:value],
|
||||
@dictionary.add_var( args[0].value,
|
||||
args[1] )
|
||||
end )
|
||||
|
||||
|
@ -20,9 +22,9 @@ module RplLang
|
|||
'Store',
|
||||
'( name -- … ) push content of variable name onto stack',
|
||||
proc do
|
||||
args = stack_extract( [%i[name]] )
|
||||
args = stack_extract( [[RplName]] )
|
||||
|
||||
content = @dictionary.lookup( args[0][:value] )
|
||||
content = @dictionary.lookup( args[0].value )
|
||||
|
||||
@stack << content unless content.nil?
|
||||
end )
|
||||
|
@ -31,17 +33,16 @@ module RplLang
|
|||
'Store',
|
||||
'( name -- ) delete variable',
|
||||
proc do
|
||||
args = stack_extract( [%i[name]] )
|
||||
args = stack_extract( [[RplName]] )
|
||||
|
||||
@dictionary.remove_var( args[0][:value] )
|
||||
@dictionary.remove_var( args[0].value )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['vars'],
|
||||
'Store',
|
||||
'( -- […] ) list variables',
|
||||
proc do
|
||||
@stack << { type: :list,
|
||||
value: (@dictionary.vars.keys + @dictionary.local_vars_layers.reduce([]) { |memo, layer| memo + layer.keys }).map { |name| { type: :name, value: name } } }
|
||||
@stack << RplList.new( (@dictionary.vars.keys + @dictionary.local_vars_layers.reduce([]) { |memo, layer| memo + layer.keys }).map { |name| RplName.new( name ) } )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['clusr'],
|
||||
|
@ -54,68 +55,52 @@ module RplLang
|
|||
@dictionary.add_word( ['sto+'],
|
||||
'Store',
|
||||
'( a n -- ) add content to variable\'s value',
|
||||
proc do
|
||||
run( '
|
||||
dup type "name" ==
|
||||
RplProgram.new( '« dup type "Name" ==
|
||||
« swap »
|
||||
ift
|
||||
over rcl + swap sto' )
|
||||
end )
|
||||
over rcl + swap sto »' ) )
|
||||
|
||||
@dictionary.add_word( ['sto-'],
|
||||
'Store',
|
||||
'( a n -- ) subtract content to variable\'s value',
|
||||
proc do
|
||||
run( '
|
||||
dup type "name" ==
|
||||
RplProgram.new( '« dup type "Name" ==
|
||||
« swap »
|
||||
ift
|
||||
over rcl swap - swap sto' )
|
||||
end )
|
||||
over rcl swap - swap sto »' ) )
|
||||
|
||||
@dictionary.add_word( ['sto×', 'sto*'],
|
||||
'Store',
|
||||
'( a n -- ) multiply content of variable\'s value',
|
||||
proc do
|
||||
run( '
|
||||
dup type "name" ==
|
||||
RplProgram.new( '« dup type "Name" ==
|
||||
« swap »
|
||||
ift
|
||||
over rcl * swap sto' )
|
||||
end )
|
||||
over rcl * swap sto »' ) )
|
||||
|
||||
@dictionary.add_word( ['sto÷', 'sto/'],
|
||||
'Store',
|
||||
'( a n -- ) divide content of variable\'s value',
|
||||
proc do
|
||||
run( '
|
||||
dup type "name" ==
|
||||
RplProgram.new( '« dup type "Name" ==
|
||||
« swap »
|
||||
ift
|
||||
over rcl swap / swap sto' )
|
||||
end )
|
||||
over rcl swap / swap sto »' ) )
|
||||
|
||||
@dictionary.add_word( ['sneg'],
|
||||
'Store',
|
||||
'( a n -- ) negate content of variable\'s value',
|
||||
proc do
|
||||
run( 'dup rcl chs swap sto' )
|
||||
end )
|
||||
RplProgram.new( '« dup rcl chs swap sto »' ) )
|
||||
|
||||
@dictionary.add_word( ['sinv'],
|
||||
'Store',
|
||||
'( a n -- ) invert content of variable\'s value',
|
||||
proc do
|
||||
run( 'dup rcl inv swap sto' )
|
||||
end )
|
||||
RplProgram.new( '« dup rcl inv swap sto »' ) )
|
||||
|
||||
@dictionary.add_word( ['↴', 'lsto'],
|
||||
'Program',
|
||||
'( content name -- ) store to local variable',
|
||||
proc do
|
||||
args = stack_extract( [%i[name], :any] )
|
||||
args = stack_extract( [[RplName], :any] )
|
||||
|
||||
@dictionary.add_local_var( args[0][:value],
|
||||
@dictionary.add_local_var( args[0].value,
|
||||
args[1] )
|
||||
end )
|
||||
end
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
module RplLang
|
||||
module Words
|
||||
module StringAndList
|
||||
include Types
|
||||
|
||||
def populate_dictionary
|
||||
super
|
||||
|
||||
|
@ -12,37 +14,35 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [:any] )
|
||||
|
||||
@stack << { type: :string,
|
||||
value: stringify( args[0] ) }
|
||||
@stack << RplString.new( "\"#{args[0]}\"" )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['str→', 'str->'],
|
||||
'String',
|
||||
'( s -- a ) convert string to element',
|
||||
proc do
|
||||
args = stack_extract( [%i[string]] )
|
||||
args = stack_extract( [[RplString]] )
|
||||
|
||||
@stack += parse( args[0][:value] )
|
||||
@stack += Parser.parse( args[0].value )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['→list', '->list'],
|
||||
'Lists',
|
||||
'( … x -- […] ) pack x stacks levels into a list',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
args = stack_extract( %i[any] * args[0][:value] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
args = stack_extract( %i[any] * args[0].value )
|
||||
|
||||
@stack << { type: :list,
|
||||
value: args.reverse }
|
||||
@stack << RplList.new( args.reverse )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['list→', 'list->'],
|
||||
'Lists',
|
||||
'( […] -- … ) unpack list on stack',
|
||||
proc do
|
||||
args = stack_extract( [%i[list]] )
|
||||
args = stack_extract( [[RplList]] )
|
||||
|
||||
args[0][:value].each do |elt|
|
||||
args[0].value.each do |elt|
|
||||
@stack << elt
|
||||
end
|
||||
end )
|
||||
|
@ -51,83 +51,66 @@ module RplLang
|
|||
'String',
|
||||
'( n -- c ) convert ASCII character code in stack level 1 into a string',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
@stack << { type: :string,
|
||||
value: args[0][:value].to_i.chr }
|
||||
@stack << RplString.new( "\"#{args[0].value.to_i.chr}\"" )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['num'],
|
||||
'String',
|
||||
'( s -- n ) return ASCII code of the first character of the string in stack level 1 as a real number',
|
||||
proc do
|
||||
args = stack_extract( [%i[string]] )
|
||||
args = stack_extract( [[RplString]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: BigDecimal( args[0][:value].ord ) }
|
||||
@stack << RplNumeric.new( args[0].value.ord )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['size'],
|
||||
'String',
|
||||
'( s -- n ) return the length of the string or list',
|
||||
proc do
|
||||
args = stack_extract( [%i[string list]] )
|
||||
args = stack_extract( [[RplString, RplList]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: BigDecimal( args[0][:value].length ) }
|
||||
@stack << RplNumeric.new( args[0].value.length )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['pos'],
|
||||
'String',
|
||||
'( s s -- n ) search for the string in level 1 within the string in level 2',
|
||||
proc do
|
||||
args = stack_extract( [%i[string], %i[string]] )
|
||||
args = stack_extract( [[RplString], [RplString]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: BigDecimal( args[1][:value].index( args[0][:value] ) ) }
|
||||
@stack << RplNumeric.new( args[1].value.index( args[0].value ) )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['sub'],
|
||||
'String',
|
||||
'( s n n -- s ) return a substring of the string in level 3',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric], %i[numeric], %i[string]] )
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric], [RplString]] )
|
||||
|
||||
@stack << { type: :string,
|
||||
value: args[2][:value][ (args[1][:value] - 1)..(args[0][:value] - 1) ] }
|
||||
@stack << RplString.new( "\"#{args[2].value[ (args[1].value - 1)..(args[0].value - 1) ]}\"" )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['rev'],
|
||||
'String',
|
||||
'( s -- s ) reverse string or list',
|
||||
proc do
|
||||
args = stack_extract( [%i[string list]] )
|
||||
args = stack_extract( [[RplString, RplList]] )
|
||||
|
||||
result = args[0]
|
||||
args[0].value.reverse!
|
||||
|
||||
case args[0][:type]
|
||||
when :string
|
||||
result = { type: :string,
|
||||
value: args[0][:value].reverse }
|
||||
when :list
|
||||
result[:value].reverse!
|
||||
end
|
||||
|
||||
@stack << result
|
||||
@stack << args[0]
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['split'],
|
||||
'String',
|
||||
'( s c -- … ) split string s on character c',
|
||||
proc do
|
||||
args = stack_extract( [%i[string], %i[string]] )
|
||||
args = stack_extract( [[RplString], [RplString]] )
|
||||
|
||||
args[1][:value].split( args[0][:value] ).each do |elt|
|
||||
@stack << { type: :string,
|
||||
value: elt }
|
||||
args[1].value.split( args[0].value ).each do |elt|
|
||||
@stack << RplString.new( "\"#{elt}\"" )
|
||||
end
|
||||
end )
|
||||
|
||||
|
@ -135,14 +118,14 @@ module RplLang
|
|||
'Lists',
|
||||
'( […] prg -- … ) run prg on each element of a list',
|
||||
proc do
|
||||
args = stack_extract( [%i[program], %i[list]] )
|
||||
args = stack_extract( [[RplProgram], [RplList]] )
|
||||
|
||||
args[1][:value].each do |elt|
|
||||
args[1].value.each do |elt|
|
||||
@stack << elt
|
||||
run( args[0][:value] )
|
||||
run( args[0].value )
|
||||
end
|
||||
|
||||
run( "#{args[1][:value].length} →list" )
|
||||
run( "#{args[1].value.length} →list" )
|
||||
end )
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
module RplLang
|
||||
module Words
|
||||
module Test
|
||||
include Types
|
||||
|
||||
def populate_dictionary
|
||||
super
|
||||
|
||||
|
@ -12,8 +14,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( %i[any any] )
|
||||
|
||||
@stack << { type: :boolean,
|
||||
value: args[1][:value] > args[0][:value] }
|
||||
@stack << RplBoolean.new( args[1].value > args[0].value )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['≥', '>='],
|
||||
|
@ -22,8 +23,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( %i[any any] )
|
||||
|
||||
@stack << { type: :boolean,
|
||||
value: args[1][:value] >= args[0][:value] }
|
||||
@stack << RplBoolean.new( args[1].value >= args[0].value )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['<'],
|
||||
|
@ -32,8 +32,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( %i[any any] )
|
||||
|
||||
@stack << { type: :boolean,
|
||||
value: args[1][:value] < args[0][:value] }
|
||||
@stack << RplBoolean.new( args[1].value < args[0].value )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['≤', '<='],
|
||||
|
@ -42,8 +41,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( %i[any any] )
|
||||
|
||||
@stack << { type: :boolean,
|
||||
value: args[1][:value] <= args[0][:value] }
|
||||
@stack << RplBoolean.new( args[1].value <= args[0].value )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['≠', '!='],
|
||||
|
@ -52,8 +50,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( %i[any any] )
|
||||
|
||||
@stack << { type: :boolean,
|
||||
value: args[1][:value] != args[0][:value] }
|
||||
@stack << RplBoolean.new( args[1].value != args[0].value )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['==', 'same'],
|
||||
|
@ -62,64 +59,57 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( %i[any any] )
|
||||
|
||||
@stack << { type: :boolean,
|
||||
value: args[1][:value] == args[0][:value] }
|
||||
@stack << RplBoolean.new( args[1].value == args[0].value )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['and'],
|
||||
'Test',
|
||||
'( a b -- t ) boolean and',
|
||||
proc do
|
||||
args = stack_extract( [%i[boolean], %i[boolean]] )
|
||||
args = stack_extract( [[RplBoolean], [RplBoolean]] )
|
||||
|
||||
@stack << { type: :boolean,
|
||||
value: args[1][:value] && args[0][:value] }
|
||||
@stack << RplBoolean.new( args[1].value && args[0].value )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['or'],
|
||||
'Test',
|
||||
'( a b -- t ) boolean or',
|
||||
proc do
|
||||
args = stack_extract( [%i[boolean], %i[boolean]] )
|
||||
args = stack_extract( [[RplBoolean], [RplBoolean]] )
|
||||
|
||||
@stack << { type: :boolean,
|
||||
value: args[1][:value] || args[0][:value] }
|
||||
@stack << RplBoolean.new( args[1].value || args[0].value )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['xor'],
|
||||
'Test',
|
||||
'( a b -- t ) boolean xor',
|
||||
proc do
|
||||
args = stack_extract( [%i[boolean], %i[boolean]] )
|
||||
args = stack_extract( [[RplBoolean], [RplBoolean]] )
|
||||
|
||||
@stack << { type: :boolean,
|
||||
value: args[1][:value] ^ args[0][:value] }
|
||||
@stack << RplBoolean.new( args[1].value ^ args[0].value )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['not'],
|
||||
'Test',
|
||||
'( a -- t ) invert boolean value',
|
||||
proc do
|
||||
args = stack_extract( [%i[boolean]] )
|
||||
args = stack_extract( [[RplBoolean]] )
|
||||
|
||||
@stack << { type: :boolean,
|
||||
value: !args[0][:value] }
|
||||
@stack << RplBoolean.new(!args[0].value )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['true'],
|
||||
'Test',
|
||||
'( -- t ) push true onto stack',
|
||||
proc do
|
||||
@stack << { type: :boolean,
|
||||
value: true }
|
||||
@stack << RplBoolean.new( true )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['false'],
|
||||
'Test',
|
||||
'( -- t ) push false onto stack',
|
||||
proc do
|
||||
@stack << { type: :boolean,
|
||||
value: false }
|
||||
@stack << RplBoolean.new( false )
|
||||
end )
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,6 +5,8 @@ require 'date'
|
|||
module RplLang
|
||||
module Words
|
||||
module TimeAndDate
|
||||
include Types
|
||||
|
||||
def populate_dictionary
|
||||
super
|
||||
|
||||
|
@ -12,15 +14,13 @@ module RplLang
|
|||
'Time and date',
|
||||
'( -- t ) push current time',
|
||||
proc do
|
||||
@stack << { type: :string,
|
||||
value: Time.now.to_s }
|
||||
@stack << RplString.new( "\"#{Time.now}\"" )
|
||||
end )
|
||||
@dictionary.add_word( ['date'],
|
||||
'Time and date',
|
||||
'( -- d ) push current date',
|
||||
proc do
|
||||
@stack << { type: :string,
|
||||
value: Date.today.to_s }
|
||||
@stack << RplString.new( "\"#{Date.today}\"" )
|
||||
end )
|
||||
@dictionary.add_word( ['ticks'],
|
||||
'Time and date',
|
||||
|
@ -28,9 +28,7 @@ module RplLang
|
|||
proc do
|
||||
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 }
|
||||
@stack << RplNumeric.new( now.to_i * 10_000_000 + now.nsec / 100 - ticks_since_epoch )
|
||||
end )
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
module RplLang
|
||||
module Words
|
||||
module Trig
|
||||
include Types
|
||||
|
||||
def populate_dictionary
|
||||
super
|
||||
|
||||
|
@ -12,49 +14,38 @@ module RplLang
|
|||
'Trig on reals and complexes',
|
||||
'( … -- 𝛑 ) push 𝛑',
|
||||
proc do
|
||||
@stack << { type: :numeric,
|
||||
base: 10,
|
||||
value: BigMath.PI( precision ) }
|
||||
@stack << RplNumeric.new( BigMath.PI( RplNumeric.precision ) )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['sin'],
|
||||
'Trig on reals and complexes',
|
||||
'( n -- m ) compute sinus of n',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: BigMath.sin( BigDecimal( args[0][:value], precision ), precision ) }
|
||||
@stack << RplNumeric.new( BigMath.sin( BigDecimal( args[0].value, RplNumeric.precision ), RplNumeric.precision ) )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['asin'],
|
||||
'Trig on reals and complexes',
|
||||
'( n -- m ) compute arg-sinus of n',
|
||||
proc do
|
||||
run( '
|
||||
dup abs 1 ==
|
||||
RplProgram.new( '« dup abs 1 ==
|
||||
« 𝛑 2 / * »
|
||||
« dup sq 1 swap - sqrt / atan »
|
||||
ifte' )
|
||||
end )
|
||||
ifte »' ) )
|
||||
|
||||
@dictionary.add_word( ['cos'],
|
||||
'Trig on reals and complexes',
|
||||
'( n -- m ) compute cosinus of n',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: BigMath.cos( BigDecimal( args[0][:value], precision ), precision ) }
|
||||
@stack << RplNumeric.new( BigMath.cos( BigDecimal( args[0].value, RplNumeric.precision ), RplNumeric.precision ) )
|
||||
end )
|
||||
@dictionary.add_word( ['acos'],
|
||||
'Trig on reals and complexes',
|
||||
'( n -- m ) compute arg-cosinus of n',
|
||||
proc do
|
||||
run( '
|
||||
dup 0 ==
|
||||
RplProgram.new( '« dup 0 ==
|
||||
« drop 𝛑 2 / »
|
||||
«
|
||||
dup sq 1 swap - sqrt / atan
|
||||
|
@ -62,38 +53,31 @@ module RplLang
|
|||
« 𝛑 + »
|
||||
ift
|
||||
»
|
||||
ifte' )
|
||||
end )
|
||||
ifte »' ) )
|
||||
|
||||
@dictionary.add_word( ['tan'],
|
||||
'Trig on reals and complexes',
|
||||
'( n -- m ) compute tangent of n',
|
||||
proc do
|
||||
run( 'dup sin swap cos /' )
|
||||
end )
|
||||
RplProgram.new( '« dup sin swap cos / »' ) )
|
||||
|
||||
@dictionary.add_word( ['atan'],
|
||||
'Trig on reals and complexes',
|
||||
'( n -- m ) compute arc-tangent of n',
|
||||
proc do
|
||||
args = stack_extract( [%i[numeric]] )
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
@stack << RplNumeric.new( BigMath.atan( BigDecimal( args[0].value, RplNumeric.precision ), RplNumeric.precision ) )
|
||||
end )
|
||||
|
||||
@stack << { type: :numeric,
|
||||
base: infer_resulting_base( args ),
|
||||
value: BigMath.atan( BigDecimal( args[0][:value], precision ), precision ) }
|
||||
end)
|
||||
@dictionary.add_word( ['d→r', 'd->r'],
|
||||
'Trig on reals and complexes',
|
||||
'( n -- m ) convert degree to radian',
|
||||
proc do
|
||||
run( '180 / 𝛑 *' )
|
||||
end )
|
||||
RplProgram.new( '« 180 / 𝛑 * »' ) )
|
||||
|
||||
@dictionary.add_word( ['r→d', 'r->d'],
|
||||
'Trig on reals and complexes',
|
||||
'( n -- m ) convert radian to degree',
|
||||
proc do
|
||||
run( '𝛑 180 / /' )
|
||||
end)
|
||||
RplProgram.new( '« 𝛑 180 / / »' ) )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,29 +5,24 @@ require 'minitest/autorun'
|
|||
require 'rpl'
|
||||
|
||||
class TestParser < MiniTest::Test
|
||||
include Types
|
||||
|
||||
def test_stack_extract
|
||||
interpreter = Rpl.new( [{ value: 1, type: :numeric },
|
||||
{ value: 2, type: :numeric }] )
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 2'
|
||||
args = interpreter.stack_extract [:any]
|
||||
assert_equal [{ value: 1, type: :numeric }],
|
||||
assert_equal [RplNumeric.new( 1 )],
|
||||
interpreter.stack
|
||||
assert_equal [{ value: 2, type: :numeric }],
|
||||
assert_equal [RplNumeric.new( 2 )],
|
||||
args
|
||||
|
||||
interpreter = Rpl.new( [{ value: 'test', type: :string },
|
||||
{ value: 2, type: :numeric }] )
|
||||
args = interpreter.stack_extract [[:numeric], :any]
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '"test" 2'
|
||||
args = interpreter.stack_extract [[RplNumeric], :any]
|
||||
assert_equal [],
|
||||
interpreter.stack
|
||||
assert_equal [{ value: 2, type: :numeric },
|
||||
{ value: 'test', type: :string }],
|
||||
assert_equal [RplNumeric.new( 2 ),
|
||||
RplString.new( '"test"' )],
|
||||
args
|
||||
end
|
||||
|
||||
def test_stringify
|
||||
assert_equal '∞',
|
||||
Rpl.new.stringify( { value: Float::INFINITY,
|
||||
base: 10,
|
||||
type: :numeric } )
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,16 +6,18 @@ require 'minitest/autorun'
|
|||
require 'rpl'
|
||||
|
||||
class TestLanguageBranch < MiniTest::Test
|
||||
include Types
|
||||
|
||||
def test_loop
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '« "hello no." swap + » 11 16 loop'
|
||||
|
||||
assert_equal [{ value: 'hello no.11', type: :string },
|
||||
{ value: 'hello no.12', type: :string },
|
||||
{ value: 'hello no.13', type: :string },
|
||||
{ value: 'hello no.14', type: :string },
|
||||
{ value: 'hello no.15', type: :string },
|
||||
{ value: 'hello no.16', type: :string }],
|
||||
assert_equal [RplString.new( '"hello no.11"' ),
|
||||
RplString.new( '"hello no.12"' ),
|
||||
RplString.new( '"hello no.13"' ),
|
||||
RplString.new( '"hello no.14"' ),
|
||||
RplString.new( '"hello no.15"' ),
|
||||
RplString.new( '"hello no.16"' )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -23,11 +25,11 @@ class TestLanguageBranch < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '« "hello no." swap + » 5 times'
|
||||
|
||||
assert_equal [{ value: 'hello no.0', type: :string },
|
||||
{ value: 'hello no.1', type: :string },
|
||||
{ value: 'hello no.2', type: :string },
|
||||
{ value: 'hello no.3', type: :string },
|
||||
{ value: 'hello no.4', type: :string }],
|
||||
assert_equal [RplString.new( '"hello no.0"' ),
|
||||
RplString.new( '"hello no.1"' ),
|
||||
RplString.new( '"hello no.2"' ),
|
||||
RplString.new( '"hello no.3"' ),
|
||||
RplString.new( '"hello no.4"' )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -35,13 +37,13 @@ class TestLanguageBranch < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run 'true « 2 3 + » « 2 3 - » ifte'
|
||||
|
||||
assert_equal [{ value: 5, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 5 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run 'false « 2 3 + » « 2 3 - » ifte'
|
||||
|
||||
assert_equal [{ value: -1, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( -1 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -49,7 +51,7 @@ class TestLanguageBranch < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run 'true « 2 3 + » ift'
|
||||
|
||||
assert_equal [{ value: 5, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 5 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
|
|
|
@ -6,24 +6,26 @@ require 'minitest/autorun'
|
|||
require 'rpl'
|
||||
|
||||
class TestLanguageFileSystem < MiniTest::Test
|
||||
include Types
|
||||
|
||||
def test_fread
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '"./spec/test.rpl" fread'
|
||||
|
||||
assert_equal [{:type=>:string, :value=>"1 2 +\n\n« dup dup * * »\n'trrr' sto\n\ntrrr\n"}],
|
||||
assert_equal [RplString.new( "\"1 2 +\n\n« dup dup * * »\n'trrr' sto\n\ntrrr\n\"" )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter.run 'eval vars'
|
||||
assert_equal [{ value: 27, base: 10, type: :numeric },
|
||||
{ value: [{ type: :name, value: 'trrr' }], type: :list }],
|
||||
assert_equal [RplNumeric.new( 27 ),
|
||||
RplList.new( [ RplName.new( 'trrr' ) ] )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_feval
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '"spec/test.rpl" feval vars'
|
||||
assert_equal [{ value: 27, base: 10, type: :numeric },
|
||||
{ value: [{ type: :name, value: 'trrr' }], type: :list }],
|
||||
assert_equal [RplNumeric.new( 27 ),
|
||||
RplList.new( [ RplName.new( 'trrr' ) ] )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
|
|
@ -6,312 +6,309 @@ require 'minitest/autorun'
|
|||
require 'rpl'
|
||||
|
||||
class TesttLanguageOperations < MiniTest::Test
|
||||
include Types
|
||||
|
||||
def test_add
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 +'
|
||||
assert_equal [{ value: 3, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 3 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 "a" +'
|
||||
assert_equal [{ value: '1a', type: :string }],
|
||||
assert_equal [RplString.new( '"1a"' )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 \'a\' +'
|
||||
assert_equal [{ value: '1a', type: :string }],
|
||||
assert_equal [RplName.new( "'1a'" )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 dup dup →list +'
|
||||
assert_equal [{ value: [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 1, type: :numeric, base: 10 }],
|
||||
type: :list }],
|
||||
assert_equal [RplList.new( [RplNumeric.new( 1 ),
|
||||
RplNumeric.new( 1 )] )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '"a" "b" +'
|
||||
assert_equal [{ value: 'ab', type: :string }],
|
||||
assert_equal [RplString.new( '"ab"' )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '"a" \'b\' +'
|
||||
assert_equal [{ value: 'ab', type: :string }],
|
||||
assert_equal [RplString.new( '"ab"' )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '"a" 1 +'
|
||||
assert_equal [{ value: 'a1', type: :string }],
|
||||
assert_equal [RplString.new( '"a1"' )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '"a" 1 dup →list +'
|
||||
assert_equal [{ value: [{ value: 'a', type: :string },
|
||||
{ value: 1, type: :numeric, base: 10 }],
|
||||
type: :list }],
|
||||
assert_equal [RplList.new( [RplString.new( '"a"' ),
|
||||
RplNumeric.new( 1 )] )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '\'a\' 1 +'
|
||||
assert_equal [{ value: 'a1', type: :name }],
|
||||
assert_equal [RplName.new( 'a1' )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '\'a\' "b" +'
|
||||
assert_equal [{ value: 'ab', type: :string }],
|
||||
assert_equal [RplString.new( '"ab"' )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '\'a\' \'b\' +'
|
||||
assert_equal [{ value: 'ab', type: :name }],
|
||||
assert_equal [RplName.new( "'ab'" )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '\'a\' 1 dup →list +'
|
||||
assert_equal [{ value: [{ value: 'a', type: :name },
|
||||
{ value: 1, type: :numeric, base: 10 }],
|
||||
type: :list }],
|
||||
assert_equal [RplList.new( [RplName.new( 'a' ),
|
||||
RplNumeric.new( 1 )] )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 a "test" 3 →list dup rev +'
|
||||
assert_equal [{ type: :list,
|
||||
value: [{ value: 1, type: :numeric, base: 10 },
|
||||
{ type: :name, value: 'a' },
|
||||
{ value: 'test', type: :string },
|
||||
{ value: 'test', type: :string },
|
||||
{ type: :name, value: 'a' },
|
||||
{ value: 1, type: :numeric, base: 10 }] }],
|
||||
assert_equal [RplList.new( [RplNumeric.new( 1 ),
|
||||
RplName.new( 'a' ),
|
||||
RplString.new( '"test"' ),
|
||||
RplString.new( '"test"' ),
|
||||
RplName.new( 'a' ),
|
||||
RplNumeric.new( 1 )] )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 a "test" 3 →list 9 +'
|
||||
assert_equal [{ type: :list,
|
||||
value: [{ value: 1, type: :numeric, base: 10 },
|
||||
{ type: :name, value: 'a' },
|
||||
{ value: 'test', type: :string },
|
||||
{ value: 9, type: :numeric, base: 10 }] }],
|
||||
assert_equal [RplList.new( [RplNumeric.new( 1 ),
|
||||
RplName.new( 'a' ),
|
||||
RplString.new( '"test"' ),
|
||||
RplNumeric.new( 9 )] )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_subtract
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 -'
|
||||
assert_equal [{ value: -1, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( -1 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '2 1 -'
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_negate
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '-1 chs'
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 chs'
|
||||
assert_equal [{ value: -1, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( -1 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_multiply
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '3 4 *'
|
||||
assert_equal [{ value: 12, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 12 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_divide
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '3.0 4 /'
|
||||
assert_equal [{ value: 0.75, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 0.75 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_inverse
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '4 inv'
|
||||
assert_equal [{ value: 0.25, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 0.25 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_power
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '3 4 ^'
|
||||
assert_equal [{ value: 81, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 81 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_sqrt
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '16 √'
|
||||
assert_equal [{ value: 4, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 4 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_sq
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '4 sq'
|
||||
assert_equal [{ value: 16, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 16 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_abs
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '-1 abs'
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 abs'
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_dec
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '0x1 dec'
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_hex
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 hex'
|
||||
assert_equal [{ value: 1, type: :numeric, base: 16 }],
|
||||
assert_equal [RplNumeric.new( 1, 16 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_bin
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 bin'
|
||||
assert_equal [{ value: 1, type: :numeric, base: 2 }],
|
||||
assert_equal [RplNumeric.new( 1, 2 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_base
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 31 base'
|
||||
assert_equal [{ value: 1, type: :numeric, base: 31 }],
|
||||
assert_equal [RplNumeric.new( 1, 31 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_sign
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '-10 sign'
|
||||
assert_equal [{ value: -1, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( -1 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '10 sign'
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '0 sign'
|
||||
assert_equal [{ value: 0, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 0 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_percent
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '2 33 %'
|
||||
assert_equal [{ value: 0.66, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 0.66 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_inverse_percent
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '2 0.66 %CH'
|
||||
assert_equal [{ value: 33, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 33 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_mod
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '9 4 mod'
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_fact
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '5 !'
|
||||
assert_equal [{ value: 24, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 24 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_floor
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '5.23 floor'
|
||||
assert_equal [{ value: 5, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 5 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_ceil
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '5.23 ceil'
|
||||
assert_equal [{ value: 6, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 6 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_min
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 min'
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '2 1 min'
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_max
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 max'
|
||||
assert_equal [{ value: 2, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 2 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '2 1 max'
|
||||
assert_equal [{ value: 2, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 2 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_ip
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '3.14 ip'
|
||||
assert_equal [{ value: 3, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 3 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_fp
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '3.14 fp'
|
||||
assert_equal [{ value: 0.14, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 0.14 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_mant
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '123.456 mant -123.456 mant 0 mant'
|
||||
assert_equal [{ type: :numeric, base: 10, value: BigDecimal( 0.123456, interpreter.precision ) },
|
||||
{ type: :numeric, base: 10, value: BigDecimal( 0.123456, interpreter.precision ) },
|
||||
{ type: :numeric, base: 10, value: BigDecimal( 0 ) }],
|
||||
assert_equal [RplNumeric.new( 0.123456 ),
|
||||
RplNumeric.new( 0.123456 ),
|
||||
RplNumeric.new( 0 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_xpon
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '123.456 xpon -123.456 xpon 0 xpon'
|
||||
assert_equal [{ value: 3, type: :numeric, base: 10 },
|
||||
{ value: 3, type: :numeric, base: 10 },
|
||||
{ value: 0, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 3 ),
|
||||
RplNumeric.new( 3 ),
|
||||
RplNumeric.new( 0 )],
|
||||
interpreter.stack
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,19 +5,21 @@ require 'minitest/autorun'
|
|||
require 'rpl'
|
||||
|
||||
class TestLanguageProgram < MiniTest::Test
|
||||
include Types
|
||||
|
||||
def test_eval
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '« 2 dup * dup » eval'
|
||||
|
||||
assert_equal [{ value: 4, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 4 ),
|
||||
RplNumeric.new( 4 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '4 \'dup\' eval'
|
||||
|
||||
assert_equal [{ value: 4, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 4 ),
|
||||
RplNumeric.new( 4 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
|
@ -25,8 +27,8 @@ class TestLanguageProgram < MiniTest::Test
|
|||
\'dup\'
|
||||
eval'
|
||||
|
||||
assert_equal [{ value: 4, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 4 ),
|
||||
RplNumeric.new( 4 )],
|
||||
interpreter.stack
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,12 +6,14 @@ require 'minitest/autorun'
|
|||
require 'rpl'
|
||||
|
||||
class TestLanguageStack < MiniTest::Test
|
||||
include Types
|
||||
|
||||
def test_swap
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 swap'
|
||||
|
||||
assert_equal [{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 1, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 2 ),
|
||||
RplNumeric.new( 1 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -19,7 +21,7 @@ class TestLanguageStack < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 drop'
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -35,7 +37,7 @@ class TestLanguageStack < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 3 4 3 dropn'
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -50,9 +52,9 @@ class TestLanguageStack < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 3 rot'
|
||||
|
||||
assert_equal [{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 3, type: :numeric, base: 10 },
|
||||
{ value: 1, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 2 ),
|
||||
RplNumeric.new( 3 ),
|
||||
RplNumeric.new( 1 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -60,9 +62,9 @@ class TestLanguageStack < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 dup'
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 ),
|
||||
RplNumeric.new( 2 ),
|
||||
RplNumeric.new( 2 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -70,10 +72,10 @@ class TestLanguageStack < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 dup2'
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 ),
|
||||
RplNumeric.new( 2 ),
|
||||
RplNumeric.new( 1 ),
|
||||
RplNumeric.new( 2 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -81,13 +83,13 @@ class TestLanguageStack < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 3 4 3 dupn'
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 3, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 3, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 ),
|
||||
RplNumeric.new( 2 ),
|
||||
RplNumeric.new( 3 ),
|
||||
RplNumeric.new( 4 ),
|
||||
RplNumeric.new( 2 ),
|
||||
RplNumeric.new( 3 ),
|
||||
RplNumeric.new( 4 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -95,11 +97,11 @@ class TestLanguageStack < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 3 4 3 pick'
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 3, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 ),
|
||||
RplNumeric.new( 2 ),
|
||||
RplNumeric.new( 3 ),
|
||||
RplNumeric.new( 4 ),
|
||||
RplNumeric.new( 2 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -107,15 +109,15 @@ class TestLanguageStack < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run 'depth'
|
||||
|
||||
assert_equal [{ value: 0, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 0 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 depth'
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 ),
|
||||
RplNumeric.new( 2 ),
|
||||
RplNumeric.new( 2 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -123,10 +125,10 @@ class TestLanguageStack < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 3 4 3 roll'
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 3, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 ),
|
||||
RplNumeric.new( 3 ),
|
||||
RplNumeric.new( 4 ),
|
||||
RplNumeric.new( 2 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -134,10 +136,10 @@ class TestLanguageStack < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 4 3 2 rolld'
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 3, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 ),
|
||||
RplNumeric.new( 2 ),
|
||||
RplNumeric.new( 3 ),
|
||||
RplNumeric.new( 4 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -145,11 +147,11 @@ class TestLanguageStack < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 3 4 over'
|
||||
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 },
|
||||
{ value: 2, type: :numeric, base: 10 },
|
||||
{ value: 3, type: :numeric, base: 10 },
|
||||
{ value: 4, type: :numeric, base: 10 },
|
||||
{ value: 3, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1 ),
|
||||
RplNumeric.new( 2 ),
|
||||
RplNumeric.new( 3 ),
|
||||
RplNumeric.new( 4 ),
|
||||
RplNumeric.new( 3 )],
|
||||
interpreter.stack
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,14 +4,16 @@ require 'minitest/autorun'
|
|||
|
||||
require 'rpl'
|
||||
|
||||
class TestLanguageProgram < MiniTest::Test
|
||||
class TestLanguageStore < MiniTest::Test
|
||||
include Types
|
||||
|
||||
def test_sto
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '« 2 dup * » \'quatre\' sto'
|
||||
assert_empty interpreter.stack
|
||||
|
||||
interpreter.run 'quatre'
|
||||
assert_equal [{ value: 4, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 4 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -20,21 +22,21 @@ class TestLanguageProgram < MiniTest::Test
|
|||
interpreter.run "« 2 'deux' lsto deux dup * » eval 'deux' rcl"
|
||||
|
||||
assert_empty interpreter.dictionary.local_vars_layers
|
||||
assert_equal [{ value: 4, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 4 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run "« 2 'deux' lsto « 3 'trois' lsto trois drop » eval deux dup * » eval 'deux' rcl 'trois' rcl"
|
||||
|
||||
assert_empty interpreter.dictionary.local_vars_layers
|
||||
assert_equal [{ value: 4, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 4 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_rcl
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '« 2 dup * » \'quatre\' sto \'quatre\' rcl'
|
||||
assert_equal [{ value: '2 dup *', type: :program }],
|
||||
assert_equal [RplProgram.new( '« 2 dup * »' )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -47,8 +49,8 @@ class TestLanguageProgram < MiniTest::Test
|
|||
def test_vars
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '« 2 dup * » \'quatre\' sto 1 \'un\' sto vars'
|
||||
assert_equal [{ value: [{ type: :name, value: 'quatre' },
|
||||
{ type: :name, value: 'un' }], type: :list }],
|
||||
assert_equal [RplList.new( [RplName.new( 'quatre' ),
|
||||
RplName.new( 'un' )] )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -61,62 +63,62 @@ class TestLanguageProgram < MiniTest::Test
|
|||
def test_sto_add
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 \'test\' sto \'test\' 3 sto+ \'test\' rcl'
|
||||
assert_equal [{ value: 4, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 4 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 \'test\' sto 3 \'test\' sto+ \'test\' rcl'
|
||||
assert_equal [{ value: 4, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 4 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_sto_subtract
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 \'test\' sto \'test\' 3 sto- \'test\' rcl'
|
||||
assert_equal [{ value: -2, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( -2 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 \'test\' sto 3 \'test\' sto- \'test\' rcl'
|
||||
assert_equal [{ value: -2, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( -2 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_sto_multiply
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '2 \'test\' sto \'test\' 3 sto* \'test\' rcl'
|
||||
assert_equal [{ value: 6, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 6 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '2 \'test\' sto 3 \'test\' sto* \'test\' rcl'
|
||||
assert_equal [{ value: 6, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 6 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_sto_divide
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '3 \'test\' sto \'test\' 2.0 sto÷ \'test\' rcl'
|
||||
assert_equal [{ value: 1.5, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1.5 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '3 \'test\' sto 2.0 \'test\' sto÷ \'test\' rcl'
|
||||
assert_equal [{ value: 1.5, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 1.5 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_sto_negate
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '3 \'test\' sto \'test\' sneg \'test\' rcl'
|
||||
assert_equal [{ value: -3, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( -3 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_sto_inverse
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '2 \'test\' sto \'test\' sinv \'test\' rcl'
|
||||
assert_equal [{ value: 0.5, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 0.5 )],
|
||||
interpreter.stack
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,11 +6,13 @@ require 'minitest/autorun'
|
|||
require 'rpl'
|
||||
|
||||
class TestLanguageString < MiniTest::Test
|
||||
include Types
|
||||
|
||||
def test_to_string
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '2 →str'
|
||||
|
||||
assert_equal [{ value: '2', type: :string }],
|
||||
assert_equal [RplString.new( '"2"' )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -18,15 +20,15 @@ class TestLanguageString < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '"2" str→'
|
||||
|
||||
assert_equal [{ value: 2, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 2 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '"« dup * » \'carré\' sto" str→'
|
||||
|
||||
assert_equal [{ value: 'dup *', type: :program },
|
||||
{ value: 'carré', type: :name },
|
||||
{ value: 'sto', type: :word }],
|
||||
assert_equal [RplProgram.new( '« dup * »' ),
|
||||
RplName.new( 'carré' ),
|
||||
RplName.new( 'sto' )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -34,7 +36,7 @@ class TestLanguageString < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '71 chr'
|
||||
|
||||
assert_equal [{ value: 'G', type: :string }],
|
||||
assert_equal [RplString.new( '"G"' )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -42,7 +44,7 @@ class TestLanguageString < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '"G" num'
|
||||
|
||||
assert_equal [{ value: 71, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 71 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -50,7 +52,7 @@ class TestLanguageString < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '"test" size'
|
||||
|
||||
assert_equal [{ value: 4, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 4 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -58,7 +60,7 @@ class TestLanguageString < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '"test of POS" "of" pos'
|
||||
|
||||
assert_equal [{ value: 5, type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 5 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -66,7 +68,7 @@ class TestLanguageString < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '"my string to sub" 4 6 sub'
|
||||
|
||||
assert_equal [{ value: 'str', type: :string }],
|
||||
assert_equal [RplString.new( '"str"' )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -74,7 +76,7 @@ class TestLanguageString < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '"my string to sub" rev'
|
||||
|
||||
assert_equal [{ value: 'my string to sub'.reverse, type: :string }],
|
||||
assert_equal [RplString.new( '"my string to sub"'.reverse )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -82,18 +84,18 @@ class TestLanguageString < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '"my string to sub" " " split'
|
||||
|
||||
assert_equal [{ value: 'my', type: :string },
|
||||
{ value: 'string', type: :string },
|
||||
{ value: 'to', type: :string },
|
||||
{ value: 'sub', type: :string }],
|
||||
assert_equal [RplString.new( '"my"' ),
|
||||
RplString.new( '"string"' ),
|
||||
RplString.new( '"to"' ),
|
||||
RplString.new( '"sub"' )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '"my,string,to sub" "," split'
|
||||
|
||||
assert_equal [{ value: 'my', type: :string },
|
||||
{ value: 'string', type: :string },
|
||||
{ value: 'to sub', type: :string }],
|
||||
assert_equal [RplString.new( '"my"' ),
|
||||
RplString.new( '"string"' ),
|
||||
RplString.new( '"to sub"' )],
|
||||
interpreter.stack
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,23 +6,25 @@ require 'minitest/autorun'
|
|||
require 'rpl'
|
||||
|
||||
class TestLanguageTest < MiniTest::Test
|
||||
include Types
|
||||
|
||||
def test_greater_than
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '0 0.1 >'
|
||||
|
||||
assert_equal [{ value: false, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( false )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '0.1 0 >'
|
||||
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 1 >'
|
||||
|
||||
assert_equal [{ value: false, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( false )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -30,19 +32,19 @@ class TestLanguageTest < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '0 0.1 >='
|
||||
|
||||
assert_equal [{ value: false, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( false )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '0.1 0 ≥'
|
||||
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 1 ≥'
|
||||
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -50,19 +52,19 @@ class TestLanguageTest < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '0 0.1 <'
|
||||
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '0.1 0 <'
|
||||
|
||||
assert_equal [{ value: false, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( false )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 1 <'
|
||||
|
||||
assert_equal [{ value: false, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( false )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -70,19 +72,19 @@ class TestLanguageTest < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '0 0.1 <='
|
||||
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '0.1 0 ≤'
|
||||
|
||||
assert_equal [{ value: false, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( false )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 1 ≤'
|
||||
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -90,13 +92,13 @@ class TestLanguageTest < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '1 1 !='
|
||||
|
||||
assert_equal [{ value: false, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( false )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 ≠'
|
||||
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -104,25 +106,25 @@ class TestLanguageTest < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run 'true true and'
|
||||
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run 'false false and'
|
||||
|
||||
assert_equal [{ value: false, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( false )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run 'true false and'
|
||||
|
||||
assert_equal [{ value: false, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( false )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run 'false true and'
|
||||
|
||||
assert_equal [{ value: false, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( false )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -130,25 +132,25 @@ class TestLanguageTest < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run 'true true or'
|
||||
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run 'false false or'
|
||||
|
||||
assert_equal [{ value: false, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( false )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run 'true false or'
|
||||
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run 'false true or'
|
||||
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -156,25 +158,25 @@ class TestLanguageTest < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run 'true true xor'
|
||||
|
||||
assert_equal [{ value: false, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( false )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run 'false false xor'
|
||||
|
||||
assert_equal [{ value: false, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( false )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run 'true false xor'
|
||||
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run 'false true xor'
|
||||
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -182,13 +184,13 @@ class TestLanguageTest < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run 'true not'
|
||||
|
||||
assert_equal [{ value: false, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( false )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run 'false not'
|
||||
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -196,13 +198,13 @@ class TestLanguageTest < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '1 1 same'
|
||||
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 2 =='
|
||||
|
||||
assert_equal [{ value: false, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( false )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -210,7 +212,7 @@ class TestLanguageTest < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run 'true'
|
||||
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -218,7 +220,7 @@ class TestLanguageTest < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run 'false'
|
||||
|
||||
assert_equal [{ value: false, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( false )],
|
||||
interpreter.stack
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,12 +6,14 @@ require 'minitest/autorun'
|
|||
require 'rpl'
|
||||
|
||||
class TestLanguageTimeDate < MiniTest::Test
|
||||
include Types
|
||||
|
||||
def test_time
|
||||
now = Time.now.to_s
|
||||
interpreter = Rpl.new
|
||||
interpreter.run 'time'
|
||||
|
||||
assert_equal [{ value: now, type: :string }],
|
||||
assert_equal [RplString.new( "\"#{now}\"" )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -20,7 +22,7 @@ class TestLanguageTimeDate < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run 'date'
|
||||
|
||||
assert_equal [{ value: now, type: :string }],
|
||||
assert_equal [RplString.new( "\"#{now}\"" )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
@ -29,7 +31,7 @@ class TestLanguageTimeDate < MiniTest::Test
|
|||
interpreter.run 'ticks'
|
||||
|
||||
# TODO: better test, but how?
|
||||
assert_equal :numeric,
|
||||
interpreter.stack[0][:type]
|
||||
assert_equal RplNumeric,
|
||||
interpreter.stack[0].class
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,69 +4,71 @@
|
|||
require 'minitest/autorun'
|
||||
|
||||
require 'rpl'
|
||||
require 'rpl/types'
|
||||
|
||||
class TesttLanguageOperations < MiniTest::Test
|
||||
include Types
|
||||
|
||||
def test_pi
|
||||
interpreter = Rpl.new
|
||||
interpreter.run 'pi'
|
||||
assert_equal [{ value: BigMath.PI( interpreter.precision ), type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( BigMath.PI( RplNumeric.precision ) )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_sin
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '3 sin'
|
||||
assert_equal [{ value: BigMath.sin( BigDecimal( 3 ), interpreter.precision ), type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( BigMath.sin( BigDecimal( 3 ), RplNumeric.precision ) )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_asin
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 asin pi 2 / =='
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_cos
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '3 cos'
|
||||
assert_equal [{ value: BigMath.cos( BigDecimal( 3 ), interpreter.precision ), type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( BigMath.cos( BigDecimal( 3 ), RplNumeric.precision ) )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_acos
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '0 acos pi 2 / =='
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_tan
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '0 tan 0 =='
|
||||
assert_equal [{ value: true, type: :boolean }],
|
||||
assert_equal [RplBoolean.new( true )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_atan
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 atan'
|
||||
assert_equal [{ value: BigMath.atan( BigDecimal( 1 ), interpreter.precision ), type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( BigMath.atan( BigDecimal( 1 ), RplNumeric.precision ) )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_d2r
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '90 d→r'
|
||||
assert_equal [{ value: BigMath.PI( interpreter.precision ) / 2,
|
||||
type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( BigMath.PI( RplNumeric.precision ) / 2 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
def test_r2d
|
||||
interpreter = Rpl.new
|
||||
interpreter.run 'pi r→d'
|
||||
assert_equal [{ value: BigDecimal( 180 ), type: :numeric, base: 10 }],
|
||||
assert_equal [RplNumeric.new( 180 )],
|
||||
interpreter.stack
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,185 +0,0 @@
|
|||
# coding: utf-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'minitest/autorun'
|
||||
|
||||
require 'rpl'
|
||||
|
||||
class TestParser < MiniTest::Test
|
||||
def test_number
|
||||
result = Rpl.new.parse( '1' )
|
||||
assert_equal [{ value: 1, type: :numeric, base: 10 }], result
|
||||
|
||||
result = Rpl.new.parse( '0b101' )
|
||||
assert_equal [{ value: BigDecimal( 5 ), type: :numeric, base: 2 }], result
|
||||
|
||||
result = Rpl.new.parse( '0o57' )
|
||||
assert_equal [{ value: BigDecimal( 47 ), type: :numeric, base: 8 }], result
|
||||
|
||||
result = Rpl.new.parse( '03_10' )
|
||||
assert_equal [{ value: BigDecimal( 3 ), type: :numeric, base: 3 }], result
|
||||
end
|
||||
|
||||
def test_word
|
||||
result = Rpl.new.parse( 'dup' )
|
||||
assert_equal [{ value: 'dup', type: :word }], result
|
||||
end
|
||||
|
||||
def test_string
|
||||
result = Rpl.new.parse( '"test"' )
|
||||
assert_equal [{ value: 'test', type: :string }], result
|
||||
|
||||
result = Rpl.new.parse( '" test"' )
|
||||
assert_equal [{ value: ' test', type: :string }], result
|
||||
|
||||
result = Rpl.new.parse( '"test "' )
|
||||
assert_equal [{ value: 'test ', type: :string }], result
|
||||
|
||||
result = Rpl.new.parse( '" test "' )
|
||||
assert_equal [{ value: ' test ', type: :string }], result
|
||||
|
||||
result = Rpl.new.parse( '" « test » "' )
|
||||
assert_equal [{ value: ' « test » ', type: :string }], result
|
||||
end
|
||||
|
||||
def test_name
|
||||
result = Rpl.new.parse( "'test'" )
|
||||
assert_equal [{ value: 'test', type: :name }], result
|
||||
end
|
||||
|
||||
def test_program
|
||||
result = Rpl.new.parse( '« test »' )
|
||||
assert_equal [{ value: 'test', type: :program }], result
|
||||
|
||||
result = Rpl.new.parse( '«test »' )
|
||||
assert_equal [{ value: 'test', type: :program }], result
|
||||
|
||||
result = Rpl.new.parse( '« test»' )
|
||||
assert_equal [{ value: 'test', type: :program }], result
|
||||
|
||||
result = Rpl.new.parse( '«test»' )
|
||||
assert_equal [{ value: 'test', type: :program }], result
|
||||
|
||||
result = Rpl.new.parse( '« test test »' )
|
||||
assert_equal [{ value: 'test test', type: :program }], result
|
||||
|
||||
result = Rpl.new.parse( '« test « test » »' )
|
||||
assert_equal [{ value: 'test « test »', type: :program }], result
|
||||
|
||||
result = Rpl.new.parse( '« test "test" test »' )
|
||||
assert_equal [{ value: 'test "test" test', type: :program }], result
|
||||
end
|
||||
|
||||
def test_list
|
||||
result = Rpl.new.parse( '{ test }' )
|
||||
assert_equal [{ value: [{ value: 'test', type: :word }], type: :list }], result
|
||||
|
||||
result = Rpl.new.parse( '{test }' )
|
||||
assert_equal [{ value: [{ value: 'test', type: :word }], type: :list }], result
|
||||
|
||||
result = Rpl.new.parse( '{ test}' )
|
||||
assert_equal [{ value: [{ value: 'test', type: :word }], type: :list }], result
|
||||
|
||||
result = Rpl.new.parse( '{test}' )
|
||||
assert_equal [{ value: [{ value: 'test', type: :word }], type: :list }], result
|
||||
|
||||
result = Rpl.new.parse( '{ test test }' )
|
||||
assert_equal [{ value: [{ value: 'test', type: :word },
|
||||
{ value: 'test', type: :word }], type: :list }], result
|
||||
|
||||
result = Rpl.new.parse( '{ test { test } }' )
|
||||
assert_equal [{ value: [{ value: 'test', type: :word },
|
||||
{ value: [{ value: 'test', type: :word }], type: :list }], type: :list }], result
|
||||
|
||||
result = Rpl.new.parse( '{ test "test" test }' )
|
||||
assert_equal [{ value: [{ value: 'test', type: :word },
|
||||
{ value: 'test', type: :string },
|
||||
{ value: 'test', type: :word }], type: :list }], result
|
||||
end
|
||||
|
||||
def test_number_number
|
||||
result = Rpl.new.parse( '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.new.parse( '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.new.parse( '4 "test"' )
|
||||
assert_equal [{ value: 4, type: :numeric, base: 10 }, { value: 'test', type: :string }], result
|
||||
end
|
||||
|
||||
def test_emptystring
|
||||
result = Rpl.new.parse( '""' )
|
||||
|
||||
assert_equal [{ value: '', type: :string }], result
|
||||
end
|
||||
|
||||
def test_spacestring
|
||||
result = Rpl.new.parse( '" "' )
|
||||
|
||||
assert_equal [{ value: ' ', type: :string }], result
|
||||
end
|
||||
|
||||
def test_string_spacestring
|
||||
result = Rpl.new.parse( '"test string" " "' )
|
||||
|
||||
assert_equal [{ value: 'test string', type: :string },
|
||||
{ value: ' ', type: :string }], result
|
||||
end
|
||||
|
||||
def test_string_word
|
||||
result = Rpl.new.parse( '"test string" split' )
|
||||
|
||||
assert_equal [{ value: 'test string', type: :string },
|
||||
{ value: 'split', type: :word }], result
|
||||
end
|
||||
|
||||
def test_spacestring_word
|
||||
result = Rpl.new.parse( '" " split' )
|
||||
|
||||
assert_equal [{ value: ' ', type: :string },
|
||||
{ value: 'split', type: :word }], result
|
||||
end
|
||||
|
||||
def test_program_name
|
||||
result = Rpl.new.parse( "« 2 dup * » 'carré' sto" )
|
||||
|
||||
assert_equal [{ value: '2 dup *', type: :program },
|
||||
{ value: 'carré', type: :name },
|
||||
{ value: 'sto', type: :word }],
|
||||
result
|
||||
end
|
||||
|
||||
def test_with_multiline
|
||||
result = Rpl.new.parse( "« 2
|
||||
|
||||
dup * »
|
||||
|
||||
'carré' sto" )
|
||||
|
||||
assert_equal [{ value: '2 dup *', type: :program },
|
||||
{ value: 'carré', type: :name },
|
||||
{ value: 'sto', type: :word }],
|
||||
result
|
||||
end
|
||||
|
||||
def test_with_comments
|
||||
result = Rpl.new.parse( "« 2 #deux
|
||||
# on duplique le deux
|
||||
dup * »
|
||||
|
||||
# on va STOcker ce programme dans la variable 'carré'
|
||||
'carré' sto" )
|
||||
|
||||
assert_equal [{ value: '2 dup *', type: :program },
|
||||
{ value: 'carré', type: :name },
|
||||
{ value: 'sto', type: :word }],
|
||||
result
|
||||
end
|
||||
end
|
|
@ -38,9 +38,12 @@ class TestTypes < MiniTest::Test
|
|||
assert_equal true, RplName.can_parse?( "'test test'" ) # let's just allow spaces in names
|
||||
assert_equal true, RplName.can_parse?( 'test' )
|
||||
assert_equal true, RplName.can_parse?( 'test test' ) # let's just allow spaces in names
|
||||
assert_equal false, RplName.can_parse?( "'test" )
|
||||
assert_equal false, RplName.can_parse?( "test'" )
|
||||
assert_equal true, RplName.can_parse?( "'test" )
|
||||
assert_equal true, RplName.can_parse?( "test'" )
|
||||
assert_equal false, RplName.can_parse?( "''" )
|
||||
assert_equal false, RplName.can_parse?( "'1" )
|
||||
assert_equal false, RplName.can_parse?( "1'" )
|
||||
assert_equal false, RplName.can_parse?( '1' )
|
||||
|
||||
assert_equal RplName, RplName.new( "'test'" ).class
|
||||
assert_equal RplName, RplName.new( "'test test'" ).class
|
||||
|
|
Loading…
Reference in a new issue