2010-07-21 7 views
7

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

Мой язык - это подмножество C, и у меня возникла проблема с реализацией стекового интерпретатора. На языке следующее скомпилируется:

somefunc() 
{ 
    1 + 2; 
} 

main() 
{ 
    somefunc(); 
} 

Теперь это хорошо, но когда «1 + 2» вычисляется результат помещается в стек, а функция возвращает, но есть еще ряд в стеке, и не должно быть. Как я могу обойти эту проблему?

Я думал о сохранении «состояния» стека перед вызовом функции и восстановлении «состояния» после вызова функции. Например, сохраняя количество элементов в стеке, затем выполните код функции, верните, а затем поместите из стека до тех пор, пока мы не будем иметь такое же количество элементов, как раньше (или, может быть, +1, если функция вернула что-то).

Любые идеи? Спасибо за любые советы!

ответ

8

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

Оператор выражения - это код, в котором оператор является просто выражением. Это означает что-то вроде <expression> ;, которое включает в себя такие функции, как присвоения и вызовы функций, но не if s, while s, или return s. Любой оператор выражения будет иметь значение слева в стеке в конце, которое вы должны отменить.

1 + 2 является выражением утверждение, но так же это:

  • x = 5;
    Назначение выражение оставляет значение 5 в стеке, так как в результате присваивания является значение левшей ручной операнд. После того, как заявление законченные вы палить неиспользуемое значение 5.

  • printf("hello world!\n");
    Е() возвращает количество символов вывода. Вы оставите это значение в стеке, так что поместите его, когда закончится утверждение.

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

+0

Забавно, что вы это называете, потому что в моем представлении AST у меня есть узел под названием «ASTStmtExpr» только для этого! Я думаю, что я начинаю понимать, вроде ... Вот о чем я не уверен: Из-за ограничений этих комментариев ответа у меня есть приклеить snipplet: \t аннулируются составители :: визит (Const ASTStmtExpr & expr_stmt, станд :: shared_ptr FUNC) \t \t { \t \t \t expr_stmt.expr() -> принимает (* это, FUNC); \t \t} Вы говорите, что после этого я должен добавить OP_POP, и для таких вещей, как присваивания, я бы нажал на фиктивный объект «Nil», чтобы затем его выскочить? –

+0

Извините, что я не знал, что комментарии не отформатированы –

+1

Для присвоений нет, вы не нажимаете фиктивное значение, потому что у вас уже будет результат назначения в стеке. Назначение - это просто выражение, использующее оператор '=', который ничем не отличается от '+' или '-', кроме' = 'имеет побочный эффект назначения переменной. В противном случае он ведет себя так же, как и все остальные операторы. –

2

Вам понадобится более разумный парсер. Когда вы видите выражение, значение которого не используется, вам нужно испустить POP.

+0

Здравствуйте, благодарю вас за ответ. Я все еще нахожусь на этапах подготовки к кодированию, и я подумал о том, чтобы сделать такую ​​оптимизацию, но не смог найти приемлемое решение :(Может быть, я попробую еще раз, снова спасибо! –

0

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^