Fingy

Оглавление

Модули

Система включает в себя следующие модули:

LangCore

LangCore представляет из себя инфрастукруру для выполнения Fingy-кода. Основа LC - Объекты Interpreter. Создав объект Interpreter, можно:

  • Загрузить в него текст Fingy-программы. При этом программа пройдет синтаксический анализ и предкомпиляцию. Ранее загруженная программа теряется.
  • Выполнить загруженную ранее Fingy-программу.
  • Получить список breakpoint'ов. Устанвовить/удалить breakpoint'ы.
  • Подгрузить в Interpreter модули (string, io, и т.п.)
  • Зарегистрировать функции (указав имя функции и callback-объект)
  • Получить/установить глобальные/локальные переменные.

Регистрация функций

Каждая функция должна представлять из себя объект, который реализует специальный интерфейс (похожий на Runnable). Например:

class TurtleForward implements FingyFunction {
    FingyVar invoke(Interpreter ipt, FingyVar vars[]) {
        // ipt - объект текущего контекста выполнения
        // позволяет получить значения глобальных переменных и т.п.

        ipt.checkVars(vars, 1);  // проверяем, что длинна массива = 1
        double distance = ipt.getFloat(vars[0]);

        // моделирование движеня "черепашки"

        return null;
    }
}

После этого данную функцию можно зарегистрировать в интерпретаторе. При вызове функции из Fingy-скрипта интерпретатор просто вызывает соответсвующий метод invoke соответсвующего объекта FingyFunction.

Альтернативы:

  • Использование рефлексии.
  • Использование единого метода диспетчеризации, с передачей в качестве параметра имени функции, которую мы ходим передать.

Выполнение программы

Объект Interpreter позволяет выполнить загруженный Fingy-скрипт. Для этого он предоставляет несколько методов (выполнить весь скрипт, одну команду и т.п.)

Первоначально необходимо создать объект Runner. Команды для выполнения передаются непосредственно Runner'у. Объект Runner служит для хранения локальных переменных, стека вызова функций, хранения номера текущей строки, на которой происходит выполнение.

Если при выполнении скрипта вызывается функция расширения, то просто вызывается соответсвующий java-метод объекта FingyFuncion. Данный метод может иметь побочные эффекты, например может нарисовать линию на канве. Interpreter не несет ответственности за организацю анимации, плавного выполнения и подобных вещей.

Отладка

Скрипт можно выполнять в 2х режимах:

  1. Выполнять до тех пор, пока не встретится breakpoint
  2. Выполнить одну команду (строку)

Если скрипт не завершил свое выполнение, то можно возобновить его выполнение, вызвав соответсвующий метод Runner'а. Также Runner предоставляет доступ к локальным и глобальным переменным. Пример использования:

Runnter run = ipt.createRunner();
run.executeOneLine();
system.out.println(run.getGlobal("var1").toString());
run.setGlobal(new FingyVarInt(123));
run.executeOneLine();
system.out.println(run.getGlobal("var1").toString());
run.executeAll();
system.out.println(run.getGlobal("var1").toString());

GameEnv

Игровое окружение представляет из себя объект, принимающий команды от Fingy-скрипта и отрисовывающий некую информацию на канве.

Исходные данные скрипта должны храниться в XML(?). GE загружает исходные данные из потока XML. Затем регистрирует набор фунций в объекте Interpreter (объявляя для нужных функций объекты FingyFunction).

Отрисовку игрового поля GE должен вести на любом объекте, который наследуется от java.awt.Component (например на JPanel). Объект создается самим GE. Данный объект DevEnv может встроить в интерфейс. При отрисовке GE может выполнять анимацию (а может и не выполнять, кто их знает, этих GE).

Important

Выполнение Fingy-скрипта выполняется в отдельном потоке, в этом же потоке будут выполняться зарегистрированные в Interpreter функции!

GE должен поддерживать функцию "перезагрузить начальное сотояние" (без перечитывания XML файла).

DevEnv

Среда ответственна за выполнение следующих функций:

  • Загрузка/сохранение тектса скрипта из/в файла.

  • Редактирование скрипта (с подсветкой синтаксиса?)

  • Выполнение/отладка скрипта
    • Загрузка и инициализация CL
    • Загрузка и инициалицация GE
    • Остановка (приостановка) скрипта

Выполнение скрипта

Первым делом DE должен инициализировать LangCore. Для этого он создает объект Interpreter. Затем загружается файл с данными обстановки GE (формат файла XML?). Из содержимого файла определяется тип GE, создается соответствующий объект. После этого DE связывает Interpreter c GE-объектом. Канва GE встраивается в интерфейс (в отдельное окошко либо в панель).

Также DE должен предоставить Interpreter'у 2 callback'a:

  • Функция, которая вызывается, когда скрипт делает вывод данных
  • Функция, которая вызывается, когда скрипт делает ввод данных

После этого DE для каждого выполнения скрипта создает объект Runner. Для этого объекта в отдельном потоке(!) вызывается метод execute(). Отдельный поток необходим, поскольку скрипт может зациклиться, или выполняться чрезвычайно долго.

API

Думаемс...

Заключение

Всем здоровьечка и щасцея. Целую, Джей.