FTS: reading compiler errors
FTS compiler message — not an obstacle, but a result of the check you yourself ordered. The compiler does not guess the intention: it names the code, formulates the discrepancy and, if possible, indicates the location. Further only translation from the diagnostic language to the model language is needed.
Below each diagnostic is presented exactly as the compiler outputs it: code, message verbatim, minimal example, and fix.
How diagnostics is structured
Diagnosis — an object with four fields:
{
"code": "FTS_UTILITY_FIELD",
"message": "unknown utility input field 'стоимость'",
"path": "$.utilities[0].rules[0].when[0].field",
"severity": "error"
}
code is stable and intended for programs: handlers are written based on it in
the editor and in CI. message is intended for a person and can be refined between
versions. severity in the current core is always error: the warning type is declared, but
no check has emitted it yet — the model is either accepted or not.
The error location comes in one of two fields.
span — coordinates in the source text: start.line, start.column and
offsets. It is set by the lexer and bracket parser, that is, the layer that
works with characters.
path — address, not a coordinate. For a natural surface this is a line number
in the form of "строка 12"; for model checking — a JSON path like
"$.utilities[0].examples[0].input.сумма". Such a path leads not to a place in
a file, but to a document node: it works the same for .fts, and for
generated JSON. Diagnostics of the execution stage have no location at all — they
relate to a call, not to text.
Parsing and execution errors throw an exception FtsError with a list
diagnostics. Model checking throws nothing: validate(document)
returns { valid, diagnostics } and collects all remarks at once.
Parsing errors
Stage compile. Until the text is walked through, no semantic checks will be performed.
FTS_EXPECTED_KEYWORD — document is not recognized as a natural surface.
The first significant line must start with the word категория in lower
case and without curly braces; otherwise, the text goes to the old brace parser.
объект Покупка
сумма является деньгами
FTS_EXPECTED_KEYWORD | expected 'category'
span: строка 1, колонка 1
This is the only common diagnostic with span, and its message is in English —
a sign that you have fallen into another parser. Fix: add as the first line
категория «Продажи». The same error occurs from Категория with uppercase.
FTS_NATURAL_DECLARATION — typo in the declaration keyword.
категория «Продажи»
объектт Покупка
сумма является деньгами
FTS_NATURAL_DECLARATION | ожидались объект, структура, морфизм, теорема или утилита
path: строка 3
FTS_NATURAL_INDENT — declaration is written at the same level as the category. Indentation in FTS carries meaning, like in Python.
категория «Продажи»
объект Покупка
сумма является деньгами
FTS_NATURAL_INDENT | объявление должно иметь отступ относительно категории
path: строка 3
FTS_NATURAL_FIELD — field without a binding является.
категория «Продажи»
объект Покупка
сумма деньги
FTS_NATURAL_FIELD | поле записывается как '«имя» является типом'
path: строка 4
FTS_UNCLOSED_STRING — unclosed fenced block.
FTS_UNCLOSED_STRING | не закрыта кавычка-ёлочка
path: строка 3
FTS_UTILITY_COMPARISON — a verb used in the condition does not exist in the language. The list of valid comparisons is closed and explicitly listed in the message.
правило «Большая покупка»
если сумма превышает 10000
то добавить 10 процентов от поля сумма
FTS_UTILITY_COMPARISON | ожидалось сравнение: равен, не равен, больше, меньше, не больше или не меньше
path: строка 13
FTS_UTILITY_INPUT / FTS_UTILITY_OUTPUT / FTS_UTILITY_INITIAL — the utility is missing one of the three required lines. The message names the utility and the missing word:
FTS_UTILITY_INPUT | утилита «Рассчитать скидку» требует строку 'принимает'
FTS_UTILITY_OUTPUT | утилита «Рассчитать скидку» требует строку 'возвращает'
FTS_UTILITY_INITIAL | утилита «Рассчитать скидку» требует строку 'начинает с'
FTS_NATURAL_UTILITY_INDENT — utility body lines are at different levels. The level is determined by the minimal indentation in the body, so the “extra indentation” will be applied to the line you shifted to the right.
FTS_NATURAL_UTILITY_INDENT | строка утилиты имеет лишний отступ
path: строка 8
FTS_UTILITY_EXAMPLE — example without a wait string.
FTS_UTILITY_EXAMPLE | пример «Большая покупка» требует строку 'ожидается'
path: строка 19
Model Errors
Stage validate. The text is parsed, but the model is contradictory. Here, there may be several diagnostics at once, and they form a chain from one cause.
FTS_UTILITY_FIELD — the rule refers to a field that does not exist in the input object. The most common error after renaming a field.
утилита «Рассчитать скидку»
принимает Покупка
возвращает деньги
начинает с 0
правило «Большая покупка»
если стоимость не меньше 10000
то добавить 10 процентов от поля сумма
FTS_UTILITY_FIELD | unknown utility input field 'стоимость'
path: $.utilities[0].rules[0].when[0].field
FTS_UTILITY_INPUT — utility accepts a non-existent object. A representative
case of a cascade: one typo in line принимает gives six diagnostics.
FTS_UTILITY_INPUT | utility 'Рассчитать скидку' references unknown input structure 'Заказ'
path: $.utilities[0].input
FTS_UTILITY_FIELD | unknown utility input field 'сумма'
path: $.utilities[0].rules[0].when[0].field
...
Reading rule: fix the diagnostics with the shortest path first. The rest
are almost always its consequence.
FTS_UTILITY_INITIAL_TYPE — initial value is not of the declared result type (начинает с «нет» at возвращает деньги).
FTS_UTILITY_INITIAL_TYPE | utility 'Рассчитать скидку' initial value does not match 'Деньги'
path: $.utilities[0].initial
FTS_UTILITY_COMPARE_TYPE — order comparison applied to a non-numeric field.
FTS_UTILITY_COMPARE_TYPE | field 'постоянный клиент' is not numeric
path: $.utilities[0].rules[0].when[0]
FTS_UTILITY_COMPARE_TYPE | comparison for 'постоянный клиент' uses incompatible values
path: $.utilities[0].rules[0].when[0]
FTS_UTILITY_EXAMPLE_FIELD — example does not set all required input fields.
Optional fields are declared through иногда является.
FTS_UTILITY_EXAMPLE_FIELD | example 'Большая покупка' misses 'постоянный клиент'
path: $.utilities[0].examples[0].input
FTS_UTILITY_EXAMPLE_TYPE and FTS_UTILITY_EXPECTED_TYPE — the input value or the expected result does not match the declared type.
FTS_UTILITY_EXAMPLE_TYPE | example field 'сумма' does not match 'Деньги'
FTS_UTILITY_EXPECTED_TYPE | example 'Большая покупка' result does not match 'Деньги'
FTS_DUPLICATE_FIELD — field is declared twice.
FTS_DUPLICATE_FIELD | duplicate field 'Покупка.сумма'
path: $.structures[0].fields[2].name
Live nearby FTS_DUPLICATE_STRUCTURE and FTS_DUPLICATE_UTILITY with the same
message form.
Execution utility errors
Stage executeUtility: the model is correct, the problem is in the input data of the call.
These diagnostics have neither span nor path — they describe the call.
FTS_UNKNOWN_UTILITY | не найдена утилита «Рассчитать бонус»
FTS_UTILITY_INPUT | во входных данных отсутствует поле «постоянный клиент»
FTS_UTILITY_INPUT_TYPE | поле «сумма» не соответствует типу «Деньги»
FTS_UTILITY_INPUT_FIELD | входная структура «Покупка» не содержит поле «скидка»
FTS_UTILITY_INPUT_TYPE most often means a string instead of a number: "20000"
instead 20000 — typical result of an unprocessed form or JSON from an external
service.
FTS_UTILITY_INPUT_FIELD triggers on an extra field: utility input is closed.
FTS_UTILITY_PROPERTY — the computation completed but violated the postcondition. The property does not fix the result, it stops the execution.
правило «Большая покупка»
если сумма не меньше 10000
то добавить 30 процентов от поля сумма
свойство «Скидка ограничена»
результат не больше 15000
FTS_UTILITY_PROPERTY | нарушено свойство «Скидка ограничена» утилиты «Рассчитать скидку»
This is the only diagnostic that reports a fallacy in business logic, not form. A fix is either a rule or a property boundary: the solution is domain-specific, the compiler will not accept it on your behalf.
Errors of examples
Stage testUtilities. Two diagnostics are emitted before execution:
FTS_NO_UTILITIES | документ не содержит утилит
FTS_NO_UTILITY_EXAMPLES | утилиты не содержат примеров
Mismatch of the example by the diagnostic is not — this is a report. The field valid
becomes false, and in results the expected and actual values are visible:
{ "utility": "Рассчитать скидку", "example": "Большая покупка",
"passed": false, "expected": 1000, "actual": 2000 }
If the example crashes due to a runtime error, instead of actual comes error:
{ "passed": false, "expected": 6000,
"error": "нарушено свойство «Скидка ограничена» утилиты «Рассчитать скидку»" }
The difference is important: expected/actual means incorrect expectation arithmetic,
error — means the result was not reached.
Proof Errors
The theorem is checked in two passes. Morphism types and presence of fields are verified
during parsing, while checking against real data occurs at stage prove.
FTS_UNKNOWN_FIELD — in line дано a field is mentioned that does not exist in the object.
FTS_UNKNOWN_FIELD | не найдено поле «Заказ».«готов к отправке»
FTS_UNKNOWN_FUNCTOR — morphism with such a name is not declared. In the internal model, morphisms are still called functors, hence the word in the code.
FTS_UNKNOWN_FUNCTOR | не найден морфизм «Заказ можно отгрузить»
FTS_PROOF_TYPE_MISMATCH — the morphism domain did not match the proof type.
Here the theorem relies on the field номер of type Строка, while the morphism expects
a state.
теорема «Заказ ЗК-7781 можно отгрузить»
дано Заказ имеет номер равное «ЗК-7781»
в данных заказы найти где номер равен «ЗК-7781»
по морфизму «Готовый заказ можно отгрузить»
следовательно «Отгрузить заказ разрешено»
FTS_PROOF_TYPE_MISMATCH | морфизм «Готовый заказ можно отгрузить» ожидает «Готов к отгрузке», получено «Строка»
FTS_THEOREM_CONCLUSION — chain inference does not match the declared one.
FTS_THEOREM_CONCLUSION | теорема объявляет «Заказ отгружен», но вывод имеет тип «Отгрузить заказ разрешено»
FTS_MULTIPLE_PROPOSITIONS — the document has two theorems.
FTS_MULTIPLE_PROPOSITIONS | версия FTS 0.2 допускает одну теорему в документе
FTS_WITNESS_MISMATCH — the only diagnostic that appears only during proof with data. Without context FTS builds a symbolic derivation and remains silent; with context it finds an object along the path and checks the value:
FTS_WITNESS_MISMATCH | witness does not match context at заказы[номер="ЗК-7781"].готов к отгрузке: expected true, got false
path: $.proposition
The message shows the built path in full. If <missing> is in place of a value, the error is in the path or the selector, not in the fact.
Practice in the sandbox
Exercise 1. Open the discount model and in the «Big purchase» rule replace
сумма with стоимость. Expected result — FTS_UTILITY_FIELD with path
$.utilities[0].rules[0].when[0].field. Return the name and ensure that
the diagnostics have disappeared.
Exercise 2. In the same rule, replace 10 процентов with 30 процентов and
run the examples. The model will pass the check, but on the example “Purchase at the discount ceiling”
execution will stop at FTS_UTILITY_PROPERTY: 30 000 against the ceiling
15 000 — the error is not in the form, but in the contradiction between the rule and the property.
Exercise 3. In the shipping model, replace line дано with field номер and
look at FTS_PROOF_TYPE_MISMATCH, then return the field and change
следовательно — get FTS_THEOREM_CONCLUSION.
Checklist: what to check when the model does not compile
- The first significant line is
категория «Имя»in lowercase. An English message instead of Russian means the document went to the bracket parser. - All declarations are indented relative to the category, and lines within one block have the same indentation.
- The pine quotes are closed, the name is not continued with extra text.
- Each utility has
принимает,возвращаетandначинает с. - Comparisons are taken from a closed list:
равен,не равен,больше,меньше,не больше,не меньше. - Field names in rules, properties and examples match those declared in the object — character by character.
- When there are multiple diagnostics, fix the one with the shortest
path. - If the error appeared only at execution, look not at the model, but at the input data of the call.
Fixed model from the exercises as a whole:
категория «Продажи»
объект Покупка
сумма является деньгами
«постоянный клиент» является признаком
утилита «Рассчитать скидку»
принимает Покупка
возвращает деньги
начинает с 0
правило «Большая покупка»
если сумма не меньше 10000
и сумма не больше 100000
то добавить 10 процентов от поля сумма
правило «Постоянный клиент»
если «постоянный клиент» равен да
и сумма больше 0
и сумма не больше 100000
то добавить 5 процентов от поля сумма
правило «Очень крупная покупка»
если сумма больше 100000
то добавить 15000
свойство «Скидка ограничена»
результат не больше 15000
пример «Большая покупка постоянного клиента»
дано сумма равна 20000
дано «постоянный клиент» равен да
ожидается результат равен 3000