Почему макросы, основанные на абстрактных синтаксических деревьях, лучше, чем макросы, основанные на предварительной обработке строк?

Я начинаю свой путь изучения Руста. Я наткнулся на эту строку в Rust на примере:

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

Почему абстрактное синтаксическое дерево лучше, чем предварительная обработка строк?

2 ответа

Решение

Если у вас есть это в C:

#define X(A,B) A+B
int r = X(1,2) * 3;

Значение r будет 7потому что препроцессор расширяет его до 1+2 * 3, который 1+(2*3),

В Rust вы бы получили:

macro_rules! X { ($a:expr,$b:expr) => { $a+$b } }
let r = X!(1,2) * 3;

Это оценит 9потому что компилятор будет интерпретировать расширение как (1+2)*3, Это потому, что компилятор знает, что результатом макроса должно быть полное, автономное выражение.

Тем не менее, макрос C также может быть определен так:

#define X(A,B) ((A)+(B))

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

Используя узлы AST вместо текста, Rust гарантирует, что такой неоднозначности не произойдет.

Классический пример использования препроцессора C:

#define MUL(a, b) a * b

// ...

int res = MUL(x + y, 5);

Использование макроса расширится до

int res = x + y * 5;

что очень далеко от ожидаемого

int res = (x + y) * 5;

Это происходит потому, что препроцессор C на самом деле просто выполняет простые текстовые подстановки, на самом деле он не является неотъемлемой частью самого языка. Предварительная обработка и анализ - два отдельных шага.

Если препроцессор вместо этого проанализировал макрос, как и остальная часть компилятора, что происходит для языков, где макросы являются частью фактического синтаксиса языка, это больше не проблема, так как такие вещи, как приоритет (как упоминалось) и ассоциативность, принимаются во внимание.

Другие вопросы по тегам