From 39ffbcddbe95567fed727cc4fb96d1dc3614e769 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Wed, 31 May 2017 18:14:02 +0200 Subject: [PATCH] #106: added string keywords: +, chr, num --- README.md | 46 ++++++++++++++++++++++++---------------------- src/object.hpp | 2 +- src/program.cpp | 2 ++ src/rpn-real.hpp | 33 ++++++++++++++++++++++++++++----- src/rpn-string.hpp | 28 ++++++++++++++++++++++++++++ test/07-string.txt | 36 ++++++++++++++++++++++++++++++++++++ 6 files changed, 119 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index df2c676..a90ce5a 100644 --- a/README.md +++ b/README.md @@ -59,41 +59,41 @@ rpn> |keyword|description| |-|-| -|nop | no operation | -|help | (or h or ?) this help message -|quit | (or q or exit) quit software +|nop | no operation | +|help | (or h or ?) this help message +|quit | (or q or exit) quit software |version | show rpn version |uname | show rpn complete identification string -|type | show type of stack first entry +|type | show type of stack first entry |default | set float representation and precision to default #### real |keyword|description| |-|-| -|+| addition -|-| substraction +|+| addition +|-| substraction |neg| negation -|*| multiplication -|/| division +|*| multiplication +|/| division |inv| inverse -|%| purcent +|%| purcent |%|CH inverse purcent -|^| (or pow) power +|^| (or pow) power |sqrt| square root |sq| (or sqr) square |mod| modulo |abs| absolute value |dec| decimal representation |hex| hexadecimal representation -|prec | get float precision in bits when first stack is not a number, set float precision in bits when first stack entry is a number. ex: ```256 prec``` +|prec| get float precision in bits when first stack is not a number, set float precision in bits when first stack entry is a number. ex: ```256 prec``` |round| set float rounding mode. Authoerized values are: ```["nearest", "toward zero", "toward +inf", "toward -inf", "away from zero"] round```. ex: ```"nearest" round``` -|fact| n! for integer n or Gamma(x+1) for fractional x -|sign| 1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0 -|mant| mantissa of a real number -|xpon| exponant of a real number -|min| min of 2 real numbers -|max| max of 2 real numbers +|fact| n! for integer n or Gamma(x+1) for fractional x +|sign| 1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0 +|mant| mantissa of a real number +|xpon| exponant of a real number +|min| min of 2 real numbers +|max| max of 2 real numbers #### mode @@ -107,9 +107,9 @@ rpn> |keyword|description| |-|-| -|>| binary operator > +|>| binary operator > |>=| binary operator >= -|<| binary operator < +|<| binary operator < |<=| binary operator <= |!=| binary operator != (different) |==| binary operator == (equal) @@ -134,9 +134,9 @@ rpn> |dupn| duplicate n first stack entries |pick| push a copy of the given stack level onto the stack |depth| give stack depth -|roll| move a stack entry to the top of the stack -|rolld| move the element on top of the stack to a higher stack position -|over| push a copy of the element in stack level 2 onto the stack +|roll| move a stack entry to the top of the stack +|rolld| move the element on top of the stack to a higher stack position +|over| push a copy of the element in stack level 2 onto the stack #### string @@ -144,6 +144,8 @@ rpn> |-|-| |->str| convert an object into a string |str->| convert a string into an object +|chr| convert ASCII character code in stack level 1 into a string +|num| return ASCII code of the first character of the string in stack level 1 as a real number #### branch diff --git a/src/object.hpp b/src/object.hpp index 5d6657a..d3d4bda 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -184,7 +184,7 @@ struct ostring : public object } } - // length of _value, not includiong the terminal '\0' + // length of _value, not including the terminal '\0' unsigned int _len; char _value[0]; }; diff --git a/src/program.cpp b/src/program.cpp index b91dd82..e85f7de 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -92,6 +92,8 @@ program::keyword_t program::s_keywords[] = { cmd_undef, "", NULL, "\nSTRING"}, { cmd_keyword, "->str", &program::instr, "convert an object into a string" }, { cmd_keyword, "str->", &program::strout, "convert a string into an object" }, + { cmd_keyword, "chr", &program::chr, "convert ASCII character code in stack level 1 into a string" }, + { cmd_keyword, "num", &program::num, "return ASCII code of the first character of the string in stack level 1 as a real number" }, //BRANCH { cmd_undef, "", NULL, "\nBRANCH"}, diff --git a/src/rpn-real.hpp b/src/rpn-real.hpp index 206aecb..84b5d71 100644 --- a/src/rpn-real.hpp +++ b/src/rpn-real.hpp @@ -1,12 +1,35 @@ void plus() { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ARG_MUST_BE_OF_TYPE(1, cmd_number); - number* right = (number*)_stack->pop_back(); - number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_add(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); + // adding strings + if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string) + { + unsigned int left_str_size = ((ostring*)_stack->get_obj(1))->_len; + unsigned int right_str_size = ((ostring*)_stack->get_obj(0))->_len; + + stack::copy_and_push_back(*_stack, _stack->size()-2, _branch_stack); + stack::copy_and_push_back(*_stack, _stack->size()-1, _branch_stack); + (void)_stack->pop_back(); + (void)_stack->pop_back(); + + ostring* str = (ostring*)_stack->allocate_back(left_str_size+right_str_size+1+sizeof(ostring), cmd_string); + str->_len = left_str_size+right_str_size; + + strncpy(str->_value, ((ostring*)_branch_stack.get_obj(1))->_value, left_str_size); + strncat(str->_value, ((ostring*)_branch_stack.get_obj(0))->_value, right_str_size); + _branch_stack.pop_back(); + _branch_stack.pop_back(); + } + // adding numbers + else + { + ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(1, cmd_number); + number* right = (number*)_stack->pop_back(); + number* left = (number*)_stack->back(); + CHECK_MPFR(mpfr_add(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); + } } void minus() diff --git a/src/rpn-string.hpp b/src/rpn-string.hpp index 07c6ea3..86762e6 100644 --- a/src/rpn-string.hpp +++ b/src/rpn-string.hpp @@ -42,3 +42,31 @@ void strout() // run it prog.run(*_stack, *_heap); } + +void chr() +{ + MIN_ARGUMENTS(1); + ARG_MUST_BE_OF_TYPE(0, cmd_number); + + // get arg as number % 256 + char the_chr = (char)mpfr_get_d(((number*)_stack->pop_back())->_value.mpfr, floating_t::s_mpfr_rnd); + if (the_chr<32 || the_chr>126) + the_chr = '.'; + + // reserve the correct size on stack (1 char) + unsigned int str_size = 1; + ostring* str = (ostring*)_stack->allocate_back(str_size+1+sizeof(ostring), cmd_string); + str->_len = str_size; + str->_value[0] = the_chr; + str->_value[1] = 0; +} + +void num() +{ + MIN_ARGUMENTS(1); + ARG_MUST_BE_OF_TYPE(0, cmd_string); + + double the_chr = (double)((ostring*)_stack->pop_back())->_value[0]; + number* numb = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + numb->_value = the_chr; +} diff --git a/test/07-string.txt b/test/07-string.txt index cb085b9..ef43650 100644 --- a/test/07-string.txt +++ b/test/07-string.txt @@ -106,3 +106,39 @@ erase str-> -> stack should be << -> n << n >> >> erase + +# add (1) +12 34 "one" "two" + +-> stack should be 12, 34, "onetwo" +erase + +# add (2) +"" "one" + "two" "" + +-> stack should be "one", "two" +erase + +# add (3) +"one" + +-> stack size should be 1 +-> error should be 2 +erase + +# chr (1) +"" 33 40 for i i chr + next +-> stack should be "!"#$%&'(" +erase + +# chr (2) +-223 chr 0 chr +-> stack should be "!", "." +erase + +# num (1) +"!wait" num +-> stack should be 33 +erase + +# num (2) +"" num +-> stack should be 0 +erase