Пошёл читать парсер. Вместо кучи классов для разных элементов синтаксического дерева я бы возможно сделал всего один, хранящий тип узла и произвольное число аргументов, но вообще текущий подход хороший, особенно если узлы бывают разных типов и типы проставлены; так что тут я ничего не предлагаю менять.
Дальше сильно пока вчитываться не буду, вы там ниже вроде про конкретные проблемы говорили, их посмотрим…
Может, для решения 2 ввести какую-нибудь операцию RetOp, которая бы возвращалась к вызвавшей данную функцию функции?
Ага, да, этого не хватает в машине. Щас я ещё немного посмотрю тут и машину обновлю. Будут две операции, ещё и
CallOp для вызова, чтобы в стек вызовов помещалось состояние, в которое вернуться, ну и
RetOp будет его оттуда брать и туда идти.
Вот пытаюсь понять, как лучше определить локальные и глобальные переменные? Все упирается в то, что переменная не может понять, внутри какой функции создается.
Можно посчитать, что весь код завёрнут в одну большущую функцию, тогда глобальные переменные будут её обычными.
Тут не понял.
Это я про то, что если определить
statement: block | assign SEMICOL | expr SEMICOL, то функции ровно так же можно будет вызывать как оператор, но притом мы немного экономим в парсере. (Но тогда же можно будет писать и штуки типа
[] + []; return x;, где выражение вычисляется впустую. Это не особая проблема, но и её потом тоже можно будет устранить предупреждениями при компиляции.)
Зачем комментариям удаляться в лексере? У меня ща они удаляются в парсере.
Но нельзя будет поставить комментарий например так:
x = /* ... */ y; а вдруг я хочу.