views:

167

answers:

2

Hello everyone I'm currently implementing a simple programming language for learning experience but I'm in need of some advice. Currently I'm designing my Interpreter and I've come into a problem.

My language is a subset of C and I'm having a problem regarding the stack interpreter implementation. In the language the following will compile:

somefunc ()
{
    1 + 2;
}

main ()
{
    somefunc ();
}

Now this is alright but when "1+2" is computed the result is pushed onto a stack and then the function returns but there's still a number on the stack, and there shouldn't be. How can I get around this problem?

I've thought about saving a "state" of the stack before a function call and restoring the "state" after the function call. For example saving the number of elements on the stack, then execute the function code, return, and then pop from the stack until we have the same number of elements as before (or maybe +1 if the function returned something).

Any ideas? Thanks for any tips!

+2  A: 

You'll need a smarter parser. When you see an expression whose value isn't being used then you need to emit a POP.

Hans Passant
Hello, thank you for the answer. I'm still in the infant phases of coding compilers and I have thought about doing an optimization like this, but was unable to find a feasible solution :( Maybe I'll try again, again thanks!!
+8  A: 

Great question! One of my hobbies is writing compilers for toy languages, so kudos for your excellent programming taste.

An expression statement is one where the code in the statement is simply an expression. This means anything of the form <expression> ;, which includes things like assignments and function calls, but not ifs, whiles, or returns. Any expression statement will have a left over value on the stack at the end, which you should discard.

1 + 2 is an expression statement, but so are these:

  • x = 5;
    The assignment expression leaves the value 5 on the stack since the result of an assignment is the value of the left-hand operand. After the statement is finished you pop off the unused value 5.

  • printf("hello world!\n");
    printf() returns the number of characters output. You will have this value left over on the stack, so pop it when the statement finishes.

Effectively every expression statement will leave a value on the stack unless the expression's type is void. In that case you either special-case void statements and don't pop anything afterwards, or push a pretend "void" value onto the stack so you can always pop a value.

John Kugelman
Its funny you name that because in my AST representation I have a node called "ASTStmtExpr" just for this! I think I'm starting to understand, sort of... Here's what I'm unsure about:Due to the limitations of these comment replies I have to paste a snipplet: void Compiler::visit (const ASTStmtExpr }You're saying I should add a OP_POP after this, and for things like assignments I would push a dummy "Nil" object so it would then get popped?
Sorry I didn't know the comments aren't formatted
For assignments no, you don't push a dummy value, because you'll have the result of the assignment on the stack already. An assignment is just an expression using the `=` operator, which is no different from `+` or `-` except `=` has a side effect of assigning to a variable. Otherwise it behaves just like all other operators.
John Kugelman
A `void` expression would be something like calling a function which returns `void`. For example: `abort();`. But heck, this might just be an academic consideration. Your example code doesn't list function return types, so this may not even be an issue for you.
John Kugelman
Yes its a non-issue for me since my language has no types, even primitives are "objects" in my language so I don't think it will be a problem. Thanks for the response!