From b7d748ac5da525064fbb950e3bc63d3b3221d7cd Mon Sep 17 00:00:00 2001 From: Gwenhael Le Moine Date: Wed, 24 Nov 2021 16:34:13 +0100 Subject: [PATCH] implement IFTE and IFT --- lib/core.rb | 1 + lib/dictionary.rb | 8 ++++---- lib/language/branch.rb | 19 +++++++++++++++++++ spec/language_branch_spec.rb | 29 +++++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 lib/language/branch.rb create mode 100644 spec/language_branch_spec.rb diff --git a/lib/core.rb b/lib/core.rb index 910afe2..bed21b5 100644 --- a/lib/core.rb +++ b/lib/core.rb @@ -1,5 +1,6 @@ require 'bigdecimal/math' +require_relative './language/branch' require_relative './language/general' require_relative './language/mode' require_relative './language/operations' diff --git a/lib/dictionary.rb b/lib/dictionary.rb index 0e09a66..01fae40 100644 --- a/lib/dictionary.rb +++ b/lib/dictionary.rb @@ -101,8 +101,8 @@ module Rpl add( 'xor', proc { |stack| Rpl::Core.xor( stack ) } ) add( 'not', proc { |stack| Rpl::Core.not( stack ) } ) add( 'same', proc { |stack| Rpl::Core.same( stack ) } ) - add( 'true', proc { |stack| Rpl::Core.true( stack ) } ) - add( 'false', proc { |stack| Rpl::Core.false( stack ) } ) + add( 'true', proc { |stack| Rpl::Core.true( stack ) } ) # specific + add( 'false', proc { |stack| Rpl::Core.false( stack ) } ) # specific # STRING add( '->str', proc { |stack| Rpl::Core.to_string( stack ) } ) @@ -124,8 +124,8 @@ module Rpl add( 'for', proc { |stack| Rpl::Core.__todo( stack ) } ) # for next| step add( 'next', proc { |stack| Rpl::Core.__todo( stack ) } ) # used with start and for add( 'step', proc { |stack| Rpl::Core.__todo( stack ) } ) # used with start and for - add( 'ift', proc { |stack| Rpl::Core.__todo( stack ) } ) # similar to if-then-end, ift - add( 'ifte', proc { |stack| Rpl::Core.__todo( stack ) } ) # similar to if-then-else-end, ifte + add( 'ift', proc { |stack| Rpl::Core.ift( stack, self ) } ) + add( 'ifte', proc { |stack| Rpl::Core.ifte( stack, self ) } ) add( 'do', proc { |stack| Rpl::Core.__todo( stack ) } ) # do until end add( 'until', proc { |stack| Rpl::Core.__todo( stack ) } ) # used with do add( 'while', proc { |stack| Rpl::Core.__todo( stack ) } ) # while repeat end diff --git a/lib/language/branch.rb b/lib/language/branch.rb new file mode 100644 index 0000000..1278eb4 --- /dev/null +++ b/lib/language/branch.rb @@ -0,0 +1,19 @@ +module Rpl + module Core + module_function + + # similar to if-then-end, ift + def ift( stack, dictionary ) + ifte( stack << { type: :word, value: 'nop' }, dictionary ) + end + + # similar to if-then-else-end, ifte + def ifte( stack, dictionary ) + stack, args = Rpl::Core.stack_extract( stack, [%i[program word], %i[program word], %i[boolean]] ) + + stack << args[ args[2][:value] ? 1 : 0 ] + + Rpl::Core.eval( stack, dictionary ) + end + end +end diff --git a/spec/language_branch_spec.rb b/spec/language_branch_spec.rb new file mode 100644 index 0000000..ae2e9fa --- /dev/null +++ b/spec/language_branch_spec.rb @@ -0,0 +1,29 @@ +# coding: utf-8 +# frozen_string_literal: true + +require 'test/unit' + +require_relative '../lib/core' +require_relative '../lib/dictionary' +require_relative '../lib/parser' +require_relative '../lib/runner' + +class TestLanguageBranch < Test::Unit::TestCase + def test_ifte + stack = Rpl::Core.ifte( [{ type: :boolean, value: true }, + { type: :program, value: '« 2 3 + »' }, + { type: :program, value: '« 2 3 - »' }], + Rpl::Dictionary.new ) + + assert_equal [{ value: 5, type: :numeric, base: 10 }], + stack + + stack = Rpl::Core.ifte( [{ type: :boolean, value: false }, + { type: :program, value: '« 2 3 + »' }, + { type: :program, value: '« 2 3 - »' }], + Rpl::Dictionary.new ) + + assert_equal [{ value: -1, type: :numeric, base: 10 }], + stack + end +end