Compare commits

..

3 commits

Author SHA1 Message Date
Gwenhael Le Moine
42f02e8e94
fix stack_extract test 2021-11-24 13:52:32 +01:00
Gwenhael Le Moine
8e7c50fc66
Merge branch 'trunk' of ssh://src.le-moine.org:38172/gwh/rpn.rb into trunk 2021-11-24 13:48:22 +01:00
Gwenhael Le Moine
3809c4b58b
reverse extracted stack order to match needs, +String 2021-11-24 13:33:44 +01:00
7 changed files with 77 additions and 20 deletions

View file

@ -5,6 +5,7 @@ require_relative './language/mode'
require_relative './language/operations'
require_relative './language/program'
require_relative './language/stack'
require_relative './language/string'
require_relative './language/time-date'
module Rpl
@ -33,7 +34,7 @@ module Rpl
args << elt
end
[stack, args.reverse]
[stack, args]
end
def __todo( stack )

View file

@ -94,13 +94,13 @@ module Rpl
add( 'same', proc { |stack| Rpl::Core.__todo( stack ) } ) # boolean operator same (equal)
# STRING
add( '->str', proc { |stack| Rpl::Core.__todo( stack ) } ) # convert an object into a string
add( '->str', proc { |stack| Rpl::Core.to_string( stack ) } )
add( 'str->', proc { |stack| Rpl::Core.__todo( stack ) } ) # convert a string into an object
add( 'chr', proc { |stack| Rpl::Core.__todo( stack ) } ) # convert ASCII character code in stack level 1 into a string
add( 'num', proc { |stack| Rpl::Core.__todo( stack ) } ) # return ASCII code of the first character of the string in stack level 1 as a real number
add( 'size', proc { |stack| Rpl::Core.__todo( stack ) } ) # return the length of the string
add( 'size', proc { |stack| Rpl::Core.size( stack ) } )
add( 'pos', proc { |stack| Rpl::Core.__todo( stack ) } ) # seach for the string in level 1 within the string in level 2
add( 'sub', proc { |stack| Rpl::Core.__todo( stack ) } ) # return a substring of the string in level 3
add( 'sub', proc { |stack| Rpl::Core.sub( stack ) } )
# BRANCH
add( 'if', proc { |stack| Rpl::Core.__todo( stack ) } ) # if <test-instruction> then <true-instructions> else <false-instructions> end

View file

@ -7,13 +7,13 @@ module Rpl
addable = %i[numeric string name]
stack, args = Rpl::Core.stack_extract( stack, [addable, addable] )
result = { type: case args[0][:type]
result = { type: case args[1][:type]
when :name
:name
when :string
:string
when :numeric
if args[1][:type] == :numeric
if args[0][:type] == :numeric
:numeric
else
:string
@ -26,11 +26,11 @@ module Rpl
result[:value] = case result[:type]
when :name
"'#{args[0][:value]}#{args[1][:value]}'"
"'#{args[1][:value]}#{args[0][:value]}'"
when :string
"\"#{args[0][:value]}#{args[1][:value]}\""
"\"#{args[1][:value]}#{args[0][:value]}\""
when :numeric
args[0][:value] + args[1][:value]
args[1][:value] + args[0][:value]
end
result[:base] = 10 if result[:type] == :numeric # TODO: what if operands have other bases ?
@ -43,7 +43,7 @@ module Rpl
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
stack << { type: :numeric, base: 10,
value: args[0][:value] - args[1][:value] }
value: args[1][:value] - args[0][:value] }
end
# negation
@ -59,7 +59,7 @@ module Rpl
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
stack << { type: :numeric, base: 10,
value: args[0][:value] * args[1][:value] }
value: args[1][:value] * args[0][:value] }
end
# division
@ -69,7 +69,7 @@ module Rpl
raise 'Division by 0' if args[0][:value].zero?
stack << { type: :numeric, base: 10,
value: args[0][:value] / args[1][:value] }
value: args[1][:value] / args[0][:value] }
end
# inverse
@ -87,7 +87,7 @@ module Rpl
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
stack << { type: :numeric, base: 10,
value: args[0][:value]**args[1][:value] }
value: args[1][:value]**args[0][:value] }
end
# rpn_square root
@ -133,9 +133,9 @@ module Rpl
def base( stack )
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric]] )
args[0][:base] = args[1][:value]
args[1][:base] = args[0][:value]
stack << args[0]
stack << args[1]
end
# 1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0

View file

@ -6,7 +6,7 @@ module Rpl
def swap( stack )
stack, args = Rpl::Core.stack_extract( stack, %i[any any] )
stack << args[1] << args[0]
stack << args[0] << args[1]
end
# drop first stack entry
@ -36,7 +36,7 @@ module Rpl
def rot( stack )
stack, args = Rpl::Core.stack_extract( stack, %i[any any any] )
stack << args[1] << args[2] << args[0]
stack << args[1] << args[0] << args[2]
end
# duplicate first stack entry
@ -55,6 +55,8 @@ module Rpl
n = args[0][:value]
stack, args = Rpl::Core.stack_extract( stack, %i[any] * args[0][:value] )
args.reverse!
2.times do
n.times.each do |i|
stack << args[ i ]
@ -70,6 +72,8 @@ module Rpl
n = args[0][:value]
stack, args = Rpl::Core.stack_extract( stack, %i[any] * args[0][:value] )
args.reverse!
n.times.each do |i|
stack << args[ i ]
end
@ -89,6 +93,8 @@ module Rpl
n = args[0][:value]
stack, args = Rpl::Core.stack_extract( stack, %i[any] * args[0][:value] )
args.reverse!
(1..(n - 1)).each do |i|
stack << args[ i ]
end
@ -103,6 +109,8 @@ module Rpl
n = args[0][:value]
stack, args = Rpl::Core.stack_extract( stack, %i[any] * args[0][:value] )
args.reverse!
stack << args[n - 1]
(0..(n - 2)).each do |i|

31
lib/language/string.rb Normal file
View file

@ -0,0 +1,31 @@
module Rpl
module Core
module_function
# convert an object into a string
def to_string( stack )
stack, args = Rpl::Core.stack_extract( stack, :any )
stack << { type: :string,
value: args[0][:value].to_s }
end
# return the length of the string
def size( stack )
stack, args = Rpl::Core.stack_extract( stack, %i[string] )
stack << { type: :numeric,
base: 10,
value: args[0][:value].length }
end
# return a substring of the string in level 3
def sub( stack )
stack, args = Rpl::Core.stack_extract( stack, [%i[numeric], %i[numeric], %i[string]] )
puts "#{args[0][:value]}[#{args[1][:value]}..#{args[2][:value]}]"
stack << { type: :string,
value: args[2][:value][args[1][:value]..args[0][:value]] }
end
end
end

View file

@ -15,13 +15,13 @@ class TestParser < Test::Unit::TestCase
assert_equal [{ value: 2, type: :numeric }],
args
stack, args = Rpl::Core.stack_extract [{ value: 1, type: :numeric },
stack, args = Rpl::Core.stack_extract [{ value: "test", type: :string },
{ value: 2, type: :numeric }],
[:any, [:numeric]]
assert_equal [],
stack
assert_equal [{ value: 1, type: :numeric },
{ value: 2, type: :numeric }],
assert_equal [{ value: 2, type: :numeric },
{ value: "test", type: :string }],
args
end
end

View file

@ -0,0 +1,17 @@
# coding: utf-8
# frozen_string_literal: true
require 'test/unit'
require_relative '../lib/core'
class TestLanguageString < Test::Unit::TestCase
def test_sub
stack = Rpl::Core.sub( [{ value: 'test', type: :string },
{ value: 1, type: :numeric, base: 10 },
{ value: 2, type: :numeric, base: 10 }] )
assert_equal [{ value: 'es', type: :string }],
stack
end
end