компиляторы - выбор инструкций для объявлений типов в AST - PullRequest
1 голос
/ 18 ноября 2011

Я изучаю компиляторы и создаю генератор кода для простого языка, который работает с двумя типами: символами и целыми числами.

После того, как пользовательский вход был отсканирован сканером, а затем проанализирован синтаксическим анализатором, я получаю AST-представление ввода.Я сделал генерацию кода для еще более простого языка, который обрабатывает выражения только с целыми числами, операторами и переменными.

Однако с этим новым языком я иногда получаю поддерево для объявления типа, например:

(IS TYPE (x) (INT))

, который говорит, что х имеет тип INT.

Должен ли быть случай в моем генераторе кода, который имеет дело с этими объявлениями типов?Или это просто для того, чтобы семантический анализатор проверял тип, поэтому я должен просто предположить, что типы были проверены, игнорировать эту часть дерева и просто присвоить значение для x?

Ответы [ 2 ]

1 голос
/ 18 ноября 2011

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

Являетесь ли вы "генератором кода" программой, которая получает в качестве входного кода язык программирования (может быть, маленький) и выводит код на другом языке программирования (может быть, маленький)?

Этот инструмент обычно называют «переводчиком».

Являетесь ли вы "генератором кода" программой, которая получает на вход язык программирования и выводит ассемблер / байт-код, как язык программирования?

Этот инструмент обычно называют "компилятором".

Примечание: «стопка» является синонимом «стопки».

Обычно A.S.T. хранит тип операции или вызов функции. Пример в c:

...
int a = 3;
int b = 5;
float c = (float)(a * b);
...

Последняя строка, генерирует A.S.T. аналогично этому (пропустите A.S.T. для других строк):

..................................................................
..................................................................
......................+--------------+............................
......................|    [root]    |............................
......................| (no type) =  |............................
......................+------+-------+............................
.............................|....................................
.................+-----------+------------+.......................
.................|........................|.......................
...........+-----+-----+....+-------------+-------------+.........
...........| (int) c   |....| (float) (cast operation)  |.........
...........+-----------+....+-------------+-------------+.........
..........................................|.......................
....................................+-----+-----+.................
....................................| (int) ()  |.................
....................................+-----+-----+.................  
..........................................|.......................
....................................+-----+-----+.................
....................................| (int) *   |.................
....................................+-----+-----+.................
..........................................|.......................
..............................+-----------+-----------+...........
..............................|.......................|...........
........................+-----+-----+...........+-----+-----+.....
........................| (int)  a  |...........| (float) b |.....
........................+-----------+...........+-----------+.....
..................................................................
..................................................................

Обратите внимание, что "(float)" приводит его как оператор или функцию, похоже на ваш вопрос.

Удачи.

1 голос
/ 18 ноября 2011

Если это декларация

(IS TYPE (x) (INT))

тогда x следует выложить в память. В случае C и автоматических переменных локальные автоматические переменные размещаются в стеке. Чтобы выделить необходимый размер стека, вы должны знать размеры всех локальных переменных и размеры относятся к типам.

Если эта переменная хранится в регистре, вы должны выбрать регистр необходимого размера (подумайте о x86 с: AL, AX, EAX, RAX - один и тот же регистр с разными размерами), если ваша цель имеет такой.

Кроме того, тип необходим, когда в AST имеется неоднозначная операция, которая может работать с различными размерами данных (например, char, short, int- или 8-битные, 16-битные, 32-битные и т. Д.). А для некоторых ассемблеров размер данных кодируется в самой инструкции; поэтому codegen должен помнить размеры переменных.

Или, если тип операции не был записан в AST, ADD:

(ADD (x) (y))

может означать дополнения как float, так и int (инструкции ADD или FADD), поэтому для выбора правильного варианта в codegen необходимы типы x и y.

...