Skip to content

Commit f5e0275

Browse files
committed
finished issue #9
1 parent 82ab824 commit f5e0275

17 files changed

Lines changed: 257 additions & 50 deletions

.vs/7Sharp/v16/.suo

0 Bytes
Binary file not shown.
12 KB
Binary file not shown.
0 Bytes
Binary file not shown.

7Sharp/7Sharp.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
<Compile Include="Editor\Editor.Designer.cs">
8484
<DependentUpon>Editor.cs</DependentUpon>
8585
</Compile>
86+
<Compile Include="Intrerpreter\FunctionDefinition.cs" />
8687
<Compile Include="Intrerpreter\Interpreter.cs" />
8788
<Compile Include="Intrerpreter\Sysfunctions.cs" />
8889
<Compile Include="Intrerpreter\TokenType.cs" />
@@ -95,6 +96,7 @@
9596
<Compile Include="Properties\AssemblyInfo.cs" />
9697
<Compile Include="Shell\CommandInfo.cs" />
9798
<Compile Include="Shell\Shell.cs" />
99+
<Compile Include="Shell\ShellFunctions.cs" />
98100
<Compile Include="Utils.cs" />
99101
</ItemGroup>
100102
<ItemGroup>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace _7Sharp.Intrerpreter
8+
{
9+
internal class FunctionDefinition
10+
{
11+
string Code;
12+
string[] ArgNames;
13+
Interpreter Interpreter;
14+
15+
public FunctionDefinition(string code, Interpreter i, string[] argNames)
16+
{
17+
Code = code;
18+
Interpreter = i;
19+
ArgNames = argNames;
20+
}
21+
22+
public dynamic Run(params dynamic[] args)
23+
{
24+
List<KeyValuePair<string, dynamic>> kvs = new List<KeyValuePair<string, dynamic>>();
25+
int i = 0;
26+
foreach (string n in ArgNames)
27+
{
28+
kvs.Add(new KeyValuePair<string, dynamic>(n, args[i]));
29+
i++;
30+
}
31+
if (ArgNames.Length == kvs.Count)
32+
{
33+
Interpreter.InternalRun(Code, out dynamic ret, false, kvs.ToArray());
34+
return ret;
35+
}
36+
return null;
37+
}
38+
39+
public int NumberOfArgs() => ArgNames.Length;
40+
}
41+
}

7Sharp/Intrerpreter/Interpreter.cs

Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ namespace _7Sharp.Intrerpreter
1919
using static TokenType;
2020
public class Interpreter
2121
{
22+
internal Dictionary<string, FunctionDefinition> userFunctions = new Dictionary<string, FunctionDefinition>();
2223
internal Dictionary<string, _7sFunction> functions = new Dictionary<string, _7sFunction>();
2324
internal Stack<int> loopIndexes = new Stack<int>();
2425
private ExpressionEvaluator evaluator = new ExpressionEvaluator();
@@ -30,6 +31,7 @@ public class Interpreter
3031
public Interpreter()
3132
{
3233
InitEvaluator();
34+
evaluator.PreEvaluateFunction += AddUserFunctions;
3335
var built = LexerBuilder.BuildLexer<TokenType>();
3436
if (built.Errors.FindAll(x => x.Level != sly.buildresult.ErrorLevel.WARN).Count != 0)
3537
{
@@ -51,6 +53,26 @@ public Interpreter()
5153
}
5254
}
5355

56+
private void AddUserFunctions(object sender, FunctionPreEvaluationEventArg e)
57+
{
58+
foreach (var kv in userFunctions)
59+
{
60+
if (kv.Key == e.Name)
61+
{
62+
if (e.Args.Count == kv.Value.NumberOfArgs())
63+
{
64+
e.CancelEvaluation = false;
65+
}
66+
else
67+
{
68+
WriteLineColor($"{e.Name} expects {kv.Value.NumberOfArgs()}, but you put {e.Args.Count}", Red);
69+
e.CancelEvaluation = true;
70+
}
71+
e.Value = kv.Value.Run(e.EvaluateArgs());
72+
}
73+
}
74+
}
75+
5476
private void InitEvaluator()
5577
{
5678
functions.Clear();
@@ -61,14 +83,18 @@ private void InitEvaluator()
6183
{
6284
evaluator.Variables.Add(f.Key, f.Value.Code);
6385
}
86+
foreach (ConsoleColor c in Enum.GetValues(typeof(ConsoleColor)).Cast<ConsoleColor>())
87+
{
88+
evaluator.Variables.Add(c.ToString(), c);
89+
}
6490
}
6591

6692
public void Run(string code)
6793
{
6894
code = evaluator.RemoveComments(code); //just to make parsing easier
6995
try
7096
{
71-
InternalRun(code, true);
97+
InternalRun(code, out _, true);
7298
}
7399
catch (Exception e)
74100
{
@@ -77,8 +103,16 @@ public void Run(string code)
77103
evaluator = new ExpressionEvaluator();
78104
}
79105

80-
private void InternalRun(string code, bool reset = true)
106+
internal void InternalRun(string code, out dynamic returnValue, bool reset = true, params KeyValuePair<string, dynamic>[] passedParams)
81107
{
108+
if (passedParams != null && passedParams.Length > 0)
109+
{
110+
foreach (var kv in passedParams)
111+
{
112+
evaluator.Variables.Add(kv.Key, kv.Value);
113+
}
114+
}
115+
returnValue = null;
82116
exitLoop = skipLoop = exit = false;
83117
if (exit)
84118
{
@@ -164,10 +198,30 @@ private void InternalRun(string code, bool reset = true)
164198
exitLoop = expression[0].TokenID == BREAK;
165199
skipLoop = !exitLoop;
166200
return;
167-
/*case RETURN:
168-
break;*/
201+
case RETURN:
202+
expression = expression.Skip(1).ToList(); //remove "return" keyword
203+
string expr = GetExpressionToToken(expression, SEMICOLON);
204+
try
205+
{
206+
returnValue = Evaluate(expr);
207+
}
208+
catch
209+
{
210+
returnValue = null;
211+
}
212+
return;
169213
}
170214
}
215+
else if (IsFunctionDef(expression))
216+
{
217+
string expr = GetExpressionToToken(expression, LBRACE);
218+
string[] args = GetArgs(expr).Replace(" ", string.Empty).Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
219+
int end = GetClosingBrace(tokens, i, out TokenList ts, out string inside);
220+
bool returns = ts.FindIndex(t => t.TokenID == RETURN) > -1;
221+
userFunctions.Add(expression[1].Value, new FunctionDefinition(inside, this, args));
222+
i = end;
223+
continue;
224+
}
171225
else if (IsVarExpression(expression))
172226
{
173227
string expr = GetExpressionToToken(expression, SEMICOLON);
@@ -200,7 +254,7 @@ private void InternalRun(string code, bool reset = true)
200254
loopIndexes.Push(0);
201255
for (int j = 0; j < times && !exitLoop; j++)
202256
{
203-
InternalRun(inside, false);
257+
InternalRun(inside, out _, false);
204258
loopIndexes.Push(loopIndexes.Pop() + 1);
205259
skipLoop = false;
206260
}
@@ -210,7 +264,7 @@ private void InternalRun(string code, bool reset = true)
210264
case WHILE:
211265
while ((bool)Evaluate(args) && !exitLoop)
212266
{
213-
InternalRun(inside, false);
267+
InternalRun(inside, out _, false);
214268
}
215269
break;
216270
}
@@ -233,6 +287,25 @@ private void InternalRun(string code, bool reset = true)
233287
}
234288
i--;
235289
}
290+
if (passedParams != null && passedParams.Length > 0)
291+
{
292+
foreach (var kv in passedParams)
293+
{
294+
evaluator.Variables.Remove(kv.Key);
295+
}
296+
}
297+
}
298+
299+
private bool IsFunctionDef(TokenList expression)
300+
{
301+
bool result = false;
302+
if (expression.Count >= 3)
303+
{
304+
result |= expression[0].TokenID == FUNCTION;
305+
result &= expression[1].TokenID == IDENTIFIER;
306+
result &= expression[2].TokenID == LPAREN;
307+
}
308+
return result;
236309
}
237310

238311
private void ProcessIf(TokenList expression, TokenList tokens, string code, ref int i)
@@ -259,7 +332,7 @@ private void ProcessIf(TokenList expression, TokenList tokens, string code, ref
259332
case IF:
260333
if ((bool)Evaluate(args))
261334
{
262-
InternalRun(inside, false);
335+
InternalRun(inside, out _, false);
263336
i = end;
264337
}
265338
else
@@ -285,7 +358,7 @@ private void ProcessIf(TokenList expression, TokenList tokens, string code, ref
285358
break;
286359
case ELSE:
287360
i = end;
288-
InternalRun(inside, false);
361+
InternalRun(inside, out _, false);
289362
break;
290363
}
291364
}
@@ -360,6 +433,10 @@ private string GetExpressionToToken(TokenList tokens, TokenType type)
360433
foreach (var t in tokens)
361434
{
362435
expr += t.Value;
436+
if (new TokenType[] { FUNCTION, IF, ELSE, RETURN }.Contains(t.TokenID))
437+
{
438+
expr += " ";
439+
}
363440
}
364441
var ts = lexer.Tokenize(expr).Tokens;
365442
var f = ts.Find(x => x.TokenID == type);

7Sharp/Intrerpreter/Sysfunctions.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,30 @@ namespace _7Sharp.Intrerpreter
1010
internal static class SystemFunctions
1111
{
1212
internal static Interpreter Interpreter = null;
13+
1314
internal static void Init(ref Interpreter interpreter)
1415
{
1516
Interpreter = interpreter;
1617
Interpreter.functions.Add("write", new _7sFunction("write", 1, new Action<dynamic>(Write)));
18+
Interpreter.functions.Add("read", new _7sFunction("read", 0, new Func<string>(Read)));
1719
Interpreter.functions.Add("getLoopIndex", new _7sFunction("getLoopIndex", 0, new Func<int>(GetLoopIndex)));
20+
Interpreter.functions.Add("fgColor", new _7sFunction("fgColor", 1, new Action<dynamic>(FgColor)));
21+
Interpreter.functions.Add("bgColor", new _7sFunction("bgColor", 1, new Action<dynamic>(BgColor)));
22+
}
23+
24+
static string Read()
25+
{
26+
return ReadLine();
27+
}
28+
29+
static void BgColor(dynamic c)
30+
{
31+
BackgroundColor = (ConsoleColor)c;
32+
}
33+
34+
static void FgColor(dynamic c)
35+
{
36+
ForegroundColor = (ConsoleColor)c;
1837
}
1938

2039
static void Write(dynamic s)

7Sharp/Intrerpreter/TokenType.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ public enum TokenType
2020
IDENTIFIER,
2121
[Lexeme(GenericToken.SugarToken, ";")]
2222
SEMICOLON,
23+
[Lexeme(GenericToken.SugarToken, ",")]
24+
COMMA,
2325
[Lexeme(GenericToken.SugarToken, "=")]
2426
ASSIGNMENT,
2527
[Lexeme(GenericToken.SugarToken, "(")]
@@ -66,6 +68,10 @@ public enum TokenType
6668
BREAK,
6769
[Lexeme(GenericToken.KeyWord, "continue")]
6870
CONTINUE,
71+
[Lexeme(GenericToken.KeyWord, "return")]
72+
RETURN,
73+
[Lexeme(GenericToken.KeyWord, "function")]
74+
FUNCTION,
6975
[Comment("//", "/*", "*/")]
7076
COMMENT
7177
}

7Sharp/Program.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ namespace _7Sharp
1717
internal class Program
1818
{
1919
internal static _7SShell shell = new _7SShell();
20+
2021
[STAThread]
2122
private static void Main(string[] args)
2223
{
@@ -26,7 +27,6 @@ private static void Main(string[] args)
2627
Read();
2728
return;
2829
}
29-
//init
3030
//title
3131
Title = "7Sharp";
3232
if (args.Length == 1)
@@ -36,6 +36,7 @@ private static void Main(string[] args)
3636
using (StreamReader sr = new StreamReader(args[0]))
3737
{
3838
shell.SetCode(sr.ReadToEnd());
39+
shell.Execute("run");
3940
}
4041
}
4142
catch (Exception e)
@@ -46,8 +47,8 @@ private static void Main(string[] args)
4647
}
4748
}
4849
shell.Run();
49-
WriteLineColor("Press enter to exit 7Sharp", Yellow);
50-
_ = ReadLine();
50+
WriteLineColor("Press any key to exit 7Sharp", Yellow);
51+
_ = ReadKey(true);
5152
}
5253
}
5354
}

0 commit comments

Comments
 (0)