diff --git a/lib/core.rb b/lib/core.rb index 86c9f7f..e50a916 100644 --- a/lib/core.rb +++ b/lib/core.rb @@ -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 ) diff --git a/lib/dictionary.rb b/lib/dictionary.rb index c24cefe..569a25b 100644 --- a/lib/dictionary.rb +++ b/lib/dictionary.rb @@ -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 then else end diff --git a/lib/language/operations.rb b/lib/language/operations.rb index bb1f8c1..b67ef72 100644 --- a/lib/language/operations.rb +++ b/lib/language/operations.rb @@ -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 diff --git a/lib/language/stack.rb b/lib/language/stack.rb index 084e20d..e912c39 100644 --- a/lib/language/stack.rb +++ b/lib/language/stack.rb @@ -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| diff --git a/lib/language/string.rb b/lib/language/string.rb new file mode 100644 index 0000000..e5549ac --- /dev/null +++ b/lib/language/string.rb @@ -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 diff --git a/spec/language_string_spec.rb b/spec/language_string_spec.rb new file mode 100644 index 0000000..bb04988 --- /dev/null +++ b/spec/language_string_spec.rb @@ -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