Tcl (произносится как « щекотать » или как инициализм [8] ) — это интерпретируемый динамический язык программирования высокого уровня общего назначения . Он был разработан с целью сделать его очень простым, но мощным. [9] Tcl приводит все в форму команды , даже такие программные конструкции, как назначение переменных и определение процедур. [10] Tcl поддерживает несколько парадигм программирования , включая объектно-ориентированный , императивный , функциональный и процедурный стили.
Он обычно используется в приложениях на языке C [11] для быстрого прототипирования , написания сценариев, графических интерфейсов и тестирования. [12] Интерпретаторы Tcl доступны для многих операционных систем , что позволяет коду Tcl работать в самых разных системах. Поскольку Tcl — очень компактный язык, он используется на платформах встраиваемых систем как в полной форме, так и в нескольких других небольших версиях. [13]
Популярная комбинация Tcl с расширением Tk называется Tcl/Tk (произносится «tickle teak» или инициализм ) и позволяет создавать графический интерфейс пользователя (GUI) непосредственно на Tcl. Tcl/Tk включен в стандартную установку Python в виде Tkinter .
Язык программирования Tcl был создан весной 1988 года Джоном Оустерхаутом, когда он работал в Калифорнийском университете в Беркли . [14] [15] Первоначально «рожденные из-за разочарования», [11] по словам автора, когда программисты разрабатывали свои собственные языки для расширения программного обеспечения для автоматизации электронного проектирования (EDA) и, более конкретно, инструмента проектирования СБИС Magic , который был профессиональный фокус Джона в то время. [16] Позже Tcl получил признание сам по себе. Оустерхаут был награжден премией ACM Software System Award в 1997 году за Tcl/Tk. [17]
Название первоначально происходит от языка Tool Command , но обычно пишется Tcl , а не TCL . [18]
Конференции и семинары Tcl проводятся как в США, так и в Европе. [28]
Возможности Tcl включают в себя
uplevel
позволяет upvar
процедурам взаимодействовать с областями охватывающих функций.Safe-Tcl — это подмножество Tcl, которое имеет ограниченные функции, поэтому сценарии Tcl не могут нанести вред хост-компьютеру или приложению. [31] Доступ к файловой системе ограничен, а выполнение произвольных системных команд запрещено. Он использует модель двойного интерпретатора, при которой ненадежный интерпретатор выполняет код в ненадежном сценарии. Он был разработан Натаниэлем Боренштейном и Маршаллом Роузом для включения активных сообщений в электронную почту. Safe-Tcl можно включать в электронную почту, если поддерживаются application/safe-tcl и multipart/enabled-mail . С тех пор функциональность Safe-Tcl была включена в стандартные выпуски Tcl/Tk. [32] [33]
Синтаксис и семантика Tcl описаны двенадцатью правилами [34], известными как Додекалог. [35]
Сценарий Tcl состоит из серии вызовов команд. Вызов команды представляет собой список слов, разделенных пробелами и заканчивающихся новой строкой или точкой с запятой. Первое слово — это имя команды, которая может быть встроена в язык, найдена в доступной библиотеке или определена в самом скрипте. Следующие слова служат аргументами команды:
Имя команды Аргумент1 Аргумент2 ... АргументN
В следующем примере используется команда puts (сокращение от «put string») для отображения текстовой строки на консоли хоста:
ставит «Привет, Мир!»
При этом отправляется строка «Hello, World!» на стандартное устройство вывода вместе с добавленным символом новой строки.
Переменные и результаты других команд можно заменить строками, как в этом примере, где используются команды set и expr для сохранения результата вычисления в переменной (обратите внимание, что Tcl не использует его =
в качестве оператора присваивания), а затем использует puts для печати результата вместе с пояснительным текстом:
# expr оценивает текстовую строку как набор выражений sum [expr 1 + 2 + 3 + 4 + 5 ] помещает «Сумма чисел 1..5 равна $sum».
Персонаж #
вводит комментарий . Комментарии могут появляться везде, где интерпретатор ожидает имя команды.
# с фигурными скобками замена переменных выполняется выражением set x 1 set sum [expr { $x + 2 + 3 + 4 + 5 }]; # $x не заменяется перед передачей параметра в expr; # expr заменяет $x на 1, а при вычислении выражения получается : «Сумма чисел 1..5 равна $sum». ; # сумма равна 15
# без фигурных скобок подстановка переменных происходит на сайте определения (лексическая область видимости) set x 2 set op * set y 3 set res [expr $x$op$y ]; # $x, $op и $y заменяются, и выражение оценивается как 6, что означает «$x $op $y is $res». ; # $x, $op, $y и $res заменяются и оцениваются как строки
Как видно из этих примеров, в языке есть одна основная конструкция: команда. Механизмы кавычек и правила замены определяют, как обрабатываются аргументы каждой команды.
Перед анализом любых команд или аргументов происходит одна специальная замена . Если последний символ в строке (т. е. непосредственно перед новой строкой) представляет собой обратную косую черту, то комбинация обратной косой черты и новой строки (а также любые пробелы или табуляции, следующие сразу за новой строкой) заменяются одним пробелом. Это обеспечивает механизм продолжения строки , благодаря которому длинные строки исходного кода могут переноситься на следующую строку для удобства читателей.
Продолжая обычную обработку аргументов, слово, начинающееся с символа двойной кавычки ( "
), расширяется до следующего символа двойной кавычки. Таким образом, такое слово может содержать пробелы и точки с запятой, при этом эти символы не интерпретируются как имеющие какое-либо особое значение (т. е. они рассматриваются как обычные текстовые символы). Слово, начинающееся с открывающей фигурной скобки ( {
), продолжается до следующего символа закрывающей фигурной скобки ( }
). Внутри фигурных скобок подавляются все формы замены, за исключением ранее упомянутого исключения обратной косой черты и новой строки. Слова, не заключенные ни в одну из конструкций, называются голыми словами.
В словах без кавычек и в двойных кавычках могут встречаться три типа замены:
[expr 1+2+3]
заменяется результатом вычисления содержащегося выражения (в данном случае 6).$foo
заменяется содержимым переменной с именем «foo». Имя переменной может быть заключено в фигурные скобки, чтобы отделить его от последующего текста в неоднозначных случаях (например, ${foo}ing
).\n
заменяется новой строкой.Замена происходит слева направо за одно сканирование каждого слова. Любой замененный текст не будет повторно сканироваться на предмет возможных дальнейших замен. Однако в одном слове может встречаться любое количество замен.
Начиная с Tcl 8.5, любое слово может иметь префикс {*}
, что приводит к разбиению слова на составляющие его подслова для целей построения вызова команды (аналогично последовательности ,@
функции квазицитирования в Лиспе ).
Как следствие этих правил, результат любой команды может использоваться в качестве аргумента для любой другой команды. Обратите внимание, что, в отличие от командных оболочек Unix , Tcl не анализирует повторно никакую строку, если это явно не указано, что делает интерактивное использование более громоздким, а использование сценариев более предсказуемым (например, наличие пробелов в именах файлов не вызывает затруднений).
Единственный знак равенства ( =
) вообще не играет особой роли в языке. Знак двойного равенства ( ==
) — это проверка на равенство, которая используется в контекстах выражений, таких как expr
команда и в первом аргументе if
. (Обе команды являются частью стандартной библиотеки; специального места в ней они не имеют и при желании могут быть заменены.)
Большинство команд Tcl, особенно в стандартной библиотеке, являются переменными , а proc
(конструктор для скриптовых командных процедур) позволяет определять значения по умолчанию для неуказанных аргументов и универсальный аргумент, позволяющий коду обрабатывать произвольное количество аргументов. .
Tcl не является статически типизированным: каждая переменная может содержать целые числа, числа с плавающей запятой, строки, списки, имена команд, словари или любые другие значения; значения переинтерпретируются (с учетом синтаксических ограничений) как другие типы по требованию. Однако значения неизменяемы , и операции, которые их изменяют, на самом деле вместо этого просто возвращают новое значение.
Наиболее важные команды, относящиеся к выполнению программы и операциям с данными:
set
записывает новое значение в переменную (создает переменную, если она не существует). Если используется только с одним аргументом, он возвращает значение данной переменной (в этом случае она должна существовать).proc
определяет новую команду, выполнение которой приводит к выполнению заданного сценария Tcl, записанного как набор команд. return
может использоваться для немедленного возврата управления вызывающему объекту.Обычные команды управления выполнением:
if
выполняет заданное тело скрипта (второй аргумент), если условие (первый аргумент) удовлетворено. За ним могут следовать дополнительные аргументы, начиная с elseif
альтернативного условия и тела или else
с дополнительного блока.while
повторяет выполнение данного тела скрипта, пока условие (первый аргумент) остается удовлетвореннымforeach
выполняет заданное тело, в котором управляющей переменной присваиваются элементы списка один за другим.for
ярлык для инициализации управляющей переменной, условия (как в while
) и дополнительного оператора «следующая итерация» (команда, выполняемая после выполнения тела)Вышеупомянутыми командами цикла можно дополнительно управлять с помощью следующих команд:
break
прерывает выполнение тела и возвращается из команды циклаcontinue
прерывает выполнение тела, но управление по-прежнему возвращается команде цикла. Ибо while
это означает повторный цикл, for for
и foreach
переход к следующей итерации.return
прерывает выполнение текущего тела независимо от глубины процедуры, пока не достигнет границы процедуры, и возвращает заданное значение вызывающей стороне.expr
передает аргумент отдельному интерпретатору выражений и возвращает вычисленное значение. Обратите внимание, что тот же интерпретатор используется также для «условных» выражений if
и команд цикла.list
создает список , содержащий все аргументы, или пустую строку, если аргумент не указан. Эту lindex
команду можно использовать для результата для повторного извлечения исходных аргументов.array
манипулирует переменными массива .dict
манипулирует словарем (начиная с версии 8.5), который представляет собой списки с четным числом элементов, где каждые два элемента интерпретируются как пара ключ/значение.regexp
сопоставляет регулярное выражение со строкой.regsub
Выполняет замены на основе сопоставления шаблонов регулярных выражений.uplevel
— это команда , которая позволяет выполнять командный сценарий в области , отличной от текущей самой внутренней области стека.upvar
создает ссылку на переменную в другом фрейме стека.namespace
позволяет создавать, получать доступ и уничтожать отдельные контексты для команд и переменных.apply
применяет анонимную функцию (начиная с версии 8.5).coroutine
, yield
, а также yieldto
создавать значения из сопрограмм (начиная с версии 8.6).try
позволяет перехватывать и обрабатывать ошибки и исключения.catch
позволяет получать исключительную прибыль.zlib
обеспечивает доступ к средствам сжатия и контрольных сумм библиотеки Zlib (начиная с версии 8.6).uplevel
позволяет выполнять командный сценарий в области , отличной от текущей внутренней области стека. Поскольку командный сценарий сам может вызывать процедуры, использующие команду повышения уровня , в конечном итоге это преобразует стек вызовов в дерево вызовов. [36]
Первоначально он был реализован, чтобы позволить процедурам Tcl переопределять встроенные команды (например , for , if или while ) и при этом иметь возможность манипулировать локальными переменными . Например, следующий сценарий Tcl представляет собой повторную реализацию команды for (без обработки исключений ):
proc for { initCmd testExpr заранееCmd bodyScript } { повышение уровня 1 $initCmd set testCmd [ list expr $testExpr ] while {[uplevel 1 $testCmd ]} { повышение уровня 1 $bodyScript повышение уровня 1 $advanceCmd } }
upvar
предписывает одной или нескольким локальным переменным в текущей процедуре ссылаться на переменные во включающем вызове процедуры или на глобальные переменные . Команда upvar упрощает реализацию вызова процедур по имени, а также упрощает создание новых управляющих конструкций в виде процедур Tcl. [37]
Команда decr, которая работает как встроенная incr
команда, за исключением того, что она вычитает значение из переменной, а не добавляет его:
proc decr { varName { decrement 1 }} { upvar 1 $varName var incr var [expr { -$decrement }] }
В 2012 году в Tcl 8.6 добавлена встроенная система динамических объектов TclOO. [29] Она включает в себя такие функции, как:
oo :: class createfruit { метод eat {} { ставит "вкуснятина! " } } oo :: class create Banan { конструктор суперкласса Fruit {} { моя переменная очищенный набор очищен 0 } метод кожура {} { моя переменная очищенный набор очищен 1 ставит "кожу теперь снимают" } метод съедобен ? {} { моя очищенная переменная return $peeled } метод eat {} { if { ! [ моё съедобное ? ]} { моя кожура } далее } } set b [ банан новый ] $b eat → печатает «кожа теперь снята» и «вкусно!» Fruit уничтожить $b eat → ошибка «неизвестная команда»
В Tcl не было объектно-ориентированного (ОО) синтаксиса до 2012 года [29] , поэтому появились различные пакеты расширений, позволяющие реализовать объектно-ориентированное программирование. Они широко распространены в существующем исходном коде Tcl. Популярные расширения включают в себя:
TclOO был добавлен не только для создания мощной объектно-ориентированной системы, но и для того, чтобы пакеты расширений могли создавать объектно-ориентированные абстракции, используя его в качестве основы. После выпуска TclOO incr Tcl был обновлен и теперь использует TclOO в качестве основы. [27]
Веб-сервер Tcl — это реализация сервера протокола HTTP на чистом Tcl. Он работает как скрипт поверх стандартного интерпретатора Tcl.
Apache Rivet — это система программирования с открытым исходным кодом для HTTP-сервера Apache , которая позволяет разработчикам использовать Tcl в качестве языка сценариев для создания динамических веб-приложений. Rivet похож на PHP , ASP и JSP . Rivet был первоначально разработан Дэймоном Кортни, Дэвидом Велтоном, Массимо Манги, Харальдом Ольманном и Карлом Лехенбауэром . Rivet может использовать любой из тысяч общедоступных пакетов Tcl, которые предлагают бесчисленное количество функций, таких как взаимодействие с базами данных (Oracle, PostgreSQL, MySQL, SQLite и т. д.) или интерфейсы с популярными приложениями, такими как GD Graphics Library .
Tcl изначально взаимодействует с языком C. [38] Это связано с тем, что изначально он был написан как основа для предоставления синтаксического интерфейса для команд, написанных на C, и все команды на языке (включая вещи, которые в противном случае могли бы быть ключевыми словами , например if
или while
) реализованы таким образом. . Каждой функции реализации команды передается массив значений, описывающих (уже замененные) аргументы команды, и она может интерпретировать эти значения по своему усмотрению.
Симуляторы цифровой логики часто включают в себя интерфейс сценариев Tcl для моделирования аппаратных языков Verilog , VHDL и SystemVerilog .
Существуют инструменты (например, SWIG , Ffidl) для автоматической генерации необходимого кода для соединения произвольных функций C и среды выполнения Tcl, а Critcl делает обратное, позволяя встраивать произвольный код C внутрь сценария Tcl и компилировать его во время выполнения в DLL .
Язык Tcl всегда позволял использовать пакеты расширений, которые предоставляют дополнительные функции, такие как графический интерфейс, автоматизация приложений на основе терминала, доступ к базе данных и т. д. Часто используемые расширения включают в себя: