Сообщений 0 Оценка 535 [+0/-1] Оценить |
Исходные тексты
Исполняемый файл
Мой интерпретатор может выполнять текст на JScript.NET прямо по ходу набора. Результаты сразу же распечатываются на экране:
Скорость запуска оптимизирована по максимуму. Несмотря на то, что компилятор JScript довольно тормознутый и при запуске просто из командной строки долго дуплится, для пользователя эти проблемы не видны.
Для удобства использования в программу зашиты многие полезные функции, например все функции класса Math продублированы в сокращённой нотации (Math.Sin -> sin, Math.Sqrt -> sqrt и т.п.) Ещё одна ценная функция, load, читает содержимое файла и пытается распознать некоторые стандартные форматы, возвращая соответствующий объект: Image, DataSet, XmlDocument, string, byte[].
При выводе результатов выполнения строки, тип полученного объекта учитывается и результат форматируется в соответствии:
Особо стоит отметить форматирование функций, показывающее название аргументов. Это служит частичной заменой Intellisense из Visual Studio, тот есть напоминает, какие параметры есть у функций, и что они означают.
Для удобства работы с объектами Windows.Forms интерпретатор выполняет команды в другом потоке, чем чтение с консоли. Поток, выполняющий команды, имеет свою собственную оконную очередь сообщений, поэтому можно одновременно видеть «запущенные» формы и одновременно использовать их: вызывать методы, получать свойства:
Для ещё большего удобства работы со свойствами есть функция show, отображающая окно свойств (PropertyGrid) для указанного объекта. Дополнительно для тех объектов, которые это поддерживают, отображается картинка (PictureBox), таблица (DataGrid) и многострочный TextBox.
При нажатии F4 в окне свойств, открывается новое окно со значением этого свойства. Обычно подобный механизм называют английским термином Drill-Down. По умолчанию окна свойств пытаются разместиться у правого края экрана без перекрытий.
Для упрощения ввода функций и многострочных операторов (например, циклов) интерпретатор производит предварительный парсинг текста перед выполнением. В том случае, если скобки в тексте не закрыты, текст не будет выполняться, а «накапливаться»:
Здесь видно, что текст не начинал выполняться до тех пор, пока как не был сформирован полноценный оператор for.
Так как такой предварительный парсинг не всегда может точно определить, что оператор уже закончился, пользователь может просто нажать Enter не вводя новую строку и накопленный текст будет выполняться независимо от синтаксиса:
И раз уж сам базовый интерпретатор Microsoft JScript.NET предоставляет расширенную информацию об ошибке, такая информация отображается и моим интерпретатором в удобочитаемом виде. В данном случае, мы видим сообщение, что в последней строке явно не хватает текста.
Для выхода из интерпретатора нужно набрать в любой строке слово «exit» или «quit».
Отдельный хитроумный механизм я сделал для возможности вызвать интерпретатор JScript.NET из обычных скриптов JScript (JScript не-.NET, то есть «старый» Windows Scripting Host). В результате можно использовать широчайшие возможности библиотеки .NET Framework в сценариях.
Для того, чтобы сценарий myscript.js выполнялся интерпретатором JScript.NET он должен быть оформлен примерно следующим образом:
var interpreter=new ActiveXObject("Mi.JScript.Interpreter"); if( interpreter.RunManaged() ) managed(); function managed() { show( Int32.Assembly ); alert("Managed!"); } |
В скрипте сначала создаётся COM-объект Mi.JScript.Interpreter и вызывается функция RunManaged. Эта функция напоминает функцию fork из мира Unix. После вызова RunManaged тот же текст скрипта начинает выполняться «в режиме .NET», то есть под интерпретатором JScript.NET. Но «старый поток» выполнения тоже не умирает, поэтому функция RunManaged возвращает логическое значение, флаг, позволяющий отличать, с каким «потоком» выполняется скрипт, с JScript.NET-скриптом или с ActiveX-скриптом.
Реализовано внутри моего объекта это следующим образом. При запуске RunManaged анализируется командная строка текущего процесса. Обычно скрипты JScript выполняются в процессе wscript или cscript (это выполняемые файлы Windows Scripting Host). Функция получает аргумент запуска wscript/cscript, который указывает на файл скрипта, например «myscript.js». Зная имя файла, мой объект загружает его содержимое и запускает выполнение в интерпретаторе Microsoft JScript.NET.
Для того, чтобы этот механизм работал, необходимо зарегистрировать COM-объект Mi.JScript.Interpreter. Я уже об этом позаботился, и нужно только запустить один раз сам интерпретатор, то есть файл jsnet.exe. Сразу же автоматически он устанавливается в GAC, регистрируется как COM-объект и оптимизируется при помощи утилиты ngen.
Тут уместно ещё раз напомнить, что несмотря на все эти операции, моя программа запускается очень быстро. В частности, весь код регистрации для COM выполняется в фоновом потоке с заниженным приоритетом, поэтому для пользователя процесс регистрации как бы невидим.
А для ускорения инициализации внутренних структур интерпретатора Microsoft.JScript используется ещё один временный поток. Пока пользователь думает и набирает первую строчку кода, инициализирующий поток интерпретатора вызывает подсчёт суммы «1+1». К тому моменту, как пользователь первый раз нажимает Enter, интерпретатор уже полностью или частично загружен и обработан JIT-компилятором. Начальная задержка успешно минимизирована.
Ещё стоит упомянуть встроенную реализацию функций ngen, regasm, gacutil для использования прямо из скрипта JScript.NET. Эти функции не обращаются к утилитам .NET SDK, они могут работать на простой клиентской инсталляции .NET Framework. Собственно, одной из целевых задач этой утилиты является административное скриптование: запуск различных действий в зависимости от каких-то условий, выполнение внешних утилит, анализ содержимого каталогов и т.п.
Также незаменимую помощь для скриптования административных задач окажет функция setLog, после вызова которой весь консольный вывод будет дублироваться в файл.
Применяя эту программу для скриптинга и автоматизации, следует помнить, что в данном случае запуск интерпретатора Microsoft JScript.NET ничем не сглажен и в таких условиях тормоза проявляются полностью, в отличие от интерактивного режима. На моей машине начальная задержка по сравнению с запуском простого JScript занимает около 1 сек. Это можно считать ценой тех возможностей, которые появляются с использованием .NET Framework.
Сообщений 0 Оценка 535 [+0/-1] Оценить |