Стандарт определяет только низкоуровневое слово >NUMBER
для интерпретации целых чисел. OTOH, использующий EVALUATE
для преобразования строк в числа, является быстрым и грязным способом. Либо используйте его без проверок (в случае доверенного ввода), либо не используйте его вообще. Попытка отфильтровать строку до EVALUATE
— плохая идея: она имеет стоимость самого слова >NUMBER
и низкий коэффициент повторного использования.
Примечание: ни >NUMBER
, ни EVALUATE
не обнаруживают числового переполнения.
В любом случае, ваше слово для ввода целого числа из одной ячейки может быть определено примерно так:
: accept-number ( -- n )
PAD DUP 80 ACCEPT ( addr u ) StoN ( n )
;
В случае доверенного ввода вы можете определить StoN
как
: StoN ( addr u -- x )
STATE @ ABORT" This naive StoN should not be used in compilation state"
DEPTH 2- >R
EVALUATE
DEPTH 1- R> <> IF -24 THROW THEN
\ check depth to accept the single-cell numbers only
;
В противном случае (в случае ненадежного ввода) у вас есть два варианта: полагаться на определенные слова конкретной системы Forth или использовать какую-либо (возможно, вашу собственную) библиотеку.
Я использую следующий словарь для определения StoN
:
\ ---
\ The words from Substring Matching library
\ (where length is counted in address units)
: MATCH-HEAD ( a u a-key u-key -- a-right u-right true | a u false )
2 PICK OVER U< IF 2DROP FALSE EXIT THEN
DUP >R
3 PICK R@ COMPARE IF RDROP FALSE EXIT THEN
SWAP R@ + SWAP R> - TRUE
;
\ ---
\ The words from Literals interpreting library
\ (where prefix 'I-' is shortcut for Interpret)
: I-DLIT ( a u -- x x true | a u false )
2DUP S" -" MATCH-HEAD >R
DUP 0= IF NIP RDROP EXIT THEN
0 0 2SWAP >NUMBER NIP IF RDROP 2DROP FALSE EXIT THEN
R> IF DNEGATE THEN 2SWAP 2DROP TRUE
;
: I-LIT ( a u -- x true | a u false )
I-DLIT IF D>S TRUE EXIT THEN FALSE
;
После этого StoN
можно определить как:
: StoN ( a u -- x ) I-LIT IF EXIT THEN -24 THROW ;
Упомянутые библиотеки можно найти на GitHub:
person
ruvim
schedule
06.08.2018