Forth и другие саморасширяющиеся системы программирования Locations of visitors to this page
Текущее время: Сб апр 20, 2024 03:14

...
Google Search
Forth-FAQ Spy Grafic

Часовой пояс: UTC + 3 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 8 ] 
Автор Сообщение
 Заголовок сообщения: неименованные стеки
СообщениеДобавлено: Пт июн 08, 2007 21:13 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 5062
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 23 раз.
Поблагодарили: 63 раз.
Иногда бывает необходимо складировать данные на промежуточный стек.
При этом каждый раз такой стек приходится создавать под каждую новую задачу.
Это не всегда удобно, тем более, что задача достаточно типовая. Для того,
чтобы повторно не писать каждый раз определяющие стек слова и создана эта
либа.

<pre>
\ 04-06-2007 ~mOleg
\ Copyright [C] 2007 mOleg mininoleg@yahoo.com
\ неименованные стеки

REQUIRE ?DEFINED devel\~moleg\lib\util\ifdef.f
REQUIRE ADDR devel\~moleg\lib\util\addr.f
REQUIRE FRAME devel\~mOleg\lib\util\stackadd.f

0 \ структура описывающая стек
CELL -- StackTop \ указатель на последний элемент стека
CELL -- StackLimit \ предельный размер стека
CELL -- StackBottom \ указатель на начало стека
CONSTANT /NStack

\ посчитать размер стека глубиной в u ячеек в байтах
: StackSize ( # --> u ) CELLS /NStack + ;

\ разметить память, начало которой определено addr под стек глубиной depth
: StackPlace ( depth addr --> stack )
2DUP >R CELLS +
R> OVER StackBottom A!
TUCK StackLimit !
0 OVER StackTop ! ;

\ получить глубину указанного стека
: StackDepth ( stack --> n ) StackTop @ ;

\ получить адрес текущей вершины стека
: TopAddr ( stack --> addr ) DUP StackDepth CELLS - ;

\ проверить не выходит ли указатель стека за его пределы
: ?Balanced ( stack --> ) DUP TopAddr OVER StackBottom A@ ROT 1 + WITHIN ;

\ прочесть верхний элемент указанного стека
: ReadTop ( stack --> n ) TopAddr @ ;

\ переместить указатель вершины стека на указанное количество ячеек
: MoveTop ( stack u --> ) OVER StackTop +! ?Balanced 0= THROW ;

\ удалить верхнее значение с вершины указанного стека
: DropTop ( stack --> ) -1 MoveTop ;

\ извлечь число из указанного стека
: PopFrom ( stack --> n ) DUP ReadTop SWAP DropTop ;

\ сохранить число в указанный стек
: PushTo ( n stack --> ) DUP 1 MoveTop TopAddr ! ;

\ переместить указанное количество # элементов a,b,c,,x на стек stack
: CopyTo ( [ a b c .. x ] # stack --> [ a b c .. x ] # )
2DUP StackTop ! DUP ?Balanced 0= THROW
OVER >R
TopAddr >R CELLS >R SP@ 2R> CMOVE
R> ;

\ переместить указанное количество элементов со стека данных на указанный стек
: MoveTo ( [ a b c .. x ] # stack --> ) CopyTo nDROP ;

\ копировать все содержимого стека stack на вершину стека данных
: GetFrom ( stack --> a b c .. x # )
DUP TopAddr SWAP StackDepth 2>R
R@ FRAME >R SP@ R> SWAP
2R> CELLS >R SWAP R> CMOVE ;

\ создать неименованный стек в хипе
: NewStack ( depth --> stack ) DUP StackSize ALLOCATE THROW StackPlace ;

\ освободить место, занимаемое стеком
: KillStack ( stack --> ) StackBottom A@ FREE THROW ;

?DEFINED test{ \EOF -- тестовая секция ---------------------------------------

test{ 5 NewStack DUP ?Balanced 0= THROW KillStack
5 NewStack VALUE stack
123 stack PushTo stack ?Balanced 0= THROW
234 stack PushTo stack ?Balanced 0= THROW
345 stack PushTo stack ?Balanced 0= THROW
456 stack PushTo stack ?Balanced 0= THROW
567 stack PushTo stack ?Balanced 0= THROW
567 stack ' PushTo CATCH 0= THROW 2DROP
stack -1 MoveTop
567 stack ReadTop <> THROW
567 stack PopFrom <> THROW
456 stack PopFrom <> THROW
stack StackDepth 3 <> THROW
stack PopFrom DROP stack PopFrom DROP stack PopFrom DROP
stack ?Balanced 0= THROW
stack ' PopFrom CATCH 0= THROW DROP
S" passed" TYPE
}test

\EOF
Пользоваться следует так:

Сначала создаем стек необходимой глубины:

200 NewStack

в результате получается адрес стека ( --> saddr )

дальше лучше сохранить адрес стека куда-нибудь, например

TO stack \ Понятно, что VALUE переменная stack уже должна быть создана

Ну и дальше просто работаем со стеком с помощью слов PushTo PopFrom ReadTop..

Если не хочется каждый раз "вспоминать" адрес стека можно создать
необходимый набор слов, не забыв о том, что стек таки перед использованием
надобно создать.

Понятно, что данный вид стеков будет более медленным, нежели базовые
стеки (данных и возвратов). Можно кое-что выиграть от переписывания данной
либы на ассемблере, но меня более волнует переносимость.

Да, стек растет вниз! То есть как обычный стек.

</pre>


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Пт июн 08, 2007 21:15 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 5062
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 23 раз.
Поблагодарили: 63 раз.
ну и сразу пример работы с такими стеками:

<pre>
\ 05-06-2007 ~mOleg
\ Copyright [C] 2007 mOleg mininoleg@yahoo.com
\ пост-скрипт подобная работа со стеком. Маркеры.

REQUIRE ?DEFINED devel\~moleg\lib\util\ifdef.f
REQUIRE NewStack devel\~mOleg\lib\util\stack.f

USER-VALUE MARKERS \ хранит указатель на стек маркеров

0x10 CONSTANT #marks \ глубина стека маркеров

\ инициализация стека маркеров - необходимо выполнять один раз на поток
\ повторное выполнение приводит к обнулению всех ранее сохраненных маркеров
: init-markers ( --> )
MARKERS DUP IF KillStack ELSE DROP THEN
#marks NewStack TO MARKERS ;

\ запомнить текущий указатель стека данных в стеке маркеров
: MarkMoment ( --> ) SP@ MARKERS PushTo ;

\ проверить, есть ли изменения глубины стека с последнего сохраненного момента
: TestMoment ( --> flag ) SP@ MARKERS ReadTop = ;

\ узнать, сколько маркеров осталось на стеке маркеров
: Marks# ( --> # ) MARKERS StackDepth ;

\ проверить, является ли текущий маркер достоверным
: ValidMark ( --> flag ) Marks# DUP IF DROP SP@ MARKERS ReadTop > 0= THEN ;

\ возвратить состояние стека данных до уровня сохраненного по MarkMoment
\ последний сохраненный маркер автоматически удаляется
: ClearToMark ( xj --> )
ValidMark IF MARKERS PopFrom SP!
ELSE -1 THROW
THEN ;

\ посчитать количество элементов на стеке данных, добавленных с момента
\ запомненного с помощью MarkMoment
: CountToMark ( --> n )
ValidMark IF SP@ MARKERS ReadTop SWAP - CELL /
ELSE -1 THROW
THEN ;

\ удалить запомненное значение с вершины стека маркеров
: ForgetMark ( --> ) MARKERS PopFrom DROP ;

\ удалить все маркеры со стека маркеров
: ClearMarks ( --> ) 0 MARKERS MoveTo ;

\ прочесть все маркеры на стек данных
: AllMarks ( --> [ a b c .. z ] # ) MARKERS GetFrom ;

?DEFINED test{ \EOF -- тестовая секция ---------------------------------------

test{ init-markers
1 2 MarkMoment 3 4 5 ClearToMark 1 2 D= 0= THROW
ValidMark THROW
MarkMoment ValidMark 0= THROW
1 2 3 4 CountToMark 4 <> THROW
ClearToMark
S" passed" TYPE
}test

\EOF это, во-первых, пример работы с библиотечкой ~mOleg\lib\util\stack.f ,
а во-вторых, метод управления содержимым стека данных.
</pre>


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Пт июн 08, 2007 21:22 
---


Последний раз редактировалось profiT Сб мар 01, 2008 01:03, всего редактировалось 1 раз.

Вернуться к началу
  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Пт июн 08, 2007 21:30 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 5062
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 23 раз.
Поблагодарили: 63 раз.
profiT писал(а):
~day/hype3/lib/stack.f? Указан в SPF_DEVEL.

почти, да не то.
У меня без всяких оопов и не "Minimalistic stack" а просто неименованный стек.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Сб июн 09, 2007 07:40 
Не в сети
Аватара пользователя

Зарегистрирован: Чт июл 20, 2006 11:31
Сообщения: 2168
Откуда: Екб
Благодарил (а): 0 раз.
Поблагодарили: 41 раз.
mOleg писал(а):
У меня без всяких оопов и не "Minimalistic stack" а просто неименованный стек.

Стек все-таки именованный - адрес стека в глобальной переменной с именем. Для следующего стека должно быть
свое имя другой глобальной переменной и т.д. :)
Стек создается под задачу, операций со стеком немного, есть смысл запрятать в эти операции адрес стека.
Для каждого стека есть смысл определить свои операции чтобы не путаться. Ну в конце концов адрес конкретного стека давать векторно, переопределяя в каждом случае этот вектор, но по-моему это худший вариант - доп. нагрузка на программиста.

_________________
С уважением, chess


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Вс июн 10, 2007 12:22 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 5062
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 23 раз.
Поблагодарили: 63 раз.
chess писал(а):
Стек все-таки именованный - адрес стека в глобальной переменной с именем. Для следующего стека должно быть свое имя другой глобальной переменной и т.д.

нет, это не обязательно. Адрес стека может лежать например на вершине стека возвратов, или в локальной переменной или на другом специализированном стеке стеков 8) уж если на то пошло.

chess писал(а):
Стек создается под задачу, операций со стеком немного, есть смысл запрятать в эти операции адрес стека.

Тут другая проблема. Часто бывает нужно создать например два стека, и при этом не хочется все время отлаживать механизм стека. Вроде мелочь, но всегда можно ошибиться. А так механизм есть, причем сам механизм отвязан от места, где стек будет храниться. То есть можно создать и в статической памяти стек и в локальной и в хипе.

chess писал(а):
Для каждого стека есть смысл определить свои операции чтобы не путаться. Ну в конце концов адрес конкретного стека давать векторно, переопределяя в каждом случае этот вектор, но по-моему это худший вариант - доп. нагрузка на программиста.

не вижу смысла. По крайней мере мне так оказалось удобнее.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Вс июн 10, 2007 12:37 
Не в сети

Зарегистрирован: Вт май 09, 2006 12:31
Сообщения: 3438
Благодарил (а): 5 раз.
Поблагодарили: 16 раз.
Цитата:
не вижу смысла. По крайней мере мне так оказалось удобнее.
Кажется, это наиболее частые слова на форуме

_________________
понимаю некоторую бестолковость некоторых вопросов


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Вс июн 10, 2007 12:43 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 5062
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 23 раз.
Поблагодарили: 63 раз.
вопрос писал(а):
Цитата:
не вижу смысла. По крайней мере мне так оказалось удобнее.
Кажется, это наиболее частые слова на форуме


Это вполне оправданные слова, так как я решил задачу наиболее удобным для меня образом. Более того рассмотрел несколько вариантов, как это делать лучше 8) По крайней мере применительно к моей задаче, для которой писалась либа! Да к тому же привел пример использования.

На голословные предложения без пояснения, без рассмотрения вариантов 8)... Вы действительно хотите услышать другой ответ???


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 8 ] 

Часовой пояс: UTC + 3 часа [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 20


Вы не можете начинать темы
Вы можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
phpBB сборка от FladeX // Русская поддержка phpBB