AllBASIC Forum
BASIC Developer & Support Resources => Interpreters => Topic started by: Marcus on April 25, 2012, 04:12:05 AM
-
For the fun of it, I've started writing a BASIC compiler in naalaa, targeting the naalaa virtual machine of course. My first idea was to write an yabasic compiler, but after reading the documentation of yabasic I cried "NO NO!!!" and had to drink three beers to calm down. Anyhow, I will try to make this language more BASIC-like than naalaa (even if it means less orthogonality), and the source code will be open. Numbers will be typeless (no floats or ints), but I will still separate numbers from strings.
The language is useless, so far. You can assign the value of an expression to a global variable, no more. The resulting value of every assignment is written to the output window.
For example:
foo = (3+17)/2 + 5
bar = 3 + foo
Outputs:
15
18
If you want to compile any other program than "test.bas" (by clicking on compile.exe), you should run compile.exe from the command prompt (yes, Windows only) and pass the name of the file to compile and run like:
compile my_test.bas
No executable is created at the moment. The compiler only creates a naalaa bytecode file (temp.nvm) and runs it.
The sourcecode of the compiler is in "compile.txt."
EDIT: When you compile a program, the bytecode is written to the window. You then have to press any key to run the actual program.
-
Hey Marcus,
This is great!
I'm glad to see you doing this.
I love working with byte code compilers.
You've been working on this..., this didn't happen just over night.
Very interesting.
-
I glanced at the naalaa compiler while writing this, of course. But naalaa is a real mess (those who say yabasic is haven't seen sh*t) so I'll try not to look too much at it.
-
Marcus,
[Your Sponsor]
I don't mean to hijack your thread but if you lose interest in this for fun project, I have a proposal for you.
ScriptBasic already has a preprocessor as a debugger. (single step, breakpoint, view variables, ...) It would be really cool if you could create an interactive version of ScriptBasic. (like the original QuickBasic version) I would say 90% plus of the code is already done and working for years.
Back to the MarcusBasic show.
[/Your Sponsor]
I'm just happy that a programmer of your skill level would hang with us Basic dudes.
-
I was given some spare time today, so I added a couple of things to the compiler (the attachment in the first post has been updated). You can now use floating point constants, not just integer constants. The floating point constants are cached and saved into the binary (a requirement of the vm, as constant floating point values can't be part of an instruction). The numeric factor function also handles some basic system calls for cos, sin, tan etc. And I also added string expressions and string constants. As before, every assignment causes an ouput. This is the example program:
a$ = "nink"
b$ = "Hegonkllo wogonkrld" - (("go") + (a$ - "ni")) + "!"
dummy = 13 + |-50 + sin(90.0)*13|
This is the output:
nink
Hello world!
50.0
The thing I like the most is the use of a pair of | characters for absolute values, like |<expr>|, instead of abs(<expr>). That's the way you type it in the universal mathematical language :) But I guess that also means I just stepped off the BASIC-like bus.
I hope this doesn't turn into a spam-like thread. I'll try to keep a low update frequency.
@JRS
I'm not sure if your words are ironic or not (I'm a swede). But I truely know very little about compiler design and I have a REAL problem with understanding other peoples code (that's why I'm not the open source kind of toad). So I don't think I'd do any good on a project like that :) But thanks for the proposal.
I created naalaa because I wanted to be able to write retro games quickly. Now I just want to reuse the virtual machine for another, very experimental, language. For example, I'll try to implement the subroutine calling convention that I got so eager about on bp.org.
-
I added logic expressions and IF-statements today (updated the zip in the first post once more). I'll go for SELECT/CASE next as naalaa doesn't have it - I'll see if it's possible to generate jump tables for this :)
Programs may behave strange as I haven't cared for line endings yet:
foo
=5
IF
foo = 5 THEN bar =
3
END
IF
is a valid program. Sorry.
-
Is your current IF/THEN/ELSE structure nestable?
Is this going to be a Windows only Basic?
-
Is your current IF/THEN/ELSE structure nestable?
Is this going to be a Windows only Basic?
Yes they can be nested. As naalaa works on linux (well, very slow on some systems, haven't figured that one out yet) this will work there too.
EDIT:
I also just added commands for text input and output, ex:
INPUT "Give me a value: ", foo, "And another value: ", bar, "And your name: ", name$
PRINT
PRINT "The first value plus the second value equals ", foo + bar, "."
PRINT "And I know that your name is ", name$, "."
IF name$ = "Marcus" OR name$ = "marcus" THEN
PRINT "... What a lovely name!"
END IF
PRINT
PRINT "Press any key to exit ..."
This was fun, because in naalaa there is no INPUT statement (atleast not in this form). And line endings are now treated correctly (you can also use ; for a virtual line ending).
-
When I came home from work today I implemented all but one of the loop structures that I found on some page about qbasic:
while <expr> ... wend
do ... loop
do while <expr> ... loop
do until <expr> ... loop
do ... loop while <expr>
do ... loop until <expr>
(I've once again updated the attachment in the first post.)
What I'm wondering about right now is how the for <assignment> to <expr> [step <???>] ... next works in "standard" basic? In naalaa I have no 'step' feature, instead you can use 'to' and 'downto' for 1 and -1 increments. My question is if the step value should be an expression or limited to a constant? It makes quite a damn difference :)
Iteration example program:
a = 0
PRINT "while a <= 4 / loop"
WHILE a < 4
PRINT a
a = a + 1
WEND
a = 0
PRINT "do while a < 4 / loop"
DO WHILE a < 4
PRINT a
a = a + 1
WEND
a = 0
PRINT "do until a = 4 / loop"
DO UNTIL a = 5
PRINT a
a = a + 1
LOOP
a = 0
PRINT "do / until a >= 5"
DO
PRINT a
a = a + 1
LOOP UNTIL a >= 5
a = 0
PRINT "do / while a < 4"
DO
PRINT a
a = a + 1
LOOP WHILE a < 5
PRINT
PRINT "Press any key to exit ..."
Every loop oviously outputs 0..4.
EDIT: Is it possible to write a stack clean version of for/to/step/next that needn't special treatment on a break in a subroutine?
-
What I'm wondering about right now is how the for <assignment> to <expr> [step <???>] ... next works in "standard" basic?
If I understand the question...,
that is simple to illustrate:
You would assume the default STEP value to be "1", as in:
FOR indx=1 TO 100 STEP 1
....
NEXT indx
however, you can't assume that the incrementation is always going to be by a factor of "1".
As in "C":
for(indx=0; indx <= 100; indx++)
{
....
}
what about:
for(indx=0; indx <= 100; indx += 2)
?
In the above, you have:
for(indx=0; indx <= 100; indx += 2)
-FOR- / -TO- / -STEP-
So, the STEP value is any value (or evaluation) other that "1".
If the STEP value is "1", then the step value need not be stated, as the default is "1".
FOR indx = 1 TO 100
....
NEXT indx
The STEP value would not be a constant.
It has to be the a value given, a variable, the result of an expression, or the default if none is stated.
FOR x = 1 TO 100 (default "1")
FOR x = 1 TO 100 STEP 3
FOR x = 1 TO 100 STEP MyVar
FOR x = 1 TO 100 STEP [expression]
NOTE:
once the entire FOR/NEXT expression is evaluated, prior to the first pass, the STEP value cannot change.
"x" is the only value that is allowed to change during the loop process.
As in:
FOR x = val1 TO val2 STEP val3
-
a = 5
FOR x = 1 to a
IF x = 4 THEN a = 4
PRINT x,":",a,"\n"
NEXT
In your new Basic, would you see 5 iterations or 4?
-
NOTE:
once the entire FOR/NEXT expression is evaluated, prior to the first pass, the STEP value cannot change.
"x" is the only value that is allowed to change during the loop process.
Okay, that is the standard?
This is how it works in naalaa:
for a = b to/downto c
...
next
b is evaluated once and c is evaluated before each branch.
So in this case:
for a = b to c step d
...
next
, you're telling me that the d should only be evaluated the first time? I know it's good for the stack and would make execution faster. But do you think it could harm backward compability to evaluate both expression c and d before each branch?
I want to make this language fully compatible with qbasic and ... well, yabasic, but I still want it to be better and more flexible :)
-
..., you're telling me that the d should only be evaluated the first time?
I want to make this language fully compatible with qbasic and ... well, yabasic, but I still want it to be better and more flexible :)
Yes.
However, Yabasic is very non-standard (and peculiar) in many things it does.
I wouldn't base much of anything on what Yabasic does.
-
Yes.
However, Yabasic is very non-standard (and peculiar) in many things it does.
I wouldn't base much of anything on what Yabasic does.
But yabasic is obviously so ... "Lollipop, lollipop, oh lolli lolli lolli lollipop!"
-
I just checked my Basic Reference Book: "The Basic Handbook",
in every case and example STEP remains constant and is not re-evaluated.
-
a = 10
s = 1
FOR x = 1 TO a STEP s
IF x = 5 THEN s = .5
IF x = 10 THEN
a = 15
s = 1
END IF
PRINT FORMAT("%g",x),"\n"
NEXT
jrs@laptop:~/sb/test$ scriba 4var.sb
1
2
3
4
5
5.5
6
6.5
7
7.5
8
8.5
9
9.5
10
11
12
13
14
15
jrs@laptop:~/sb/test$
-
Then Sb and Yabasic share the same peculiarity.
That is very uncommon.
-
a = 10
s = 1
FOR x = 1 TO a STEP s
IF x = 5 THEN s = .5
IF x = 10 THEN
a = 15
s = 1
END IF
PRINT FORMAT("%g",x),"\n"
NEXT
jrs@laptop:~/sb/test$ scriba 4var.sb
1
2
3
4
5
5.5
6
6.5
7
7.5
8
8.5
9
9.5
10
11
12
13
14
15
jrs@laptop:~/sb/test$
Very nice!
But I'm not sure it works like this in yabasic at all; what I meant was just that I want compability with yabasic in general, as people seem to like it that much.
However, this SB example illustrates perfectly what I'm after :) Can you find more hidden candy like that in SB?
-
Isn't this sort of a "Kobayashi Maru", where you set up a test and in mid-stream you alter or change the conditions of the test ?
Why would you do that ?
The following snippets are extracts from: ECMA-55 (Basic Standard), section 13:
<quotation...>
"The action of the for-statement and the next-statement is defined in terms of other statements, as follows:
FOR v = initial-value TO limit STEP increment
(block)
NEXT v
is equivalent to:
LET own1 = limit
LET own2 = increment
LET v = initial-value
line1 IF (v-own1)*SGN (own2) > 0 THEN line2
(block)
LET v = v+own2
GOTO line1
line2 REM continued in sequence
Here v is any simple-numeric-variable, own1 and own2 are variables associated with a particular for-block and not accessible to the programmer, and line1 and line2 are line numbers and not accessible to the programmer.
A program shall not transfer control into a for-body by any statement other than a return statement."<...end>
And,
<quotation...>
The variables "own1" and "own2" associated with a for-block are assigned values only upon entry to the for-block through its for-statement."<...end>
To me, the key notes here are:
..."own1 and own2 are variables ... not accessible to the programmer,..."
and,
...variables "own1" and "own2" ... assigned values only upon entry to the for-block...
-
Can you find more hidden candy like that in SB?
It's Halloween at the ScriptBasic project and all you need to do is open your bag and help yourself. We promise not to to make your visit too scary. :D
(http://www.cartoonmotivators.com/images/P/SpinningPlates.jpg)
-
Isn't this sort of a "Kobayashi Maru", where you set up a test and in mid-stream you alter or change the conditions of the test ?
@Steve: Please don't apply for any missile silo operator jobs!
ScriptBasic is a scripting language that happens to use traditional Basic (for the most part) as it's syntax. What may be lost in performance is returned 10 fold in simplicity with the expectation the language is smart enough to assume the obvious.
-
ScriptBasic is a scripting language that happens to use traditional Basic (for the most part) as it's syntax.
Well, I'm not an absolute pureist.
I think that is one of the faults of the BASIC language and some might say part of its charm, the fact that despite attempts to create Industry Standards, in both the US and Europe, developers refused to adhere to them.
Instead, we have a hundred plus different dialects of a language, each with their own nuances and idiosyncrasies.
Take C as an example, the C language is clearly defined as to what is and what isn't considered "C".
You can't call it "C" if it isn't really compliant with the "C" Standards.
Javascript is Javascript, Perl is Perl.
You don't generally run into various dialects of the most popular and widely used, modern languages.
I think in the case of Basic, in an effort to expand the language and add functionality, developers failed to recognise the importance of standardization.
With the exception of x86 Assembly Language, I personally don't know of another programming language that suffers from the same problem of having too many dialects to choose from. Each with their own following and user base.
Contrarily, the C/C++ user base seems to cluster more around which IDE to use.
If you know C, then you know C.
If you know C++, then you know C++.
If you know Perl, then you know Perl.
If you know Basic, then you need to specify which dialect of Basic you are proficient in.
From the perspective of the end-users, does having too many differing dialects enhance or dilute the appeal of using a particular language ?
-
From the perspective of the end-users, does having too many differing dialects enhance or dilute the appeal of using a particular language ?
Variety is the spice of life.
Why do some people build hot rods or return a classic cars to mint condition when they can pick up a car off a lot?