[bug] fix variable overwriting bug

This commit is contained in:
Gwenhael Le Moine 2022-08-30 14:34:15 +02:00
parent 703c659f83
commit db0d8cb5a9
No known key found for this signature in database
GPG key ID: FDFE3669426707A7
6 changed files with 200 additions and 105 deletions

View file

@ -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

View file

@ -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

View file

@ -1,5 +1,7 @@
# frozen_string_literal: true
require 'rpl/parser'
module Types
class RplString
attr_accessor :value

View file

@ -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

View file

@ -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'],

View file

@ -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