elektito / qbee Goto Github PK
View Code? Open in Web Editor NEWYet another QBASIC compiler
License: GNU General Public License v3.0
Yet another QBASIC compiler
License: GNU General Public License v3.0
In the absence of a complete graph analysis, we can still remove some simple cases like:
One example of the first case being created by the compiler, is at the end of an if block, right before an "else" or an "elseif", if there is an "EXIT SUB/FUNCTION" statement. The compiler generates a JMP instruction afterwards to the end of the IF block, which is unreachable.
Right now get_variable_type is in Compiler
and receives a Routine
object. It might make more sense to move it to the Routine
class. For global variables we can refer to the compiler object. DEF* statements are effective only in the current routine, so this causes cleaner code for them as well.
readidx/storeidx and storeidx/readidx pairs can be eliminated if their indices match, the same way we eliminate simple read/store and store/read pairs.
The following cases should be added to vars.test
file, and pass.
Duplicate definition:
x% = 10
dim x as
Duplicate definition:
dim x as single
x% = 2
Duplicate definition:
dim x a s single
print x%
No error; x and x! are the same variable:
dim x as sinle
x! = 2
No error; x and x% are separate variables:
dim x
x% = 2
No error; x and x! are the same variable:
dim x
x! = 5
Without any conflicting declarations, variable names can contain periods. For example, the following is valid:
f.x = 100
PRINT f.x
This also works with SUB/FUNCTON names, but not with DIM statements however. The following is invalid and will result in an error saying "Identifier cannot include period":
DIM f.x AS INTEGER
Interestingly, the following code will result in the same error ("identifier cannot include period") on the assignment line, even though the DIM statement determining the variable type is after that:
TYPE foo
x AS INTEGER
END TYPE
f.x = 100 ' <-- ERROR: Identifier cannot include period
DIM x AS foo
This does not mean that in general DIM statements work on variable names used before them. The following will cause a "duplicate definition" error on the DIM statement:
x = 10
DIM x AS INTEGER ' <-- ERROR: Duplicate definition
Currently we only support a LOCATE command accepting a row and column. The original command has more optional arguments. Implement the full command.
In a snippet like this:
push1!
storel! x!
push! 2.0
storel! x!
The first two instructions can be eliminated, because the second pair overwrites it. This is more difficult than current optimizations that only work on consecutive instructions. This could also span many instructions.
Currently we only support a LOCATE command accepting a row and column. The original command has more optional arguments. Implement the full command.
Consider this piece of code:
DEFLNG A-Z
A = 100000
DEFINT A-Z
PRINT A
This prints 0, because the DEFINT
statement re-defines the variable as INTEGER.
When converting a float value to an int value, in case of overflow, we get max negative int. For example in:
a% = 40000.1
a%
would get -32768. The following would cause an overflow error however:
a% = 40000
QB 7.1 supports ON LOCAL ERROR...
statement which can be used to set up a sub-routine local error handler.
QB supports fixed strings declared like:
DIM x AS STRING * 10
x will not hold anything larger than 10 characters, and if a larger string is assigned to it, it is truncated.
Fixed-strings can also be used in TYPE blocks.
Encountering a RETURN statement without a GOSUB active would cause the "RETURN without GOSUB" error in QB. Currently we do not handle this case and the return statement would just throw away an active call frame (in case of a simple RETURN statement), or read a value from stack and attempt to jump to it (in case of "RETURN " statement). Both would be incorrect, and would likely cause a crash.
We can safely ignore DECLARE statements and use the actual SUB/FUNCTION definitions, as we do right now. However, we should make sure the DECLARE statements match with the SUB/FUNCTION blocks.
Notice that:
If an array is used without a DIM statement, it's implicitly defined as an array of size 10. For example:
x(3) = 30
PRINT x(3) ' <-- prints 30
PRINT x(5) ' <-- prints 0
PRINT x(15) ' <-- ERROR: Subscript out of range
Notice that without subscript, the variable is considered a different variable:
x(3) = 10
x = 4
PRINT x(3); x ' <-- prints " 10 4"
For example, a top-level DEFINT
statement has no bearing on the variables declared inside a SUB, even though their names match the letter range in the DEFINT statement.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.