All streams
Search
Write a publication
Pull to refresh
0
0

Dark side eye. А у нас печеньки! А у вас?

Send message
О, а так и вправду лучше =) Хмм… И расширение удобное — добавил себе замену и всех остальных шрифтов на нормальные, т.к. те, что используются на фрилансим/тостере в опере 12 постоянно отваливаются и выдают квадратики.
Миддл клик, контрол клик.
Вот-вот! И это при том, что там в среднем один-два заказа в день добавляются (разработка ПО). И за это платить 300р? Вот если бы там было как на некоторых других крупных биржах по 20-30-50 в день заказов — я еще может быть понял бы. Но вот так силой заставлять платить — ИМХО, это как-то перебор. Сильно похоже на вымогательство — поэтому не буду платить принципиально.
Неделя логотипов из лего:



Большая картинка

Но есть нюансы. Оказалось, что на горшке можно просидеть довольно неподвижно и более трех минут, а тогда придется махать руками. Это, конечно, минус. Поэтому я думаю о том, что нужен еще датчик веса — сами понимаете, для чего. Хотя это лишние провода в ванной.

Датчик на закрытие двери изнутри: например на блокиратор дверного замка или какой-то сенсор, который определяет, что дверь была закрыта изнутри. Плюс немого логики: если в ванной есть движение, то свет/музыка остаются включенными до тех пор, пока кто-то не закроет дверь снаружи / откроет изнутри и в ванной после этого не будет движения.
в чем прикол?

Отличная демонстрация того, что современные компиляторы(интерпретатор, ЯП — нужное подчеркнуть или вставить что-то другое) настолько сложны, что даже безобидный на первый взгляд код вызывает неимоверное количество ошибок, а то и вовсе вводит в ступор сам компилятор.
Частное техническое задание.
Да, почти все тесты платные. Есть несколько бесплатных — например на знание английского.
Да, gForth в целом довольно неплох и вполне юзабелен. Но и у него есть свои особенности, плюсы и недостатки. Один из немногих х64 фортов. Вот его репозиторий на гитхабе: github.com/forthy42/gforth — там всегда самая свежая версия. В официальных репозиториях линуксов отставание в год и более. На данный момент главное преимущество данной версии в полной поддержке стандартной либы ptheard — т.е. многопоточности. А вот с юзер-переменными там немного печальнее.
Андроидная версия все таки еще сырая, но в целом работает.
Тогда сам редактор должен быть написан на форте =) Гибкость синтаксиса форта — головная боль для редакторов его исходного кода.
Уже пройденный этап — так неудобно. Удобнее всего с браузером взаимодействовать через веб-сокеты: использовал в одном проекте форт сокет-сервер для точных и быстрых вычислений, а GUI был на веб-ките. Вся графика на jQuery+Html, а ядро программы и основная логика — на форте (СПФ).
Да, например загрузчик БСД или вот тот же самый ПДФ вырос из форта.
Кто был достаточно внимателен, то заметил что мы переопределили базовые слова двоеточие и минус. Как быть с этим? Ответ ниже.

Эмм… Зачем же так извращаться-то? А дальше-то как писать? Таки немного покритикую выбранный подход: для демонстрации тех или иных способов решения задачи в целом пример годится. Но вот в продакшене данный код бесполезен. Во-первых: совершенно ненужное переопределение стандартных и привычных слов. Во-вторых, это нужно было делать в отдельный словарь и просто переключать поиск на него в тот момент, когда это нужно. В третьих: существует куча библиотек для строковых операций в подкаталоге ~devel, в т.ч. для сложения строк/чисел, так же существуют опенсорсные либы для работы со строками (например плагины к ннкрон). Достаточно подключить и можно использовать что-то типа такого:
" %DD%-%MM%-%YYYY%/%HH%:%MM%:%SS%"
В четвертых: можно использовать встроенный механизм конвертации чисел для получения строки с нужным форматированием.
Пример(код одноразовый — написал и забыл, приоритет — скорость):
Код из реального проекта для отдачи времени в заголовках браузеру по стандарту RFC 822
WINAPI: GetSystemTime Kernel32.dll

0
2 -- -Year		        \ Указывает текущий год
2 -- -Month		        \ Текущий месяц; Январь = 1, Февраль = 2, и так далее
2 -- -DayOfWeek       \ Текущий день недели; Воскресенье = 0, Понедельник = 1, и так далее
2 -- -Day             \ Текущий день месяца
2 -- -Hour            \ Час
2 -- -Minute          \ Минуты
2 -- -Second          \ Секунды
2 -- -Milliseconds    \ Миллисекунды
CONSTANT /SYSTEMTIME
USER-CREATE SYSTEMTIME-BUF /SYSTEMTIME USER-ALLOT
USER-CREATE WebTime[] 30 USER-ALLOT
29 CONSTANT WebTime#

CREATE WebDays S" Sun, Mon, Tue, Wed, Thu, Fri, Sat, " HERE SWAP DUP ALLOT 0 C, CMOVE
CREATE WebMonths  S"     Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec " HERE SWAP DUP ALLOT 0 C, CMOVE

: WebTime!   \ ( addr -- ) \ Записать по адресу addr строку с текущей датой вида "Fri, 04 Jul 2008 08:42:36 GMT"
  >R SYSTEMTIME-BUF GetSystemTime                               \ Получаем текущее системное время
  DUP -DayOfWeek W@  5 * WebDays + R@ 5 CMOVE  R> 5 + >R        \ и конвертируем его в формат RFC 822
  DUP -Day W@ 0 <# # # #> R@ SWAP CMOVE  R> 2 + >R              \ Код хоть и немного жуткий, зато быстрый — а это главное
  BL R> DUP 1+ >R C!
  DUP -Month W@  CELLS WebMonths + R@ 4 CMOVE  R> 4 + >R
  DUP -Year W@ 0 <# # # # # #> R@ SWAP CMOVE  R> 4 + >R
  BL R> DUP 1+ >R C!
  DUP -Hour W@ 0 <# # # #> R@ SWAP CMOVE R> 2 + >R
  [CHAR] : R> DUP 1+ >R C!
  DUP -Minute W@ 0 <# # # #> R@ SWAP CMOVE R> 2 + >R
  [CHAR] : R> DUP 1+ >R C!
  -Second W@ 0 <# # # #> R@ SWAP CMOVE R> 2 + >R
  S"  GMT" R> SWAP CMOVE
;

: GetWebTime   \ ( -- a u )
  WebTime[] WebTime!
  WebTime[] 29
;

В пятых:: оптимальнее сначала собирать все данные для отправки браузеру в один буфер и одним вызовом передавать в сокеты, а не делать овер 9000 апи-вызовов.
В шестых: можно использовать вектор NOTFOUND для сбора строк, не являющихся словами. Т.е. создаем словарь с нужным набором слов, которые просто пишут в текущую позицию в буфере. Далее, когда нужно сделать форматированную строку, то просто переключаем словарь и записываем в вектор NOTFOUND слово, которое будет неизвестные слова складывать в буфер. Но это уже ближе к экзотическим способам решения задачи.
Например: github.com/yarus23/SPF.JS — заявлена совместимость с СПФ, но я его особо не ковырял — так что ничего конкретного сказать не могу.
Под R обычно обозначает стек возвратов. И он всегда один, т.к. на этот стек сохраняется следующий адрес для перехода перед тем, как происходит вызов слова. Использовать его для временного хранения данных можно, но не желательно, т.к. неосторожное обращение с ним может все поломать. С другой стороны, его часто используют для временных данных с целью ускорения работы программы, т.к. его вершина тоже обычно представлена отдельным регистром или несколькими процессора или он реализован аппаратно (в форт процессорах, например). Кроме того, существуют еще и другие виды стеков: например стек структур управления, стеки циклов, стек для флоат чисел(в х86 он аппаратный), локальные стеки, даже бывают отдельные стеки для адресов, строк и вообще любых других типов данных.
А так, стеков можно наделать сколько душе угодно:
1024 CONSTANT NewStackSize
CREATE NewStack /NewStack NewStackSize ALLOT 0 ,
0 VALUE NewStackDepth
: -TH   \ ( addr n -- addr+n*cell )
    CELLS +
;

: NewStack!   \ ( n -- )
    NewStackDepth 1024 < IF
        NewStack NewStackDepth -TH !
        NewStackDepth 1+ TO NewStackDepth
    ELSE
        ABORT" Переполнение стека NewStack"
    THEN
;

: ClearNewStack
  0 TO NewStackDepth
;

: NewStack@   \ ( -- n )
    NewStackDepth IF
        NewStackDepth 1- TO NewStackDepth
        NewStack NewStackDepth -TH @
    ELSE
        ABORT" Опустошение стека NewStack"
    THEN
;

: NewStackGet   \ ( -- n )
    NewStackDepth IF
        NewStack NewStackDepth 1- -TH @
    ELSE
        0
    THEN
;
Не так. Слово forget переносит текущий указатель области кода на адрес, соответствующий указанному слову. Т.е. затираются все слова, определенные после указанного слова. Т.о. система возвращается в состояние, предшествующее определению данному слову и следующее слово будет записано по адресу «забываемого» слова. Это если в общих чертах. А если чуть углубиться: существуют форт системы с раздельным хранением кода и данных (код и строки, структуры, константы и отеделены друг от друга) и совместным (код и данные перемешаны), есть еще системы с поддержкой многопоточности и т.н. «пользовательских переменных » — переменных, которые для каждого потока разные, плюс существуют разные варианты структуры словарей. Т.о. в какой-то простой системе forget сводится к записи адреса слова в переменную указатель текущего адреса для компиляции, а в какой-то более сложной системе forget настолько сложно сделать, что лучше заняться чем-нибудь полезным и никогда об этом думать.
Да. Можно переопределить даже компилятор и вообще практически все что угодно, а при использовании хаков вообще можно сделать все захочется.
Сидишь пишешь что-то на форте — вдруг надоело или еще чего: взял написал пару символов и прям тут же пишешь на си.
В качестве наглядного примера приведу реальный кусок кода из gForth:
Скрытый текст
c-library socket
\c #include <netdb.h>
c-function gethostbyname gethostbyname a -- a ( name -- hostent )
\c #include <unistd.h>
c-function gethostname gethostname a n -- n ( c-addr u -- ior )
\c #include <errno.h>
\c #define get_errno() errno
c-function errno get_errno -- n ( -- value )
\c #include <sys/types.h>
\c #include <sys/socket.h>
c-function socket socket n n n -- n ( class type proto -- fd )
c-function closesocket close n -- n ( fd -- ior )
c-function connect connect n a n -- n ( fd sock size -- err )
c-function send send n a n n -- n ( socket buffer count flags -- size )
c-function recv recv n a n n -- n ( socket buffer count flags -- size )
c-function listen() listen n n -- n ( socket backlog -- err )
c-function bind bind n a n -- n ( socket sockaddr socklen --- err )
c-function accept() accept n a a -- n ( socket sockaddr addrlen -- fd )
\c #include <stdio.h>
c-function fdopen fdopen n a -- a ( fd fileattr -- file )
\c #include <fcntl.h>
c-function fcntl fcntl n n n -- n ( fd n1 n2 -- ior )
\c #include <arpa/inet.h>
c-function htonl htonl n -- n ( x -- x' )
c-function htons htons n -- n ( x -- x' )
c-function ntohl ntohl n -- n ( x -- x' )
\c #define fileno1(file) fileno((FILE*)(file))
c-function fileno fileno1 a -- n ( file* -- fd )
end-c-library

4 4 2Constant int%
2 2 2Constant short%

struct
    cell% field h_name
    cell% field h_aliases
    int% field h_addrtype
    int% field h_length
    cell% field h_addr_list
end-struct hostent

struct
    short% field family
    short% field port
    int% field sin_addr
    cell% 2* field padding
end-struct sockaddr_in

В данном случае, си код сохраняется в отдельный файл, к нему дописывается еще один инклюд с частью кода самого gForth, он скармливается gcc и на выходе получается so библиотека, которая подключается и используется уже в форт-коде.
А вот пример хака:
: IFNOT   \ ( flag -- ) 
  ?COMP  \ Проверка на режим компиляции
  [COMPILE] IF
  0x85 HERE 5 - C!   \ Хак: подменяем скомпилированную ранее инструкцию JE(0x84) на JNE(0x85)
  \ Высокоуровневый вариант:
  \ POSTPONE 0= [COMPILE] IF
; IMMEDIATE
Вообще, обычно комментарий в форте это обратный слеш \, а два минуса -- это обычно определение нового поля в текущей структуре данных.
0
<size> -- field1_name
<size> -- field2_name
<size> -- field3_name
CONSTANT /structure_name

Впрочем, слово «обычно» зачастую сложно применимо относительно того или иного аспекта в форте.
Да, все верно. Логика обычного литерала в общем случае сводится к следующему: поместить в стек число из области памяти для статических данных. Обычно это следующий адрес для исполнения (да, прямо там же где и код) и пропуск данного адреса (прибавление размера ячейки) или смещение в области пользовательских данных. Говорю так размыто по причине того, что реализаций очень много и у каждого автора на все есть своё мнение =)
А положить ноль или единицу на вершину стека — это по сути одна-две процессорных команды.
Хабр не знает сорцов Форта?

В общем случае все сводится вот к этому:
Скрытый текст
: INTERPRET ( -> ) \ интерпретировать входной поток
  BEGIN
    PARSE-NAME DUP   \ PARSE-NAME тупо перебирает символы из входного потока в поиске разделителя (пробел и меньше) и возвращает найденное слово
  WHILE
    SFIND   \ Ищем слово в словаре/словарях
    IF
         STATE @   \ Проверка режима работы системы: компиляция или исполнение
         IF COMPILE, ELSE EXECUTE THEN   \ Компилируем слово или исполняем его
    ELSE
         NOTFOUND   \ Зависит от реализации, но в общем случае тут обрабатываем исключение "слово не найдено", обычно тут еще бывает проверка "число?" -> компилируем числовой литерал или кладем число на стек
    THEN
  REPEAT
2DROP  \ Выкидываем уже не нужную строку со стека
;


Если же интересуют подробности, то можно заглянуть сюда (SP-Forth) или сюда (gForth), или даже вот сюда (форт форум).

Information

Rating
Does not participate
Registered
Activity

Specialization

Application Developer, Software Architect
Lead