1
1
Fork 0
mirror of https://github.com/boxgaming/qbjs.git synced 2024-05-28 19:00:14 +00:00

Added support for static variable declarations (#49). Added support for shared variable declarations in functions and subs (#50)

This commit is contained in:
boxgaming 2023-06-14 14:14:58 -05:00
parent fb0af807b2
commit 595b8f5864
3 changed files with 137 additions and 87 deletions

View file

@ -121,7 +121,7 @@
<div>
<img id="logo" src="logo.png" onclick="window.open('https://github.com/boxgaming/qbjs/wiki', '_blank')">
<p>QBJS - QBasic for the Web!</p>
<p>Version: 0.7.3</p>
<p>Version: 0.8.0</p>
<p></p>
<p>
QBJS brings the fun and accessibility of QBasic to the browser.<br/>
@ -141,7 +141,7 @@
</body>
<script language="javascript" src="vfs.js"></script>
<script language="javascript" src="gx/gx.js"></script>
<script language="javascript" src="qb.js?v=0.7.3"></script>
<script language="javascript" src="qb2js.js"></script>
<script language="javascript" src="qbjs-ide.js?v=0.7.3.1"></script>
<script language="javascript" src="qb.js?v=0.8.0"></script>
<script language="javascript" src="qb2js.js?v=0.8.0"></script>
<script language="javascript" src="qbjs-ide.js?v=0.8.0"></script>
</html>

101
qb2js.js
View file

@ -1,4 +1,5 @@
async function _QBCompiler() {
/* static method variables: */
// Option _Explicit
// $Console
@ -33,6 +34,7 @@ async function _QBCompiler() {
var currentMethod = ''; /* STRING */
var currentModule = ''; /* STRING */
var programMethods = 0; /* INTEGER */
var staticVarLine = 0; /* INTEGER */
if (QB.func_Command() != "" ) {
await sub_QBToJS( QB.func_Command(), FILE, "");
await sub_PrintJS();
@ -68,6 +70,8 @@ if (QB.halted()) { return; }
} else if ( sourceType == FILE) {
await sub_AddJSLine( 0, "async function init() {");
}
await sub_AddJSLine( 0, "/* static method variables: */ ");
staticVarLine = (QB.func_UBound( jsLines));
if (! selfConvert && moduleName == "" ) {
await sub_AddJSLine( 0, "QB.start();");
}
@ -180,6 +184,7 @@ if (QB.halted()) { return; }
}
currentMethod = "";
programMethods = 0;
staticVarLine = 0;
}
async function sub_InitData() {
if (QB.halted()) { return; }
@ -291,7 +296,7 @@ if (QB.halted()) { return; }
await sub_AddConst( (QB.func__Trim( cleft)));
}
}
} else if ( first == "DIM" || first == "REDIM" || first == "STATIC" ) {
} else if ( first == "DIM" || first == "REDIM" || first == "STATIC" || first == "SHARED" ) {
js = (await func_DeclareVar( parts , i));
} else if ( first == "SELECT" ) {
caseVar = await func_GenJSVar();
@ -1413,6 +1418,8 @@ var DeclareVar = null;
isGlobal = False;
var isArray = 0; /* INTEGER */
isArray = False;
var isStatic = 0; /* INTEGER */
isStatic = False;
var arraySize = ''; /* STRING */
var pstart = 0; /* INTEGER */
var bvar = {type:'',name:'',jsname:'',isConst:0,isArray:0,arraySize:0,typeId:0}; /* VARIABLE */
@ -1425,6 +1432,23 @@ var DeclareVar = null;
js = "";
var preserve = ''; /* STRING */
preserve = "false";
if ((QB.func_UCase( QB.arrayValue(parts, [ 1]).value)) == "STATIC" ) {
if ( currentMethod == "" ) {
await sub_AddWarning( lineNumber, "STATIC must be used within a SUB/FUNCTION");
DeclareVar = "";
return DeclareVar;
} else {
isStatic = True;
}
} else if ((QB.func_UCase( QB.arrayValue(parts, [ 1]).value)) == "SHARED" ) {
if ( currentMethod == "" ) {
await sub_AddWarning( lineNumber, "SHARED must be used within a SUB/FUNCTION");
DeclareVar = "";
} else {
DeclareVar = "/* shared variable(s): " + (await func_Join( parts , 1, - 1, " ")) + " */";
}
return DeclareVar;
}
var i = 0; /* INTEGER */
var ___v4687001 = 0; for ( i= 1; i <= (QB.func_UBound( parts)); i= i + 1) { if (QB.halted()) { return; } ___v4687001++; if (___v4687001 % 100 == 0) { await QB.autoLimit(); }
if ((QB.func_UCase( QB.arrayValue(parts, [ i]).value)) == "AS" ) {
@ -1459,24 +1483,7 @@ var DeclareVar = null;
arraySize = "";
bvar.name = vname;
}
bvar.jsname = "";
if (! bvar.isArray) {
js = js + "var " + bvar.name + " = " + (await func_InitTypeValue( bvar.type)) + "; ";
} else {
if ((await func_FindVariable( bvar.name, findVar, True)) ) {
js = js + "QB.resizeArray(" + bvar.name + ", [" + (await func_FormatArraySize( arraySize)) + "], " + (await func_InitTypeValue( bvar.type)) + ", " + preserve + "); ";
} else {
js = js + "var " + bvar.name + " = QB.initArray([" + (await func_FormatArraySize( arraySize)) + "], " + (await func_InitTypeValue( bvar.type)) + "); ";
}
}
if ( isGlobal) {
await sub_AddVariable( bvar, globalVars);
} else {
await sub_AddVariable( bvar, localVars);
}
if ( PrintDataTypes) {
js = js + " /* " + bvar.type + " */ ";
}
js = (await func_RegisterVar( bvar, js, isGlobal, isStatic, preserve, arraySize));
}
} else {
var vpartcount = 0; /* INTEGER */
@ -1485,7 +1492,7 @@ var DeclareVar = null;
var ___v6226967 = 0; for ( i= 1; i <= (QB.func_UBound( parts)); i= i + 1) { if (QB.halted()) { return; } ___v6226967++; if (___v6226967 % 100 == 0) { await QB.autoLimit(); }
var p = ''; /* STRING */
p = (QB.func_UCase( QB.arrayValue(parts, [ i]).value));
if ( p == "DIM" || p == "REDIM" || p == "SHARED" || p == "_PRESERVE" ) {
if ( p == "DIM" || p == "REDIM" || p == "SHARED" || p == "_PRESERVE" || p == "STATIC" ) {
nextIdx = i + 1;
}
}
@ -1511,29 +1518,45 @@ var DeclareVar = null;
bvar.isArray = False;
arraySize = "";
}
bvar.jsname = "";
if (! bvar.isArray) {
js = js + "var " + bvar.name + " = " + (await func_InitTypeValue( bvar.type)) + "; ";
} else {
if ((await func_FindVariable( bvar.name, findVar, True)) ) {
js = js + "QB.resizeArray(" + bvar.name + ", [" + (await func_FormatArraySize( arraySize)) + "], " + (await func_InitTypeValue( bvar.type)) + ", " + preserve + "); ";
} else {
js = js + "var " + bvar.name + " = QB.initArray([" + (await func_FormatArraySize( arraySize)) + "], " + (await func_InitTypeValue( bvar.type)) + "); ";
}
}
if ( isGlobal) {
await sub_AddVariable( bvar, globalVars);
} else {
await sub_AddVariable( bvar, localVars);
}
if ( PrintDataTypes) {
js = js + " /* " + bvar.type + " */ ";
}
js = (await func_RegisterVar( bvar, js, isGlobal, isStatic, preserve, arraySize));
}
}
DeclareVar = js;
if ( isStatic) {
QB.arrayValue(jsLines, [ staticVarLine]).value .text = QB.arrayValue(jsLines, [ staticVarLine]).value .text + js;
DeclareVar = "/* static variable(s): " + (await func_Join( parts , 1, - 1, " ")) + " */";
} else {
DeclareVar = js;
}
return DeclareVar;
}
async function func_RegisterVar(bvar/*VARIABLE*/,js/*STRING*/,isGlobal/*INTEGER*/,isStatic/*INTEGER*/,preserve/*STRING*/,arraySize/*STRING*/) {
if (QB.halted()) { return; }
var RegisterVar = null;
var findVar = {type:'',name:'',jsname:'',isConst:0,isArray:0,arraySize:0,typeId:0}; /* VARIABLE */
bvar.jsname = (await func_RemoveSuffix( bvar.name));
if ( isStatic) {
bvar.jsname = "$" + currentMethod + "__" + bvar.jsname;
}
if (! bvar.isArray) {
js = js + "var " + bvar.jsname + " = " + (await func_InitTypeValue( bvar.type)) + "; ";
} else {
if ((await func_FindVariable( bvar.name, findVar, True)) ) {
js = js + "QB.resizeArray(" + bvar.jsname + ", [" + (await func_FormatArraySize( arraySize)) + "], " + (await func_InitTypeValue( bvar.type)) + ", " + preserve + "); ";
} else {
js = js + "var " + bvar.jsname + " = QB.initArray([" + (await func_FormatArraySize( arraySize)) + "], " + (await func_InitTypeValue( bvar.type)) + "); ";
}
}
if ( isGlobal) {
await sub_AddVariable( bvar, globalVars);
} else {
await sub_AddVariable( bvar, localVars);
}
if ( PrintDataTypes) {
js = js + " /* " + bvar.type + " */ ";
}
RegisterVar = js;
return RegisterVar;
}
async function func_FormatArraySize(sizeString/*STRING*/) {
if (QB.halted()) { return; }
var FormatArraySize = null;

View file

@ -76,6 +76,7 @@ Dim Shared modLevel As Integer
Dim Shared As String currentMethod
Dim Shared As String currentModule
Dim Shared As Integer programMethods
Dim Shared As Integer staticVarLine
' Only execute the conversion from the native version if we have been passed the
' source file to convert on the command line
@ -126,6 +127,12 @@ Sub QBToJS (source As String, sourceType As Integer, moduleName As String)
' AddJSLine 0, "try {"
End If
' Add a placeholder line for static method variables
' This line will be appended to as static variable declarations are encountered
AddJSLine 0, "/* static method variables: */ "
staticVarLine = UBound(jsLines)
If Not selfConvert And moduleName = "" Then AddJSLine 0, "QB.start();"
If Not selfConvert And moduleName = "" Then
@ -245,6 +252,7 @@ Sub ResetDataStructures
End If
currentMethod = ""
programMethods = 0
staticVarLine = 0
End Sub
Sub InitData
@ -354,7 +362,7 @@ Sub ConvertLines (firstLine As Integer, lastLine As Integer, functionName As Str
End If
Next constIdx
ElseIf first = "DIM" Or first = "REDIM" Or first = "STATIC" Then
ElseIf first = "DIM" Or first = "REDIM" Or first = "STATIC" Or first = "SHARED" Then
js = DeclareVar(parts(), i)
@ -1537,6 +1545,7 @@ Function DeclareVar$ (parts() As String, lineNumber As Integer)
Dim vtypeIndex As Integer: vtypeIndex = 4
Dim isGlobal As Integer: isGlobal = False
Dim isArray As Integer: isArray = False
Dim isStatic As Integer: isStatic = False
Dim arraySize As String
Dim pstart As Integer
Dim bvar As Variable
@ -1548,6 +1557,28 @@ Function DeclareVar$ (parts() As String, lineNumber As Integer)
Dim js As String: js = ""
Dim preserve As String: preserve = "false"
If UCase$(parts(1)) = "STATIC" Then
If currentMethod = "" Then
AddWarning lineNumber, "STATIC must be used within a SUB/FUNCTION"
DeclareVar = ""
Exit Function
Else
isStatic = True
End If
ElseIf UCase$(parts(1)) = "SHARED" Then
If currentMethod = "" Then
AddWarning lineNumber, "SHARED must be used within a SUB/FUNCTION"
DeclareVar = ""
Else
' We get this for "free" due to the fact that all variables
' declared in the main module are effectively shared.
' This will need to be revisited when support for
' implicit variable declaration is added
DeclareVar = "/* shared variable(s): " + Join(parts(), 1, -1, " ") + " */"
End If
Exit Function
End If
Dim i As Integer
For i = 1 To UBound(parts)
If UCase$(parts(i)) = "AS" Then asIdx = i
@ -1583,27 +1614,8 @@ Function DeclareVar$ (parts() As String, lineNumber As Integer)
arraySize = ""
bvar.name = vname
End If
bvar.jsname = ""
' TODO: this code is in two places - refactor into a separate function
If Not bvar.isArray Then
js = js + "var " + bvar.name + " = " + InitTypeValue(bvar.type) + "; "
Else
If FindVariable(bvar.name, findVar, True) Then
js = js + "QB.resizeArray(" + bvar.name + ", [" + FormatArraySize(arraySize) + "], " + InitTypeValue(bvar.type) + ", " + preserve + "); "
Else
js = js + "var " + bvar.name + " = QB.initArray([" + FormatArraySize(arraySize) + "], " + InitTypeValue(bvar.type) + "); "
End If
End If
If isGlobal Then
AddVariable bvar, globalVars()
Else
AddVariable bvar, localVars()
End If
If PrintDataTypes Then js = js + " /* " + bvar.type + " */ "
js = RegisterVar(bvar, js, isGlobal, isStatic, preserve, arraySize)
Next i
@ -1615,7 +1627,7 @@ Function DeclareVar$ (parts() As String, lineNumber As Integer)
For i = 1 To UBound(parts)
Dim p As String
p = UCase$(parts(i))
If p = "DIM" Or p = "REDIM" Or p = "SHARED" Or p = "_PRESERVE" Then
If p = "DIM" Or p = "REDIM" Or p = "SHARED" Or p = "_PRESERVE" Or p = "STATIC" Then
nextIdx = i + 1
End If
Next i
@ -1646,32 +1658,47 @@ Function DeclareVar$ (parts() As String, lineNumber As Integer)
bvar.isArray = False
arraySize = ""
End If
bvar.jsname = ""
' TODO: this code is in two places - refactor into a separate function
If Not bvar.isArray Then
js = js + "var " + bvar.name + " = " + InitTypeValue(bvar.type) + "; "
Else
If FindVariable(bvar.name, findVar, True) Then
js = js + "QB.resizeArray(" + bvar.name + ", [" + FormatArraySize(arraySize) + "], " + InitTypeValue(bvar.type) + ", " + preserve + "); "
Else
js = js + "var " + bvar.name + " = QB.initArray([" + FormatArraySize(arraySize) + "], " + InitTypeValue(bvar.type) + "); "
End If
End If
If isGlobal Then
AddVariable bvar, globalVars()
Else
AddVariable bvar, localVars()
End If
If PrintDataTypes Then js = js + " /* " + bvar.type + " */ "
js = RegisterVar(bvar, js, isGlobal, isStatic, preserve, arraySize)
Next i
End If
DeclareVar = js
If isStatic Then
jsLines(staticVarLine).text = jsLines(staticVarLine).text + js
DeclareVar = "/* static variable(s): " + Join(parts(), 1, -1, " ") + " */"
Else
DeclareVar = js
End If
End Function
Function RegisterVar$ (bvar As Variable, js As String, isGlobal As Integer, isStatic As Integer, preserve As String, arraySize As String)
Dim findVar As Variable
bvar.jsname = RemoveSuffix(bvar.name)
If isStatic Then
bvar.jsname = "$" + currentMethod + "__" + bvar.jsname
End If
If Not bvar.isArray Then
js = js + "var " + bvar.jsname + " = " + InitTypeValue(bvar.type) + "; "
Else
If FindVariable(bvar.name, findVar, True) Then
js = js + "QB.resizeArray(" + bvar.jsname + ", [" + FormatArraySize(arraySize) + "], " + InitTypeValue(bvar.type) + ", " + preserve + "); "
Else
js = js + "var " + bvar.jsname + " = QB.initArray([" + FormatArraySize(arraySize) + "], " + InitTypeValue(bvar.type) + "); "
End If
End If
If isGlobal Then
AddVariable bvar, globalVars()
Else
AddVariable bvar, localVars()
End If
If PrintDataTypes Then js = js + " /* " + bvar.type + " */ "
RegisterVar = js
End Function
Function FormatArraySize$ (sizeString As String)