1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/junruoyu-zheng-ligral

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
node.md 15 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 29.11.2024 02:01 6be31cf

Заявление узлов

Как было сказано ранее, узлы включают модули и маршруты, их заявление, способ использования похожи, поэтому они рассматриваются вместе.

Заявление узла, будь то модуль или маршрут, по сути, создаёт новый экземпляр. Поведение и логика экземпляра определяются его типом. Если вы обновите определение класса (например, обновите расширение пакета модуля или измените код маршрута), все экземпляры будут изменены, что обеспечивает согласованность кода.

Стандартный синтаксис

В отличие от C++ и производных языков, где экземпляр типа обычно создаётся с использованием круглых скобок и параметров, в ligral вы просто ссылаетесь на имя типа, чтобы создать его экземпляр. В следующем примере Step — это источник сигнала шага, а Print — модуль печати, оба требуют необязательных параметров, поэтому можно использовать только имя типа для заявления.

Step -> Print;

Однако при использовании этого метода для создания экземпляра после завершения оператора ligral теряет ссылку на этот экземпляр. То есть экземпляр должен завершить все соединения портов в этом операторе, поскольку вы не можете вызвать его в других операторах. Для более сложных функций необходимо назначить уникальный идентификатор. Синтаксис назначения идентификатора следующий:

Step[src];
src -> Print;

После присвоения идентификатора src первой строке объявляется только один экземпляр Step, который вызывается во второй строке. При необходимости вы также можете вызывать его в других утверждениях для реализации более сложной логики. В Ligral идентификаторы должны быть назначены до использования, независимо от порядка расчёта сигналов. Например, в следующем коде, хотя оператор второй строки будет рассчитан первым, с точки зрения грамматики модуль abs должен быть объявлен в первой строке.

Abs[abs] -> Print;
Step -> abs;

Иногда узлам необходимо передавать некоторые параметры при объявлении, формат передачи параметров аналогичен JSON. После оператора объявления используйте фигурные скобки для заключения всех параметров, разделяя параметры запятыми, каждый параметр должен явно указывать имя параметра и значение (если это необязательный параметр, вы можете опустить его и использовать значение по умолчанию), а имя параметра и значения разделены двоеточием. Например, модуль Step имеет два необязательных параметра start и level, которые определяют время возникновения и уровень сигнала шага. Если уровень остаётся неизменным, время возникновения изменяется на 2 секунды, это должно быть записано следующим образом:

Step{start:2};

Если вам нужно присвоить идентификатор и передать параметры, присвоение идентификатора должно предшествовать передаче параметров.

Step[src]{start:2};

Синтаксический сахар

Модуль Constant

Одна из целей Ligral — уменьшить трудоёмкость моделирования, сделать модели симуляции более краткими, ясными и интуитивными, поэтому он поддерживает множество синтаксических сахаров, делая моделирование более эффективным.

Прежде всего, модуль Constant является источником постоянного сигнала, и у него есть обязательный параметр value, который непрерывно выводит значение во время симуляции. Начиная с версии v0.2.0, value может быть скаляром или матрицей. Например, если вам нужен источник постоянного сигнала со значением 1, вы можете записать следующее:

Constant{value:1};

Но это слишком громоздко, Ligral поддерживает использование констант для ответа на этот модуль, поэтому вы можете упростить его следующим образом:

1 -> Print;

Кроме того, уже определённые константы также могут быть проанализированы и заключены в модуль Constant.

let a = 1;
a -> Print;

Модуль Calculator

Во-вторых, модуль Calculator представляет собой двумерный вычислительный модуль с обязательным параметром type, значение которого может быть +, -, *, /, ^ и другими операторами. Этот модуль принимает два входных данных, вычисляет результат и выводит его. Если ваша модель симуляции равна 1+1, она должна быть записана следующим образом (соединение здесь относительно сложное, см. раздел «Соединение узлов»):

(1, 1) -> Calculator{type:'+'};

Чтобы избежать громоздкости, Ligral напрямую анализирует выражение 1+1 и поддерживает выражения в скобках, порядок вычислений и порядок, упомянутый в разделе «Объявление констант».

1 + 2 * 3 ^ (4 - 3) -> Print; # 7

Из этого примера также видно, что порядок операций этих двумерных операторов выше, чем у операторов соединения. Кроме того, Ligral также поддерживает + и - как одномерные операторы и вызывает модуль Calculator с добавлением 0.

За исключением констант, все узлы с одним выходным портом могут использовать синтаксический сахар Calculator, например, модуль Step.

Step + 1 -> Print;

Модуль Node

Хотя система «заявление — ссылка» уже достаточно мощна для описания сложных моделей симуляции, в некоторых случаях она кажется противоречащей интуиции. Например, в системе первого порядка с низким проходом структура модели следующая:

                  ┌───┐ 
          ┌───────┤ k │◄─────┐
          │       └───┘      │
╭───╮   + ▼-      ┌─────┐x   │
│ r ├───►(x)─────►│ 1/s ├────┘
╰───╯             └─────┘

Здесь r — входной узел, k — постоянный коэффициент усиления. Очевидно, что выход интегратора должен быть перед входом интегратора, поэтому определение интегратора должно быть впереди, код выглядит следующим образом:

r - Integrator[i] * k -> i;

Этот метод написания легко сбивает с толку, поэтому Ligral предоставляет пустой узел Node для замены таких узлов, как Integrator, которые имеют очевидное значение. Узел Node просто пересылает входные данные на выходные, что очень подходит для ссылок. На основе этого Ligral даже позволяет ссылаться на неопределённые узлы Node, но на самом деле Ligral просто анализирует неопределённый символ как узел Node при первом обнаружении. Таким образом, вышеупомянутый код можно дополнительно упростить следующим образом:

r - Node[i] * k -> Integrator -> i;

Хотя код стал длиннее, структура стала более понятной. Исходя из этого, Ligral даже допускает прямую ссылку без определения узла Node, что кажется нарушением принципа «сначала объявить, затем сослаться», упомянутого ранее, но фактически Ligral просто анализирует неопределённое выражение как узел Node при первой встрече. Поэтому вышеупомянутый код может быть дополнительно упрощён следующим образом:

r - i * k -> Integrator -> i;

Кроме того, в некоторых сценариях может потребоваться только объявить узел Node, но не ссылаться на него, вы можете использовать ~ для представления. Это означает, что ~ может появляться в цепочке модулей в любом месте, не влияя на всю программу, например:

1 -> ~ -> Print; # 1

Ссылка на порт

Многие модули имеют несколько входных или выходных портов, если вам нужно указать вызов определённого порта, вы можете указать имя порта через двоеточие. Например, модуль LogicSwitch имеет три входных порта condition, first и second, если вы хотите указать порт condition, вы можете написать следующее:

1 -> LogicSwitch:condition;

В этом случае обычно требуется присвоить ID модулю, иначе другие порты не могут быть подключены. Поведение входного порта аналогично узлу с одним входным и нулевым выходным сигналом, поэтому к входному порту может быть подключён только один сигнал, и сигнал не может быть подключен от входного порта к другим узлам.

Синтаксис указания выходного порта такой же, как и у входного порта, но отличается тем, что поведение выходного порта похоже на узел с несколькими входами и одним выходом, а его входные порты такие же, как у исходного узла. Система не включает многопортовый выходной узел, но однопортовый выходной узел также может использовать ссылку на порт (хотя это кажется немного избыточным). Возьмём в качестве примера узел Gain, у которого есть входной порт input и выходной порт output, при использовании вы можете написать так:

1 -> Gain{value:10}:output -> Print;

Если выходной порт определённого узла должен быть указан в нескольких местах, вы также можете дать ему псевдоним, но этот псевдоним также должен быть уникальным, потому что он эквивалентен присвоению ID или, фактически, Ligral автоматически определяет узел Node для подключения к этому выходному порту и присваивает ему ID. Входной порт обычно не указывается в нескольких местах, потому что входной порт может быть соединён только с одним выходным портом, поэтому псевдоним порта не поддерживает входной порт. Псевдоним узла похож на синтаксис присвоения ID узлу, оба используют квадратные скобки для именования:

1 -> Gain{value:10}:output[x];
x -> Print;

Конечно, согласно предыдущему разделу, вы также можете написать:

1 -> Gain{value:10}:output -> x;
x -> Print;

Тем не менее, между ними всё ещё есть тонкие различия, которые будут подробно описаны в последующих документах.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/junruoyu-zheng-ligral.git
git@api.gitlife.ru:oschina-mirror/junruoyu-zheng-ligral.git
oschina-mirror
junruoyu-zheng-ligral
junruoyu-zheng-ligral
dev