[bug] fix variable overwriting bug
This commit is contained in:
parent
703c659f83
commit
db0d8cb5a9
6 changed files with 200 additions and 105 deletions
|
@ -7,7 +7,6 @@ To run REPL locally: `rake run`
|
|||
To run the test suite: `rake test`
|
||||
|
||||
# BUGs
|
||||
* var1 var2 +|-|*|\ ===> result in on stack (normal) AND stored in var1 (_bug_)
|
||||
|
||||
# TODO-list
|
||||
* pseudo filesystem: subdir/namespace for variables
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RplTypeError < StandardError
|
||||
attr_reader :reason
|
||||
|
||||
def initialize( reason = "-undefined-" )
|
||||
@reason = reason
|
||||
end
|
||||
end
|
||||
|
||||
class Parser
|
||||
include Types
|
||||
|
||||
|
@ -68,7 +76,7 @@ class Parser
|
|||
end
|
||||
|
||||
# 2. parse
|
||||
regrouped_input.map do |element|
|
||||
parsed_input = regrouped_input.map do |element|
|
||||
if RplBoolean.can_parse?( element )
|
||||
Types.new_object( RplBoolean, element )
|
||||
elsif RplNumeric.can_parse?( element )
|
||||
|
@ -83,5 +91,7 @@ class Parser
|
|||
Types.new_object( RplName, element )
|
||||
end
|
||||
end
|
||||
|
||||
parsed_input
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rpl/parser'
|
||||
|
||||
module Types
|
||||
class RplString
|
||||
attr_accessor :value
|
||||
|
|
|
@ -25,56 +25,50 @@ module RplLang
|
|||
args.reverse!
|
||||
|
||||
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]
|
||||
new_list = if args[1].instance_of?( RplList )
|
||||
RplList.new( args[0].to_s ).value.concat( args[1].value )
|
||||
else
|
||||
RplList.new( args[0].to_s ).value.concat( [ args[1] ] )
|
||||
end
|
||||
|
||||
RplList.new( "{ #{new_list.join(' ')} }" )
|
||||
|
||||
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
|
||||
new_list = if args[0].instance_of?( RplList )
|
||||
RplList.new( args[0].to_s ).value.concat( args[1].value )
|
||||
else
|
||||
RplList.new( "{ #{args[0]} }" ).value.concat( args[1].value )
|
||||
end
|
||||
|
||||
RplList.new( "{ #{new_list.join(' ')} }" )
|
||||
|
||||
elsif args[0].instance_of?( RplString )
|
||||
args[0].value = if args[1].instance_of?( RplString ) ||
|
||||
RplString.new( 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]
|
||||
"\"#{args[0].value}#{args[1].value}\""
|
||||
else
|
||||
"\"#{args[0].value}#{args[1]}\""
|
||||
end )
|
||||
|
||||
elsif args[0].instance_of?( RplName )
|
||||
|
||||
if args[1].instance_of?( RplName )
|
||||
args[0].value = "#{args[0].value}#{args[1].value}"
|
||||
args[0]
|
||||
RplName.new( "'#{args[0].value}#{args[1].value}'" )
|
||||
elsif args[1].instance_of?( RplString )
|
||||
Types.new_object( RplString, "\"#{args[0].value}#{args[1].value}\"" )
|
||||
elsif args[1].instance_of?( RplNumeric )
|
||||
RplName.new( "'#{args[0].value}#{args[1]}'" )
|
||||
else
|
||||
if args[1].instance_of?( RplString )
|
||||
Types.new_object( RplString, "\"#{args[0].value}#{args[1].value}\"" )
|
||||
elsif args[1].instance_of?( RplNumeric )
|
||||
args[0].value = "#{args[0].value}#{args[1]}"
|
||||
args[0]
|
||||
else
|
||||
Types.new_object( RplString, "\"#{args[0]}#{args[1]}\"" )
|
||||
end
|
||||
Types.new_object( RplString, "\"#{args[0]}#{args[1]}\"" )
|
||||
end
|
||||
|
||||
elsif args[0].instance_of?( RplNumeric )
|
||||
if args[1].instance_of?( RplNumeric )
|
||||
args[0].value += args[1].value
|
||||
args[0]
|
||||
|
||||
elsif args[1].instance_of?( RplString ) ||
|
||||
args[1].instance_of?( RplName )
|
||||
args[1].value = "#{args[0]}#{args[1].value}"
|
||||
args[1]
|
||||
RplNumeric.new( args[0].value + args[1].value, args[0].base )
|
||||
elsif args[1].instance_of?( RplString )
|
||||
RplString.new( "\"#{args[0]}#{args[1].value}\"" )
|
||||
elsif args[1].instance_of?( RplName )
|
||||
RplName.new( "'#{args[0]}#{args[1].value}'" )
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -87,9 +81,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
args[1].value = args[1].value - args[0].value
|
||||
|
||||
@stack << args[1]
|
||||
@stack << RplNumeric.new( args[1].value - args[0].value, args[1].base )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['chs'],
|
||||
|
@ -105,9 +97,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
args[1].value = args[1].value * args[0].value
|
||||
|
||||
@stack << args[1]
|
||||
@stack << RplNumeric.new( args[1].value * args[0].value, args[1].base )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['÷', '/'],
|
||||
|
@ -116,9 +106,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
args[1].value = args[1].value / args[0].value
|
||||
|
||||
@stack << args[1]
|
||||
@stack << RplNumeric.new( args[1].value / args[0].value, args[1].base )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['inv'],
|
||||
|
@ -134,9 +122,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
args[1].value = args[1].value**args[0].value
|
||||
|
||||
@stack << args[1]
|
||||
@stack << RplNumeric.new( args[1].value**args[0].value, args[1].base )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['√', 'sqrt'],
|
||||
|
@ -145,9 +131,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
args[0].value = BigMath.sqrt( args[0].value, RplNumeric.precision )
|
||||
|
||||
@stack << args[0]
|
||||
@stack << RplNumeric.new( BigMath.sqrt( args[0].value, RplNumeric.precision ), args[0].base )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['²', 'sq'],
|
||||
|
@ -163,9 +147,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
args[0].value = args[0].value.abs
|
||||
|
||||
@stack << args[0]
|
||||
@stack << RplNumeric.new( args[0].value.abs, args[0].base )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['dec'],
|
||||
|
@ -195,9 +177,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
args[1].base = args[0].value
|
||||
|
||||
@stack << args[1]
|
||||
@stack << RplNumeric.new( args[1].value, args[0].value )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['sign'],
|
||||
|
@ -205,15 +185,14 @@ module RplLang
|
|||
'( a -- b ) sign of element',
|
||||
proc do
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
args[0].value = if args[0].value.positive?
|
||||
1
|
||||
elsif args[0].value.negative?
|
||||
-1
|
||||
else
|
||||
0
|
||||
end
|
||||
|
||||
@stack << args[0]
|
||||
@stack << RplNumeric.new( if args[0].value.positive?
|
||||
1
|
||||
elsif args[0].value.negative?
|
||||
-1
|
||||
else
|
||||
0
|
||||
end )
|
||||
end )
|
||||
|
||||
# Operations on reals
|
||||
|
@ -223,9 +202,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
args[1].value = args[0].value * ( args[1].value / 100.0 )
|
||||
|
||||
@stack << args[1]
|
||||
@stack << RplNumeric.new( args[0].value * ( args[1].value / 100.0 ), args[1].base )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['%CH'],
|
||||
|
@ -234,9 +211,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
args[1].value = 100.0 * ( args[0].value / args[1].value )
|
||||
|
||||
@stack << args[1]
|
||||
@stack << RplNumeric.new( 100.0 * ( args[0].value / args[1].value ), args[1].base )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['mod'],
|
||||
|
@ -245,9 +220,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
args[1].value = args[1].value % args[0].value
|
||||
|
||||
@stack << args[1]
|
||||
@stack << RplNumeric.new( args[1].value % args[0].value, args[1].base )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['!', 'fact'],
|
||||
|
@ -256,9 +229,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
args[0].value = Math.gamma( args[0].value )
|
||||
|
||||
@stack << args[0]
|
||||
@stack << RplNumeric.new( Math.gamma( args[0].value ), args[0].base )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['floor'],
|
||||
|
@ -267,9 +238,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
args[0].value = args[0].value.floor
|
||||
|
||||
@stack << args[0]
|
||||
@stack << RplNumeric.new( args[0].value.floor, args[0].base )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['ceil'],
|
||||
|
@ -278,9 +247,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
args[0].value = args[0].value.ceil
|
||||
|
||||
@stack << args[0]
|
||||
@stack << RplNumeric.new( args[0].value.ceil, args[0].base )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['min'],
|
||||
|
@ -316,9 +283,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
args[0].value = args[0].value.exponent
|
||||
|
||||
@stack << args[0]
|
||||
@stack << RplNumeric.new( args[0].value.exponent, args[0].base )
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['ip'],
|
||||
|
@ -334,9 +299,7 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [[RplNumeric]] )
|
||||
|
||||
args[0].value = args[0].value.frac
|
||||
|
||||
@stack << args[0]
|
||||
@stack << RplNumeric.new( args[0].value.frac, args[0].base )
|
||||
end )
|
||||
|
||||
# Operations on complexes
|
||||
|
|
|
@ -98,9 +98,11 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [[RplString, RplList]] )
|
||||
|
||||
args[0].value.reverse!
|
||||
|
||||
@stack << args[0]
|
||||
if args[0].is_a?( RplString )
|
||||
@stack << args[0].class.new( "\"#{args[0].value.reverse}\"" )
|
||||
else
|
||||
@stack << args[0].class.new( "{ #{args[0].value.reverse.join(' ')} }" )
|
||||
end
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['split'],
|
||||
|
|
|
@ -27,7 +27,7 @@ class TesttLanguageOperations < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '1 dup dup →list +'
|
||||
assert_equal [Types.new_object( RplList, [Types.new_object( RplNumeric, 1 ),
|
||||
Types.new_object( RplNumeric, 1 )] )],
|
||||
Types.new_object( RplNumeric, 1 )] )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
|
@ -48,7 +48,7 @@ class TesttLanguageOperations < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '"a" 1 dup →list +'
|
||||
assert_equal [Types.new_object( RplList, [Types.new_object( RplString, '"a"' ),
|
||||
Types.new_object( RplNumeric, 1 )] )],
|
||||
Types.new_object( RplNumeric, 1 )] )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
|
@ -69,25 +69,144 @@ class TesttLanguageOperations < MiniTest::Test
|
|||
interpreter = Rpl.new
|
||||
interpreter.run '\'a\' 1 dup →list +'
|
||||
assert_equal [Types.new_object( RplList, [Types.new_object( RplName, 'a' ),
|
||||
Types.new_object( RplNumeric, 1 )] )],
|
||||
Types.new_object( RplNumeric, 1 )] )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 a "test" 3 →list dup rev +'
|
||||
assert_equal [Types.new_object( RplList, [Types.new_object( RplNumeric, 1 ),
|
||||
Types.new_object( RplName, 'a' ),
|
||||
Types.new_object( RplString, '"test"' ),
|
||||
Types.new_object( RplString, '"test"' ),
|
||||
Types.new_object( RplName, 'a' ),
|
||||
Types.new_object( RplNumeric, 1 )] )],
|
||||
Types.new_object( RplName, 'a' ),
|
||||
Types.new_object( RplString, '"test"' ),
|
||||
Types.new_object( RplString, '"test"' ),
|
||||
Types.new_object( RplName, 'a' ),
|
||||
Types.new_object( RplNumeric, 1 )] )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 a "test" 3 →list 9 +'
|
||||
assert_equal [Types.new_object( RplList, [Types.new_object( RplNumeric, 1 ),
|
||||
Types.new_object( RplName, 'a' ),
|
||||
Types.new_object( RplString, '"test"' ),
|
||||
Types.new_object( RplNumeric, 9 )] )],
|
||||
Types.new_object( RplName, 'a' ),
|
||||
Types.new_object( RplString, '"test"' ),
|
||||
Types.new_object( RplNumeric, 9 )] )],
|
||||
interpreter.stack
|
||||
|
||||
#################
|
||||
# now with vars #
|
||||
#################
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 \'a\' sto 2 \'b\' sto a b + a b'
|
||||
assert_equal [Types.new_object( RplNumeric, 3 ),
|
||||
Types.new_object( RplNumeric, 1 ),
|
||||
Types.new_object( RplNumeric, 2 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 \'a\' sto "a" \'b\' sto a b + a b'
|
||||
assert_equal [Types.new_object( RplString, '"1a"' ),
|
||||
Types.new_object( RplNumeric, 1 ),
|
||||
Types.new_object( RplString, '"a"' )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 \'a\' sto \'z\' \'b\' sto a b + a b'
|
||||
assert_equal [Types.new_object( RplName, "'1z'" ),
|
||||
Types.new_object( RplNumeric, 1 ),
|
||||
Types.new_object( RplName, "'z'" )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 \'a\' sto a dup →list \'b\' sto a b + a b'
|
||||
assert_equal [Types.new_object( RplList, [Types.new_object( RplNumeric, 1 ),
|
||||
Types.new_object( RplNumeric, 1 )] ),
|
||||
Types.new_object( RplNumeric, 1 ),
|
||||
Types.new_object( RplList, [Types.new_object( RplNumeric, 1 )] )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '"a" \'a\' sto "b" \'b\' sto a b + a b'
|
||||
assert_equal [Types.new_object( RplString, '"ab"' ),
|
||||
Types.new_object( RplString, '"a"' ),
|
||||
Types.new_object( RplString, '"b"' )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '"a" \'a\' sto \'z\' \'b\' sto a b + a b'
|
||||
assert_equal [Types.new_object( RplString, '"az"' ),
|
||||
Types.new_object( RplString, '"a"' ),
|
||||
Types.new_object( RplName, "'z'" )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '"a" \'a\' sto 1 \'b\' sto a b + a b'
|
||||
assert_equal [Types.new_object( RplString, '"a1"' ),
|
||||
Types.new_object( RplString, '"a"' ),
|
||||
Types.new_object( RplNumeric, 1 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '"a" \'a\' sto 1 dup →list \'b\' sto a b + a b'
|
||||
assert_equal [Types.new_object( RplList, [Types.new_object( RplString, '"a"' ),
|
||||
Types.new_object( RplNumeric, 1 )] ),
|
||||
Types.new_object( RplString, '"a"' ),
|
||||
Types.new_object( RplList, [Types.new_object( RplNumeric, 1 )] )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '\'z\' \'a\' sto 1 \'b\' sto a b + a b'
|
||||
assert_equal [Types.new_object( RplName, 'z1' ),
|
||||
Types.new_object( RplName, 'z' ),
|
||||
Types.new_object( RplNumeric, 1 )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '\'z\' \'a\' sto "b" \'b\' sto a b + a b'
|
||||
assert_equal [Types.new_object( RplString, '"zb"' ),
|
||||
Types.new_object( RplName, "'z'" ),
|
||||
Types.new_object( RplString, '"b"' )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '\'z\' \'a\' sto \'y\' \'b\' sto a b + a b'
|
||||
assert_equal [Types.new_object( RplName, "'zy'" ),
|
||||
Types.new_object( RplName, "'z'" ),
|
||||
Types.new_object( RplName, "'y'" )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '\'z\' \'a\' sto 1 dup →list \'b\' sto a b + a b'
|
||||
assert_equal [Types.new_object( RplList, [Types.new_object( RplName, "'z'" ),
|
||||
Types.new_object( RplNumeric, 1 )] ),
|
||||
Types.new_object( RplName, "'z'" ),
|
||||
Types.new_object( RplList, [Types.new_object( RplNumeric, 1 )] )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 z "test" 3 →list \'a\' sto a rev \'b\' sto a b + a b'
|
||||
assert_equal [Types.new_object( RplList, [Types.new_object( RplNumeric, 1 ),
|
||||
Types.new_object( RplName, 'z' ),
|
||||
Types.new_object( RplString, '"test"' ),
|
||||
Types.new_object( RplString, '"test"' ),
|
||||
Types.new_object( RplName, 'z' ),
|
||||
Types.new_object( RplNumeric, 1 )] ),
|
||||
Types.new_object( RplList, [Types.new_object( RplNumeric, 1 ),
|
||||
Types.new_object( RplName, 'z' ),
|
||||
Types.new_object( RplString, '"test"' )] ),
|
||||
Types.new_object( RplList, [Types.new_object( RplString, '"test"' ),
|
||||
Types.new_object( RplName, 'z' ),
|
||||
Types.new_object( RplNumeric, 1 )] )],
|
||||
interpreter.stack
|
||||
|
||||
interpreter = Rpl.new
|
||||
interpreter.run '1 a "test" 3 →list \'a\' sto 9 \'b\' sto a b + a b'
|
||||
assert_equal [Types.new_object( RplList, [Types.new_object( RplNumeric, 1 ),
|
||||
Types.new_object( RplName, 'a' ),
|
||||
Types.new_object( RplString, '"test"' ),
|
||||
Types.new_object( RplNumeric, 9 )] ),
|
||||
Types.new_object( RplList, [Types.new_object( RplNumeric, 1 ),
|
||||
Types.new_object( RplName, 'a' ),
|
||||
Types.new_object( RplString, '"test"' )] ),
|
||||
Types.new_object( RplNumeric, 9 )],
|
||||
interpreter.stack
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue