User Tools

Site Tools


geda:gnetlist_scheme_tutorial.ru

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Last revision Both sides next revision
geda:gnetlist_scheme_tutorial.ru [2012/10/25 06:49]
vzh Spelling
geda:gnetlist_scheme_tutorial.ru [2014/04/25 06:27]
vzh Workaround for po4a system: empty string placeholders
Line 1: Line 1:
 +//Это руководство доступно также на следующих языках://​
 +[[gnetlist_scheme_tutorial|English]]
 +
 ====== Написание скриптов драйверов gnetlist на Scheme ====== ====== Написание скриптов драйверов gnetlist на Scheme ======
  
Line 11: Line 14:
 Если ты никогда не писал программы на **Lisp**, это выглядит страшновато. Но Если ты никогда не писал программы на **Lisp**, это выглядит страшновато. Но
 это намного легче, чем кажется. Добавь в **Lisp** чуть-чуть синтаксического это намного легче, чем кажется. Добавь в **Lisp** чуть-чуть синтаксического
-сахара(("Синтаксический сахар" ​--- конструкция языка программирования,​ +сахара((«Синтаксический сахар» --- конструкция языка программирования,​ 
-полностью эквивалентная другой его конструкции,​ но имеющая более естественную +полностью эквивалентная другой его конструкции,​ но имеющая более 
-запись (Компьютерный словарь). --- //Прим. перев.//​)) и он превращается в +естественную запись (Компьютерный словарь). --- //Прим. перев.//​)) и он 
-**Logo**, который могут изучить даже дети из начальной школы.+превращается в **Logo**, который могут изучить даже дети из начальной школы.
  
 И просто для объяснения значения некоторых из этих странных слов: И просто для объяснения значения некоторых из этих странных слов:
 [[wp>​Lisp_(programming_language)|Lisp]] --- компьютерный язык, [[wp>​Lisp_(programming_language)|Lisp]] --- компьютерный язык,
-[[wp>​Scheme_(programming_language)|Scheme]] --- диалект **Lisp**'​а,​ +[[wp>​Scheme_(programming_language)|Scheme]] --- диалект **Lisp**'​а,​ и 
-и [[wp>​GNU_Guile|Guile]] --- реализация **Scheme**. +[[wp>​GNU_Guile|Guile]] --- реализация **Scheme**. ​ **Guile** в gEDA 
-**Guile** в gEDA используется для написания скриптов. В частности,​ +используется для написания скриптов. В частности,​ оболочка **gnetlist**,​ 
-оболочка **gnetlist**,​ написанная на **C**, выделяет из схем информацию о +написанная на **C**, выделяет из схем информацию о топологии и атрибутах,​ а 
-топологии и атрибутах,​ а затем отдаёт данные низкоуровневым скриптам +затем отдаёт данные низкоуровневым скриптам (драйверам) на **Guile** для 
-(драйверам) на **Guile** для обработки и вывода.+обработки и вывода.
  
-Это руководство именно по программированию драйверов +Это руководство именно по программированию драйверов **gnetlist** на 
-**gnetlist** на **Scheme**. Если ты ещё не знаешь **Scheme**, тебе, наверно,​ +**Scheme**. Если ты ещё не знаешь **Scheme**, тебе, наверно,​ стоит взглянуть 
-стоит взглянуть и на другие материалы,​ такие как:+и на другие материалы,​ такие как:
  
 http://​www.ccs.neu.edu/​home/​dorai/​t-y-scheme/​t-y-scheme.html http://​www.ccs.neu.edu/​home/​dorai/​t-y-scheme/​t-y-scheme.html
  
-Или поищи ​"Учебник по Scheme" ​в своём любимом поисковике:​ их много.+Или поищи ​«Учебник по Scheme» ​в своём любимом поисковике:​ их много.
  
 Также может пригодиться справочный документ по адресу:​ Также может пригодиться справочный документ по адресу:​
Line 37: Line 40:
 http://​www.gnu.org/​software/​guile/​manual/​html_node/​index.html http://​www.gnu.org/​software/​guile/​manual/​html_node/​index.html
  
 +%%%%
  
 Итак, начнём. Вот очень простой драйвер:​ Итак, начнём. Вот очень простой драйвер:​
-<​code ​scheme>+ 
 +<​code ​lisp>
 ;; gnetlist development playground ;; gnetlist development playground
  
Line 50: Line 55:
 </​code>​ </​code>​
  
-Чтобы это применить,​ сохрани всё в файле //''​gnet-devel.scm''//​. Скопируй этот +Чтобы это применить,​ сохрани всё в файле //''​gnet-devel.scm''//​. Скопируй 
-файл туда, где в твоей системе хранятся файлы **Scheme**. На машине,​ на+этот файл туда, где в твоей системе хранятся файлы **Scheme**. На машине,​ на
 которой я сейчас работаю,​ команда такова:​ которой я сейчас работаю,​ команда такова:​
 +
 <code bash> <code bash>
 $ sudo cp gnet-devel.scm /​sw/​share/​gEDA/​scheme/​ $ sudo cp gnet-devel.scm /​sw/​share/​gEDA/​scheme/​
 </​code>​ </​code>​
  
-//''/​sw/''//​ для многих устанавливаемых в Linux пакетов надо +//''/​sw/''//​ для многих устанавливаемых в Linux пакетов надо заменить на 
-заменить на //''/​usr/''//,​ может быть на //''/​usr/​local''//,​ или --- при +//''/​usr/''//,​ может быть на //''/​usr/​local''//,​ или --- при установке из 
-установке из tar-архива --- на //''​~/​mygeda/''//​. Это нужно выяснить. Если ты +tar-архива --- на //''​~/​mygeda/''//​. Это нужно выяснить. Если ты можешь 
-можешь записывать в целевой каталог без прав суперпользователя,​ **''​sudo''​** +записывать в целевой каталог без прав суперпользователя,​ **''​sudo''​** не 
-не нужно.+нужно.
  
 Теперь,​ изменив нужным образом //''/​sw/''//,​ набери:​ Теперь,​ изменив нужным образом //''/​sw/''//,​ набери:​
Line 68: Line 74:
 </​code>​ </​code>​
  
-Ты должен увидеть обычный текст стандартного приглашения,​ за которым следует:​+%%%% 
 + 
 +Ты должен увидеть обычный текст стандартного приглашения,​ за которым 
 +следует:​ 
 <​code>​ <​code>​
 guile> guile>
Line 74: Line 84:
  
 Попробуй:​ Попробуй:​
 +
 <​code>​ <​code>​
 guile> packages guile> packages
Line 79: Line 90:
  
 Ты должен увидеть:​ Ты должен увидеть:​
-<​code ​scheme>+<​code ​lisp>
 ("​Q3"​ "​R5"​ "​Q2"​ "​R4"​ "​Q1"​ "​C6"​ "​R3"​ "​L2"​ "​A1"​ "​bat(+3v)"​ "​lamp(1)"​ "​R2"​ "​C5"​ "​L1"​ "​R1"​ "​C4"​ "​lamp(2)"​ "​C3"​ "​C2"​ "​C1"​ "​D1"​ "​bat(0v)"​ "​R7"​ "​Q4"​ "​R6"​) ("​Q3"​ "​R5"​ "​Q2"​ "​R4"​ "​Q1"​ "​C6"​ "​R3"​ "​L2"​ "​A1"​ "​bat(+3v)"​ "​lamp(1)"​ "​R2"​ "​C5"​ "​L1"​ "​R1"​ "​C4"​ "​lamp(2)"​ "​C3"​ "​C2"​ "​C1"​ "​D1"​ "​bat(0v)"​ "​R7"​ "​Q4"​ "​R6"​)
 </​code>​ </​code>​
 +
 +%%%%
  
 ''​packages''​ --- удобная переменная,​ содержащая список всех уникальных ''​packages''​ --- удобная переменная,​ содержащая список всех уникальных
-значений атрибутов ''​refdes=''​. Набрав её, ты скормил её "​REPL" ​--- циклу +значений атрибутов ''​refdes=''​. Набрав её, ты скормил её «REPL» ​--- циклу 
-чтения,​ оценки,​ вывода (Read, Evaluate, Print Loop). Итак, +чтения,​ оценки,​ вывода (Read, Evaluate, Print Loop). ​ Итак, REPL считал её, 
-REPL считал её, оценил (создав список) и вывел.+оценил (создав список) и вывел.
  
 Теперь попробуй:​ Теперь попробуй:​
 +
 <​code>​ <​code>​
 guile> (length packages) guile> (length packages)
Line 95: Line 109:
  
 Что здесь произошло?​ Здесь REPL оценил список. Что здесь произошло?​ Здесь REPL оценил список.
-<​code ​scheme>+ 
 +<​code ​lisp>
 (length packages) (length packages)
 </​code>​ </​code>​
Line 103: Line 118:
 функция,​ которая сообщит тебе длину списка. функция,​ которая сообщит тебе длину списка.
  
-Такая же запись используется для арифметических вычислений. Например, ​"2+3"+Такая же запись используется для арифметических вычислений. Например, ​«2+
 вычисляется так: вычисляется так:
 +
 <​code>​ <​code>​
 guile> (+ 2 3) guile> (+ 2 3)
Line 112: Line 128:
 Учти, что процедура %%"​+"​%% может использоваться для сложения любого Учти, что процедура %%"​+"​%% может использоваться для сложения любого
 количества величин,​ в том числе и совсем ни одной: количества величин,​ в том числе и совсем ни одной:
 +
 <​code>​ <​code>​
 guile> (+) guile> (+)
Line 121: Line 138:
 Это мы используем позже. Это мы используем позже.
  
-Строки про ''​readline''​ в нашем драйвере //''​gnet-devel.scm''//​ позволят тебе +Строки про ''​readline''​ в нашем драйвере //''​gnet-devel.scm''//​ позволят 
-пользоваться стрелками на клавиатуре для перемещения по истории и для +тебе пользоваться стрелками на клавиатуре для перемещения по истории и для 
-редактирования вводимых строк. Очень удобно в интерактивном режиме. Попробуй.+редактирования вводимых строк. Очень удобно в интерактивном 
 +режиме. Попробуй.
  
 Другая полезная переменная,​ определённая в **gnetlist**,​ это Другая полезная переменная,​ определённая в **gnetlist**,​ это
Line 131: Line 149:
  
 Ещё есть ''​all-pins'':​ Ещё есть ''​all-pins'':​
 +
 <​code>​ <​code>​
 guile> all-pins guile> all-pins
Line 136: Line 155:
 </​code>​ </​code>​
  
-Заметь,​ это немного сложнее,​ чем в предыдущих примерах:​ это список списков, ​а +Заметь,​ это немного сложнее,​ чем в предыдущих примерах:​ это список списков,​ 
-не просто список строк. Каждый из списков соответствует выводам компонента. +а не просто список строк. Каждый из списков соответствует выводам 
-Есть одна штука, которую мы могли бы вытащить отсюда,​ --- это подсчёт +компонента. ​ Есть одна штука, которую мы могли бы вытащить отсюда,​ --- это 
-количества выводов. Мы не можем просто взять длину ''​all-pins'',​ чтобы +подсчёт количества выводов. Мы не можем просто взять длину ''​all-pins'',​ 
-получить его: это даст нам только количество списков,​ содержащихся там, равное +чтобы получить его: это даст нам только количество списков,​ содержащихся 
-количеству компонентов:​+там, равное количеству компонентов:​ 
 <​code>​ <​code>​
 guile> (length all-pins) guile> (length all-pins)
Line 149: Line 169:
 Чтобы посчитать количество выводов,​ сначала посчитаем их количество для Чтобы посчитать количество выводов,​ сначала посчитаем их количество для
 каждого из компонентов в отдельности:​ каждого из компонентов в отдельности:​
 +
 <​code>​ <​code>​
 guile> (map length all-pins) guile> (map length all-pins)
Line 154: Line 175:
 </​code>​ </​code>​
  
-Это один из простых способов сделать ​"цикл" ​на **Scheme**; ''​(map p x)''​+Это один из простых способов сделать ​«цикл» на **Scheme**; ''​(map p x)''​
 выдаёт список результатов вызываемой процедуры ''​p''​ отдельно для каждого выдаёт список результатов вызываемой процедуры ''​p''​ отдельно для каждого
-элемента из ''​x''​. Затем мы можем их сложить с помощью ​"цикла" ​несколько иного +элемента из ''​x''​. Затем мы можем их сложить с помощью ​«цикла» несколько 
-типа:+иного типа: 
 <​code>​ <​code>​
 guile> (apply + (map length all-pins)) guile> (apply + (map length all-pins))
Line 166: Line 188:
 элементов из ''​x''​. Поэтому вышеуказанное выражение в конце концов посчитает элементов из ''​x''​. Поэтому вышеуказанное выражение в конце концов посчитает
 следующее:​ следующее:​
-<​code ​scheme>+ 
 +<​code ​lisp>
 (+ 3 3 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 3 3 1 2 3 2 1 1) (+ 3 3 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 3 3 1 2 3 2 1 1)
 </​code>​ </​code>​
Line 172: Line 195:
 До сих пор мы использовали предопределённые переменные и процедуры. Но мы бы До сих пор мы использовали предопределённые переменные и процедуры. Но мы бы
 хотели иметь возможность определять свои. Это просто:​ хотели иметь возможность определять свои. Это просто:​
 +
 <​code>​ <​code>​
 guile> (define the-answer 42) guile> (define the-answer 42)
Line 181: Line 205:
  
 Можно также определять процедуры:​ Можно также определять процедуры:​
 +
 <​code>​ <​code>​
 guile> (define add1 (lambda (x) (+ x 1))) guile> (define add1 (lambda (x) (+ x 1)))
Line 187: Line 212:
 </​code>​ </​code>​
  
-Когда видишь ''​lambda'',​ думай --- "процедура". Сразу следом за ''​lambda''​ идёт +Когда видишь ''​lambda'',​ думай --- «процедура». Сразу следом за ''​lambda''​ 
-первый элемент (технический термин --- "выражение"((Англоязычный термин --- +идёт первый элемент (технический термин --- «выражение»((Англоязычный термин 
-"​form"​. --- //Прим. перев.//​))) --- список аргументов процедуры,​ в данном случае +--- «form». --- //Прим. перев.//​))) --- список аргументов процедуры,​ в 
-''​(x)''​. Когда вызывается процедура,​ **Guile** оценивает оставшиеся выражения,​ +данном случае ''​(x)''​. Когда вызывается процедура,​ **Guile** оценивает 
-в данном случае только одно, ''​(+ x 1)'',​ с подстановкой текущих аргументов. +оставшиеся выражения,​ в данном случае только одно, ''​(+ x 1)'',​ с 
-Результат процедуры --- это результат оценки последнего выражения. Так, +подстановкой текущих аргументов. ​ Результат процедуры --- это результат 
-''​(add1 100)''​ становится ''​(+ 100 1)'',​ что даёт 101.+оценки последнего выражения. Так, ''​(add1 100)''​ становится ''​(+ 100 1)'',​ 
 +что даёт 101. 
 + 
 +Теперь мы можем объединить наш сбор статистики в драйвер. Сначала определим 
 +процедуру для записи выходной строки:​
  
-Теперь мы можем объединить наш сбор статистики в драйвер. +<​code ​lisp>
-Сначала определим процедуру для записи выходной строки:​ +
-<​code ​scheme>+
 (define format-line (define format-line
      ​(lambda (name value)      ​(lambda (name value)
Line 207: Line 234:
 </​code>​ </​code>​
  
-Здесь мы используем две новых встроенных процедуры,​ ''​display''​ и ''​newline'',​ +Здесь мы используем две новых встроенных процедуры,​ ''​display''​ и 
-названия которых говорят сами за себя. Теперь:​ +''​newline'',​ названия которых говорят сами за себя. Теперь:​ 
-<​code ​scheme>+ 
 +<​code ​lisp>
 (define display-stats (define display-stats
      ​(lambda ()                  ; без аргументов      ​(lambda ()                  ; без аргументов
Line 226: Line 254:
 </​code>​ </​code>​
  
-Чтобы завершить драйвер,​ нам нужна ​"основная программа". По соглашению она +Чтобы завершить драйвер,​ нам нужна ​«основная программа». По соглашению она 
-называется так же, как и сам драйвер. Также она отвечает за открывание выходного файла. +называется так же, как и сам драйвер. Также она отвечает за открывание 
-Итак, целиком файл драйвера сбора статистики ​"​stats" ​будет выглядеть +выходного файла. ​ Итак, целиком файл драйвера сбора статистики ​«stats» ​будет 
-примерно так: +выглядеть примерно так: 
-<​code ​scheme>+ 
 +<​code ​lisp>
 ;; драйвер gnetlist для получения статистики по проекту ;; драйвер gnetlist для получения статистики по проекту
 ;; ;;
Line 272: Line 301:
 //''​output.net''//​). //''​output.net''//​).
  
-Довольно просто,​ а? А также полезно. Недавно я проектировал системы,​ состоящие +Довольно просто,​ а? А также полезно. Недавно я проектировал системы,​ 
-из множества плат: статистика,​ подобная этой, помогает мне выяснить,​ какие +состоящие из множества плат: статистика,​ подобная этой, помогает мне 
-подсистемы лучше скомбинировать на каждой из плат.+выяснить,​ какие подсистемы лучше скомбинировать на каждой из плат.
  
geda/gnetlist_scheme_tutorial.ru.txt · Last modified: 2015/08/25 07:41 by vzh