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 Both sides next revision
geda:gnetlist_scheme_tutorial.ru [2012/11/21 15:20]
vzh Updated
geda:gnetlist_scheme_tutorial.ru [2014/04/25 05:58]
vzh Updated using po4a
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» ​в своём любимом поисковике:​ их много.
  
 Также может пригодиться справочный документ по адресу:​ Также может пригодиться справочный документ по адресу:​
  
 http://​www.gnu.org/​software/​guile/​manual/​html_node/​index.html http://​www.gnu.org/​software/​guile/​manual/​html_node/​index.html
 +
  
  
 Итак, начнём. Вот очень простой драйвер:​ Итак, начнём. Вот очень простой драйвер:​
 +
 <code lisp> <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 82: Line 93:
 ("​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 lisp> <code lisp>
 (length packages) (length packages)
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 lisp> <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)
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 lisp>
 (define format-line (define format-line
Line 207: Line 234:
 </​code>​ </​code>​
  
-Здесь мы используем две новых встроенных процедуры,​ ''​display''​ и ''​newline'',​ +Здесь мы используем две новых встроенных процедуры,​ ''​display''​ и 
-названия которых говорят сами за себя. Теперь:​+''​newline'',​ названия которых говорят сами за себя. Теперь:​ 
 <code lisp> <code lisp>
 (define display-stats (define display-stats
Line 226: Line 254:
 </​code>​ </​code>​
  
-Чтобы завершить драйвер,​ нам нужна ​"основная программа". По соглашению она +Чтобы завершить драйвер,​ нам нужна ​«основная программа». По соглашению она 
-называется так же, как и сам драйвер. Также она отвечает за открывание выходного файла. +называется так же, как и сам драйвер. Также она отвечает за открывание 
-Итак, целиком файл драйвера сбора статистики ​"​stats" ​будет выглядеть +выходного файла. ​ Итак, целиком файл драйвера сбора статистики ​«stats» ​будет 
-примерно так:+выглядеть примерно так: 
 <code lisp> <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