Еще один простой по реализации вариант стековых переменных:
\ виртуальное дно стека параметров
user-value vds
\ преобразование имен
m: nalf
a[ 1> ] b[ 2> ] c[ 3> ] d[ 4> ]
e[ 5> ] f[ 6> ] g[ 7> ] h[ 8> ] ;
\ определение определения с установкой виртуального дна стека параметров
: s: s0 @ depth 4 * - TO vds : ;
\ содержимое ячеек стека начиная от виртуального дна стека параметров
m: 1> vds @ ;
m: 2> vds 4 - @ ;
m: 3> vds 8 - @ ;
m: 4> vds 12 - @ ;
m: 5> vds 16 - @ ;
m: 6> vds 20 - @ ;
m: 7> vds 24 - @ ;
m: 8> vds 28 - @ ;
\ Пример:
\ сумма 4-х квадратов чисел
: sum_4sqr1 ( n1 n2 n3 n4 -- n.sum )
dup * swap dup * + swap dup * + swap dup * + ;
s: sum_4sqr2 ( n1 n2 n3 n4 -- n.sum )
nalf dup * a dup * b dup * c dup * + + + nip nip nip ;
: t1 t6| 3 4 5 6 sum_4sqr1 |1t ;
: t2 t6| 3 4 5 6 sum_4sqr2 |1t ;
seet t1
seet t2
see sum_4sqr1
see sum_4sqr2
: sum_4sqr3 { a b c d }
a dup * b dup * c dup * d dup * + + + ;
: t3 t6| 3 4 5 6 sum_4sqr3 |1t ;
seet t3
see sum_4sqr3
t1 (10**6 runs)
pr: 4 4
T1 = 4850208 tics 1 ms 102 us 320 ns
pr: 4 4
Tc = 4876696 tics 1 ms 108 us 340 ns
t2 (10**0 runs)
pr: 4 4
T1 = 4988060 tics 1 ms 133 us 650 ns
pr: 0 0
Tc = 5093440 tics 1 ms 157 us 600 ns
sum_4sqr1
7D2BAF F7E8 IMUL EAX
7D2BB1 8B5500 MOV EDX , 0 [EBP]
7D2BB4 894500 MOV 0 [EBP] , EAX
7D2BB7 8BC2 MOV EAX , EDX
7D2BB9 F7EA IMUL EDX
7D2BBB 034500 ADD EAX , 0 [EBP]
7D2BBE 8B5504 MOV EDX , 4 [EBP]
7D2BC1 894504 MOV 4 [EBP] , EAX
7D2BC4 8BC2 MOV EAX , EDX
7D2BC6 F7EA IMUL EDX
7D2BC8 034504 ADD EAX , 4 [EBP]
7D2BCB 8B5508 MOV EDX , 8 [EBP]
7D2BCE 894508 MOV 8 [EBP] , EAX
7D2BD1 8BC2 MOV EAX , EDX
7D2BD3 F7EA IMUL EDX
7D2BD5 034508 ADD EAX , 8 [EBP]
7D2BD8 8D6D0C LEA EBP , C [EBP]
7D2BDB C3 RET NEAR
45 bytes, 18 instructions
sum_4sqr2
7D2BF3 F7E8 IMUL EAX
7D2BF5 8945FC MOV FC [EBP] , EAX
7D2BF8 8B87DC440000 MOV EAX , 44DC [EDI]
7D2BFE 8B00 MOV EAX , [EAX]
7D2C00 F7E8 IMUL EAX
7D2C02 8945F8 MOV F8 [EBP] , EAX
7D2C05 8B87DC440000 MOV EAX , 44DC [EDI]
7D2C0B 8B40FC MOV EAX , FC [EAX]
7D2C0E F7E8 IMUL EAX
7D2C10 8945F4 MOV F4 [EBP] , EAX
7D2C13 8B87DC440000 MOV EAX , 44DC [EDI]
7D2C19 8B40F8 MOV EAX , F8 [EAX]
7D2C1C F7E8 IMUL EAX
7D2C1E 0345F4 ADD EAX , F4 [EBP]
7D2C21 0345F8 ADD EAX , F8 [EBP]
7D2C24 0345FC ADD EAX , FC [EBP]
7D2C27 8D6D0C LEA EBP , C [EBP]
7D2C2A C3 RET NEAR
56 bytes, 18 instructions
PS. Быстродействие со стековыми локальными переменными практически совпало
с быстродействием без локальных переменных даже для простого определения.
ВеткаЕще один простой по реализации вариант стековых переменных:
11 сообщений · –В Было не предусмотрено доступа к адресам ячеек стека параметров как адресам стековых локальных переменных. Тем самым не было предусмотрено присвоение значений таким локальным переменным(как в ФП). Но форт это не совсем ФП, поэтому присвоение сделать не сложно: m: @1 vds ; m: 1> @1 @ ; и т. д. Подменять имена адресов и содержимого ячеек стека(локалсов) можно произвольным образом. Например адреса можно обозначать большими буквами, b A ! означает записать содержимое второй ячейки от виртуального дна стека параметров в первую ячейку.R В Это точно. 1> 2> + даст возможность использовать сумму (1> 2> +) как 3> без явного присвоения, так как результат сложения содержимого 1 и 2 ячеек будет в ячейке 3 (все промежуточные операции над содержимым стека происходят без потери информации в стеке). В циклах нужно держать количество ячеек стека в определенном диапазоне, поэтому без присвоения (с переустановкой указателя в сторону уменьшения глубины) не обойтись.R В R В Ну раз в ФП отказались от понятия состояния(которое реально все-таки существует), то конечно нельзя. В форте и состояния есть и рекурсия есть. В конечном итоге вычислительные ресурсы всегда ограничены и при реализации тех или иных алгоритмов требуется это учитывать. Теоретически рекурсия и итерация могут быть преобразованы одна в другую. Есть компиляторы, которые позволяют преобразовать рекурсию в итерацию, чтобы, например ускорить код и/или уменьшить расход памяти.R Ссылка
нажмите — покажемНасчет реальности состояния — это философский и довольно спорный вопрос (см. ранее https://t.me/ruforth/14623/20727). Допустим, у нас есть переход (или отношение): Obj₁ → Obj₂, где Obj₁ и Obj₂ различимы как значения. Что именно позволяет нам сказать, что это изменение состояния одного и того же объекта, а не переход от одного объекта к другому? Насколько сильными должны быть изменения, чтобы мы считали Obj₁ и Obj₂ разными объектами? Содержимое объектов не даёт однозначного ответа. Мы должны ввести функцию идентификации, и если Id(Obj₁) = Id(Obj₂) , то мы интерпретируем этот переход как изменение состояния. И при этом неважно, насколько радикально это изменение. А в ФП мы не столько отказываемся от состояния, сколько отказываемся от интерпретации последовательности состояний (значений) как истории одного и того же объекта. #functional