Added 'atoi' to stdlib.
authorAaron Taylor <ataylor@subgeniuskitty.com>
Fri, 13 Mar 2020 04:50:47 +0000 (21:50 -0700)
committerAaron Taylor <ataylor@subgeniuskitty.com>
Fri, 13 Mar 2020 04:50:47 +0000 (21:50 -0700)
stdlib/README.md
stdlib/convert.pvvs [new file with mode: 0644]
stdlib_tests/7001_atoi.pvvs [new file with mode: 0644]
stdlib_tests/vv_test.py

index 40b9f4a..eb92964 100644 (file)
@@ -63,6 +63,7 @@ header comment for each function to learn the call and return stack.
          101100 ----- rshift                        (logic.pvvs)
          101101 ----- lshift                        (logic.pvvs)
          110xxx - conversion functions
          101100 ----- rshift                        (logic.pvvs)
          101101 ----- lshift                        (logic.pvvs)
          110xxx - conversion functions
+         110000 ----- atoi                          (convert.pvvs)
          111xxx - debug functions
          111000 ----- dump heap                     (debug.pvvs)
          111001 ----- dump stack                    (debug.pvvs)
          111xxx - debug functions
          111000 ----- dump heap                     (debug.pvvs)
          111001 ----- dump stack                    (debug.pvvs)
diff --git a/stdlib/convert.pvvs b/stdlib/convert.pvvs
new file mode 100644 (file)
index 0000000..e20c809
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef VVS_STDLIB_CONVERT
+#define VVS_STDLIB_CONVERT
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@   atoi (110000)
+@ Description:
+@   Convert null-terminated ASCII string to integer.
+@   Result is negative if leading character is a hyphen ('-').
+@   Result is positive if leading character is a plus sign ('+') or number.
+@   Excluding the sign, parsing halts on the first non-numeric ASCII character.
+@   Since all possible return values are valid, this subroutine simply returns
+@   zero if no parseable number was found. Any stronger validity checks are the
+@   responsibility of the caller. Similarly, no overflow checks are performed.
+@   In addition to returning the parsed integer, also returns a pointer to the
+@   first character after the parsed integer.
+@ Call Stack:
+@   pointer to first character  <-- TOS
+@ Return Stack:
+@   integer
+@   pointer to last parsed character  <-- TOS
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#include <stack.pvvs>
+#include <string.pvvs>
+NSSVTTSSSSN             | Mark: 110000 (atoi)
+
+@ Check the first character and create a 'sign' flag on the stack.
+@ Update the pointer to point to the first numeric character.
+SNS                     | DUP
+TTT                     | LOAD
+SSSSSTSTTSTN            | PUSH 45 (ASCII '-')
+TSST                    | SUBTRACT
+NTSSSTTSSSSSSSSSSSSN    | BRZ > 00110000 00000000 (found_minus_sign)
+SNS                     | DUP
+TTT                     | LOAD
+SSSSSTSTSTTN            | PUSH 43 (ASCII '+')
+TSST                    | SUBTRACT
+NTSSSTTSSSSSSSSSSSTN    | BRZ > 00110000 00000001 (found_plus_sign)
+NSNSSTTSSSSSSSSSSTSN    | JMP > 00110000 00000010 (found_digit)
+NSSVSSTTSSSSSSSSSSSTN   | Mark: 00110000 00000001 (found_plus_sign)
+SSSTN                   | PUSH +1
+TSSS                    | ADD
+NSSVSSTTSSSSSSSSSSTSN   | Mark: 00110000 00000010 (found_digit)
+SSSTN                   | PUSH +1 (sign_flag)
+SNT                     | SWAP
+NSNSSTTSSSSSSSSSSTTN    | JMP > 00110000 00000011 (done_with_sign_flag)
+NSSVSSTTSSSSSSSSSSSSN   | Mark: 00110000 00000000 (found_minus_sign)
+SSSTN                   | PUSH +1
+TSSS                    | ADD
+SSTTN                   | PUSH -1 (sign_flag)
+SNT                     | SWAP
+NSSVSSTTSSSSSSSSSSTTN   | Mark: 00110000 00000011 (done_with_sign_flag)
+
+@ Create an accumulator on the TOS.
+SSSSN                   | PUSH 0 (accumulator)
+
+@ Main loop examines string one character at a time, building result in accumulator.
+@ TOS> accumulator, string_ptr, sign_flag
+NSSVSSTTSSSSSSSSSTSSN   | Mark: 00110000 00000100 (atoi:main_loop)
+SSSTSN                  | PUSH +2
+NSTTTSSN                | JSR > 1100 (deepdup)
+TTT                     | LOAD
+SNS                     | DUP
+NSTTSSSSTN              | JSR > 100001 (isdigit)
+NTSSSTTSSSSSSSSSTSTN    | BRZ > 00110000 00000101 (found_end_of_number)
+SSSSSTTSSSSN            | PUSH 48 (ASCII '0')
+TSST                    | SUBTRACT
+SNT                     | SWAP
+SSSTSTSN                | PUSH 10
+TSSN                    | MULTIPLY
+TSSS                    | ADD
+SNT                     | SWAP
+SSSTN                   | PUSH 1
+TSSS                    | ADD
+SNT                     | SWAP
+NSNSSTTSSSSSSSSSTSSN    | JMP > 00110000 00000100 (atoi:main_loop)
+
+@ Clean up and return
+@ TOS> character, accumulator, string_ptr, sign_flag
+NSSVSSTTSSSSSSSSSTSTN   | Mark: 00110000 00000101 (found_end_of_number)
+SNN                     | DROP
+SSSTTN                  | PUSH 3
+NSTTSTTN                | JSR > 1011 (stackrotatereverse)
+TSSN                    | MULTIPLY
+SNT                     | SWAP
+NTN                     | RTS
+
+#endif
diff --git a/stdlib_tests/7001_atoi.pvvs b/stdlib_tests/7001_atoi.pvvs
new file mode 100644 (file)
index 0000000..c4ea625
--- /dev/null
@@ -0,0 +1,59 @@
+A"42"
+SSSTSSSSSN      | PUSH 32 (address)
+SSSTSN          | PUSH 2 (count)
+NSTTTTTTN       | JSR > 11111 (spew)
+SSSTSSSSSN      | PUSH 32 (address)
+NSTTTSSSSN      | JSR > 110000 (atoi)
+SNN             | DROP
+NSTTTTTSTN      | JSR > 111101 (debug:printsignednumber)
+
+A"+42"
+SSSTSSSSSN      | PUSH 32 (address)
+SSSTTN          | PUSH 3 (count)
+NSTTTTTTN       | JSR > 11111 (spew)
+SSSTSSSSSN      | PUSH 32 (address)
+NSTTTSSSSN      | JSR > 110000 (atoi)
+SNN             | DROP
+NSTTTTTSTN      | JSR > 111101 (debug:printsignednumber)
+
+A"-42"
+SSSTSSSSSN      | PUSH 32 (address)
+SSSTTN          | PUSH 3 (count)
+NSTTTTTTN       | JSR > 11111 (spew)
+SSSTSSSSSN      | PUSH 32 (address)
+NSTTTSSSSN      | JSR > 110000 (atoi)
+SNN             | DROP
+NSTTTTTSTN      | JSR > 111101 (debug:printsignednumber)
+
+A"+"
+SSSTSSSSSN      | PUSH 32 (address)
+SSSTN           | PUSH 1 (count)
+NSTTTTTTN       | JSR > 11111 (spew)
+SSSTSSSSSN      | PUSH 32 (address)
+NSTTTSSSSN      | JSR > 110000 (atoi)
+SNN             | DROP
+NSTTTTTSTN      | JSR > 111101 (debug:printsignednumber)
+
+A"-"
+SSSTSSSSSN      | PUSH 32 (address)
+SSSTN           | PUSH 1 (count)
+NSTTTTTTN       | JSR > 11111 (spew)
+SSSTSSSSSN      | PUSH 32 (address)
+NSTTTSSSSN      | JSR > 110000 (atoi)
+SNN             | DROP
+NSTTTTTSTN      | JSR > 111101 (debug:printsignednumber)
+
+A""
+SSSTSSSSSN      | PUSH 32 (address)
+SSSSN           | PUSH 0 (count)
+NSTTTTTTN       | JSR > 11111 (spew)
+SSSTSSSSSN      | PUSH 32 (address)
+NSTTTSSSSN      | JSR > 110000 (atoi)
+SNN             | DROP
+NSTTTTTSTN      | JSR > 111101 (debug:printsignednumber)
+
+NNN             | DIE
+
+#include <heap.pvvs>
+#include <convert.pvvs>
+#include <debug.pvvs>
index 4ec6a81..045f81c 100755 (executable)
@@ -50,6 +50,7 @@ tests = [
         ['6007_printf_staticheapstring', '', 'test'],
         ['6008_printf_escapedstackstring', '', '\\%\t\n'],
         ['6009_printf_substitutedstackstring', '', 'Atest142+42'],
         ['6007_printf_staticheapstring', '', 'test'],
         ['6008_printf_escapedstackstring', '', '\\%\t\n'],
         ['6009_printf_substitutedstackstring', '', 'Atest142+42'],
+        ['7001_atoi', '', '+42+42-42+0+0+0'],
         ] 
 
 for test in tests:
         ] 
 
 for test in tests: