I'm attempting to implement a small, portable, compiled stack based language for my osdev endeavors. I am currently in the early steps in writing my compiler(In perl, because I want portability, and I don't want to play with strings in C.) However, I've run into a problem....How does one implement local variables in a stack based programming language? I've read that local variables are implemented using the stack, but if my language uses the stack for everything, I'm not thinking that will work.....Any ideas?
Thanks!
Stack based languages and local variables...
Stack based languages and local variables...
C8H10N4O2 | #446691 | Trust the nodes.
Really? It makes everything so easy. though....ehird wrote:A compiler written in Perl? That'll be a first.
I now have a compiler that will start to assemble things...but....it seems as if there is too much pushing....For instance, when I do something like:
Code: Select all
32 $x @add
Code: Select all
push 32
push word [x]
pop eax
pop ebx
add eax, ebx
push eax
C8H10N4O2 | #446691 | Trust the nodes.
Well fine! Don't replay to my topic! (Just kidding)
I've found that stack based languages are not easy to compile efficiently, so I have gone and made an imperative stack type language. I plan for it to be specifically for osdev and cross platform assembly type stuff, where you don't feel like playing with C's noisy compiler. For example:
Now, this directly translates to:
Moreover, I have a simple directive system in a slightly working process, so:
translates to:
I designed the syntax to be extremely compiler friendly. Currently, it all fits in 3.3kb of Perl code, using regular expressions as if prohibition started tomorrow.
The question is: what would you want if you were designing a language for osdev? Any suggestions?
Thanks.
I've found that stack based languages are not easy to compile efficiently, so I have gone and made an imperative stack type language. I plan for it to be specifically for osdev and cross platform assembly type stuff, where you don't feel like playing with C's noisy compiler. For example:
Code: Select all
~main {
12 (cv)
23452 $cv:4 =
}
Code: Select all
main:
mov dword [cv], 2203409
cv: db 0,0,0,0,0,0,0,0,0,0
Code: Select all
~main {
1 (char)
65 $char =
%asm {
mov eax, 32
}
}
Code: Select all
main:
mov byte [char], 65
mov eax, 32
char: db 0
The question is: what would you want if you were designing a language for osdev? Any suggestions?
Thanks.
C8H10N4O2 | #446691 | Trust the nodes.
The whole idea of stack-based languages is to do away with the idea of local variables, at least in the sense of local-variables with names, instead using explicit stack manipulation to do the same.
Consider the following example in Lisp:
That binds a local variable x to the value 2, and then adds two x's together.
In a stack based language you'd do the same thing as something like:
In other words: push the value 2, then duplicate the top of stack, and then replace the 2 topmost elements with their sum.
I think the easiest way to compile a stack-based language efficiently (in the sense of actually doing more complicated optimizations than just peepholing certain combinations of words) would be to convert the code back to something functional like Scheme, A-normalize the result, and then compile it. You'll probably have to do that globally to the whole program to get much out of it but..
On the other hand, if you don't want to optimize (other than said peepholing) then compiling a stack based language basicly consists of writing assembly version of all the primitive words (as Forth calls them) and reading the source, patching sequences of the primitive words and calls to non-primitive words (=other sequences of primitive and non-primitive words). Doing this isn't very hard.
Consider the following example in Lisp:
Code: Select all
(let ((x 2))
(+ x x))
In a stack based language you'd do the same thing as something like:
Code: Select all
2 dup +
I think the easiest way to compile a stack-based language efficiently (in the sense of actually doing more complicated optimizations than just peepholing certain combinations of words) would be to convert the code back to something functional like Scheme, A-normalize the result, and then compile it. You'll probably have to do that globally to the whole program to get much out of it but..
On the other hand, if you don't want to optimize (other than said peepholing) then compiling a stack based language basicly consists of writing assembly version of all the primitive words (as Forth calls them) and reading the source, patching sequences of the primitive words and calls to non-primitive words (=other sequences of primitive and non-primitive words). Doing this isn't very hard.
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.