Skip to content

Commit d5eeaed

Browse files
author
aafent
committed
WAIT statement and deeper async implementation
1 parent a89b49e commit d5eeaed

19 files changed

Lines changed: 541 additions & 300 deletions

FAST.FBasic.InteractiveConsole/FBasicIC.cs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ internal partial class FBasicIC
1515
string sourceProgram=null!;
1616
Interpreter basic= null!;
1717
ExecutionResult result = null!;
18+
bool asyncMode = true;
1819

19-
public void run(string iCommandArg)
20+
public async Task run(string iCommandArg)
2021
{
22+
2123
if (env == null ) setupEnvironment(); // run once
2224
iCommand = iCommandArg;
2325

@@ -33,7 +35,7 @@ public void run(string iCommandArg)
3335

3436
case "RUN":
3537
case "R":
36-
runFBasicProgram();
38+
await runFBasicProgram();
3739
break;
3840

3941
case "DUMP":
@@ -92,6 +94,14 @@ public void run(string iCommandArg)
9294
}
9395
break;
9496

97+
case "SYNC":
98+
if (asyncMode)
99+
Console.WriteLine("Switching to SYNCHRONOUS mode");
100+
else
101+
Console.WriteLine("Switching to ASYNCHRONOUS mode");
102+
asyncMode = !asyncMode;
103+
break;
104+
95105
case "S":
96106
Console.WriteLine("REVERSED SOURCE:");
97107
Console.WriteLine("---------------------------");
@@ -115,7 +125,7 @@ public void run(string iCommandArg)
115125

116126
}
117127

118-
private void runFBasicProgram()
128+
private async Task runFBasicProgram()
119129
{
120130

121131
var basProgramFile = Directory.GetFiles(programsFolder, startupName).FirstOrDefault();
@@ -151,7 +161,15 @@ private void runFBasicProgram()
151161
basic = new Interpreter(env.installBuiltIns, this.sourceProgram);
152162
env.SetupInterpreter(basic);
153163

154-
result=basic.ExecWithResult();
164+
if (asyncMode)
165+
{
166+
result = await basic.ExecWithResultAsync();
167+
}
168+
else
169+
{
170+
result = basic.ExecWithResult();
171+
}
172+
155173

156174
if (result.hasError)
157175
{
@@ -161,7 +179,10 @@ private void runFBasicProgram()
161179
else
162180
{
163181
Console.WriteLine();
164-
Console.WriteLine("....................end of program....................");
182+
if (asyncMode)
183+
Console.WriteLine("....................end of async program....................");
184+
else
185+
Console.WriteLine("....................end of program....................");
165186
Console.WriteLine($"Result: {result.value}");
166187
Console.WriteLine();
167188
}

FAST.FBasic.InteractiveConsole/FBasicIC_Methods.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public void help()
3434
Console.WriteLine("HELP | ? :: Show this help");
3535
Console.WriteLine("QUIT | Q :: Exit of the test console program");
3636
Console.WriteLine("CLS | :: Clear the screen");
37+
Console.WriteLine("SYNC | :: switch between async and sync mode");
3738
Console.WriteLine();
3839
Console.WriteLine("BC1 | :: Run Business Case 1 - Credit Scoring");
3940
Console.WriteLine();

FAST.FBasic.InteractiveConsole/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
{
2121
try
2222
{
23-
FBASIC.run(iCommand);
23+
await FBASIC.run(iCommand);
2424
}
2525
catch (Exception ex)
2626
{
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
REM Test program for WAIT
2+
REM
3+
REM
4+
for i=1 To 3
5+
print i;
6+
wait 1000
7+
next i
8+
9+
halt
10+

FAST.FBasic.LibraryToolkit/Core/FBasic_Delegates.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,16 @@ namespace FAST.FBasicInterpreter
4747
public delegate Value FBasicFunction(IInterpreter interpreter, List<Value> args);
4848

4949
/// <summary>
50-
/// A new statement delegate
50+
/// A new sync statement delegate
5151
/// </summary>
5252
/// <param name="interpreter">The instance of this interpreter</param>
53-
public delegate void FBasicStatement(IInterpreter interpreter);
53+
public delegate void FBasicStatementSync(IInterpreter interpreter);
54+
55+
/// <summary>
56+
/// A new async statement delegate
57+
/// </summary>
58+
/// <param name="interpreter">The instance of this interpreter</param>
59+
public delegate Task FBasicStatementAsync(IInterpreter interpreter);
5460

5561
/// <summary>
5662
/// Delegate type for GetNextToken Method

FAST.FBasic.LibraryToolkit/Core/InterpreterHelper.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public static bool IsStatement(Token token)
4040
case Token.EndForEach:
4141
case Token.SData:
4242
case Token.RInput:
43+
case Token.Wait:
4344
return true;
4445

4546
default:

FAST.FBasic.LibraryToolkit/Core/Token.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public enum Token
3535
EndForEach,
3636
SData,
3737
RInput,
38+
Wait,
3839

3940

4041
NewLine,

FAST.FBasic.LibraryToolkit/Interfaces/IInterpreter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public interface IInterpreter
1414
void AddCollection(string name, IBasicCollection collection);
1515
void AddDataAdapter(IFBasicDataAdapter adapter);
1616
void AddFunction(string name, FBasicFunction function);
17-
void AddStatement(string name, FBasicStatement statement);
17+
void AddStatement(string name, FBasicStatementSync statement);
1818
void RemoveStatement(string name);
1919
void RefreshLexerStatements();
2020

FAST.FBasicInterpreter/Core/Interpreter.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ public partial class Interpreter : IFBasicError, IInterpreter
5353
private Stack<Marker> instructionStack; // for return points
5454

5555
private Dictionary<string, FBasicFunction> funcs; // all mapped functions
56-
private Dictionary<string, FBasicStatement> statements; // all mapped statements
56+
private Dictionary<string, FBasicStatementSync> statementsSync; // all mapped statements
57+
private Dictionary<string, FBasicStatementAsync> statementsAsync; // all mapped statements
5758
private int ifCounter; // (NOT WORKING, TO RECHECK) counter used for matching "if" with "else"
5859

5960
private Marker lineMarker; // current line marker
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
namespace FAST.FBasicInterpreter
2+
{
3+
/// <summary>
4+
/// The interpreter factory of the FBASIC
5+
/// Part: THE FBASIC STATEMENT METHODS
6+
/// </summary>
7+
public partial class Interpreter : IFBasicError
8+
{
9+
/*
10+
* Execution flow: A->B->C
11+
* [A]BuildIn_Statement -> [B]your code to manipulate keywords -> [C]BuildIn_NotAStatement
12+
* Rules:
13+
* if A.tokenfound -> C
14+
* From B do always -> C
15+
* if C.doStatement -> call again (recursive) the method (eg Statement())
16+
*/
17+
18+
private void BuildIn_Statement(out Token keyword, out bool keywordFound)
19+
{
20+
keywordFound = true;
21+
keyword = lastToken;
22+
GetNextToken();
23+
if (keyword == Token.AddOn) // not in switch->default, for best performance
24+
{
25+
keywordFound = false;
26+
return;
27+
}
28+
switch (keyword)
29+
{
30+
// (v) statement tokens
31+
case Token.Print: Print(); break;
32+
case Token.Input: Input(); break;
33+
case Token.Goto: Goto(); break;
34+
case Token.Gosub: Gosub(); break;
35+
case Token.Return: Return(); break;
36+
case Token.If: If(); break;
37+
case Token.Else: Else(); break;
38+
case Token.EndIf: break;
39+
case Token.For: For(); break;
40+
case Token.Next: Next(); break;
41+
case Token.Let: Let(); break;
42+
case Token.End: Halt(); break; // synonyms: END, HALT
43+
case Token.Assert: Assert(); break;
44+
case Token.Result: ResultStatement(); break;
45+
case Token.Dump: DumpStatement(); break;
46+
case Token.Call: CallStatement(); break;
47+
case Token.Chain: ChainStatement(); break;
48+
case Token.Eval: EvalStatement(); break;
49+
case Token.ForEach: ForEachStatement(); break;
50+
case Token.EndForEach: EndForEachStatement(); break;
51+
case Token.SData: SDataStatement(); break;
52+
case Token.RInput: RInputStatement(); break;
53+
54+
default:
55+
keywordFound = false;
56+
break;
57+
}
58+
}
59+
60+
private void BuildIn_NotAStatement(Token keyword, bool keywordAlreadyFound, out bool doStatement)
61+
{
62+
doStatement = false;
63+
if (!keywordAlreadyFound)
64+
{
65+
switch (keyword)
66+
{
67+
// (v) non-statement tokens
68+
case Token.Identifier:
69+
if (lastToken == Token.Equal) Let();
70+
else if (lastToken == Token.Colon) Label();
71+
else goto default;
72+
break;
73+
case Token.EOF:
74+
exit = true;
75+
break;
76+
default:
77+
string msg2 = "";
78+
switch (keyword)
79+
{
80+
case Token.Identifier:
81+
msg2 = lex.Identifier;
82+
break;
83+
case Token.Value:
84+
msg2 = lex.Value.ToString();
85+
break;
86+
default:
87+
msg2 = "";
88+
break;
89+
}
90+
Error(Errors.E106_ExpectingKeyword(keyword.ToString(), msg2));
91+
break;
92+
}
93+
}
94+
if (lastToken == Token.Colon)
95+
{
96+
// we can execute more statements in single line if we use ";"
97+
while (GetNextToken() == Token.NewLine) { } // GetNextToken but bypass any NewLine
98+
doStatement = true; // eg: Statement() or StatementAsync() // The caller should do Just that
99+
}
100+
}
101+
102+
}
103+
}

0 commit comments

Comments
 (0)