Материал FTS: reading compiler errors
0%

FTS: reading compiler errors

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

  1. The first significant line is категория «Имя» in lowercase. An English message instead of Russian means the document went to the bracket parser.
  2. All declarations are indented relative to the category, and lines within one block have the same indentation.
  3. The pine quotes are closed, the name is not continued with extra text.
  4. Each utility has принимает, возвращает and начинает с.
  5. Comparisons are taken from a closed list: равен, не равен, больше, меньше, не больше, не меньше.
  6. Field names in rules, properties and examples match those declared in the object — character by character.
  7. When there are multiple diagnostics, fix the one with the shortest path.
  8. 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

Cases in the catalog on this topic

Нашли неточность? Выделите фрагмент текста — рядом появится жучок.

Нужен разбор именно вашей ситуации?

Статья описывает общий случай. Если у вас частный — можно разобрать его отдельно, платно. А если не хватает целого материала, предложите тему: её оплачивают вскладчину, и она выходит открытой для всех.

Доска запросов
Дальше