Skip to content

Commit

Permalink
changed "repeat until" loop to "repeat times"
Browse files Browse the repository at this point in the history
Added setBackground function
Renamed setStepDuration to setStep
  • Loading branch information
Walperr committed Nov 25, 2023
1 parent a47e871 commit e734cd6
Show file tree
Hide file tree
Showing 12 changed files with 84 additions and 60 deletions.
18 changes: 10 additions & 8 deletions LanguageInterpreter/Execution/ExpressionEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,20 +290,22 @@ public Result<SyntaxException, object> Evaluate(CancellationToken token)
return null;
}

object? value;
object? value = Empty.Instance;

if (Visit(expression.CountExpression, token) is not double count)
return null;

int i = 0;

while (true)
{
if (i >= count)
break;
i++;

value = Visit(expression.Body, token);
if (value is null)
return null;

var condition = Visit(expression.Condition, token);
if (condition is null)
return null;

if ((bool)condition)
break;
}

return value;
Expand Down
8 changes: 4 additions & 4 deletions LanguageInterpreter/Execution/TypeResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -279,14 +279,14 @@ public Result<SyntaxException, Type> Resolve(CancellationToken token)
return null;
}

var conditionType = Visit(expression.Condition, token);
var countType = Visit(expression.CountExpression, token);

if (conditionType is null)
if (countType is null)
return null;

if (conditionType != typeof(bool))
if (countType != typeof(double))
{
_errors.Add(new ExpectedOtherTypeException(expression.Condition, conditionType, typeof(bool)));
_errors.Add(new ExpectedOtherTypeException(expression.CountExpression, countType, typeof(double)));
return null;
}

Expand Down
10 changes: 5 additions & 5 deletions LanguageParser.Tests/UnitTest1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,8 @@ public void CanParseRepeatExpression()
{
var texts = new[]
{
"repeat expression() until (true)", "repeat { expression() foo(e, a) 5 - 8 } until (true)",
"repeat expression(); until (true);", "repeat { expression(); foo(e, a); 5 - 8; } until (true);"
"repeat count() times expression()", "repeat 50 times { expression() foo(e, a) 5 - 8 }",
"repeat count(); times expression();", "repeat 50; times { expression(); foo(e, a); 5 - 8; };"
};

foreach (var text in texts)
Expand Down Expand Up @@ -355,7 +355,7 @@ public void CanParseSequenceOfExpressions()
public void CanParseComplexString()
{
var text =
"number a;\nnumber b;\n\nstring arg1;\n\nstring arg2 = \"some string;\"\n\nbool boolValue = false \n \nsomeFunction(arg1, arg2)\n\nif (boolValue)\n arg1 = someFunction2(arg)\n\nif (false)\n a = someFunction3(arg)\nelse\n b = someFunction4(arg)\n\nif (predicat())\n print(\"Hello, world\")\n\nwhile(true)\n{\n Function1()\n Function2()\n Function3()\n number c = (4 + 3) * 2.5 - 38 / 2\n}\n\nfor (;;)\n{\n ForBody()\n}\n\nrepeat Expression() until (true)\n\nfor (i = 0; i <= 23; i = i + 1)\n ForBody()\n\nfor (;i > 0;)\n{}\n\n{\n Expression1()\n Expression2()\n\n a + b + 4\n}\n\nif (1)\n if (2)\n DoSomething()\n else\n if (3)\n doOther()\n else\n print(\"String\")\n\n\nif (1)\n{\n if (2)\n DoSomething()\n else\n if (3)\n doOther()\n}\nelse\n print(\"String\")";
"number a;\nnumber b;\n\nstring arg1;\n\nstring arg2 = \"some string;\"\n\nbool boolValue = false \n \nsomeFunction(arg1, arg2)\n\nif (boolValue)\n arg1 = someFunction2(arg)\n\nif (false)\n a = someFunction3(arg)\nelse\n b = someFunction4(arg)\n\nif (predicat())\n print(\"Hello, world\")\n\nwhile(true)\n{\n Function1()\n Function2()\n Function3()\n number c = (4 + 3) * 2.5 - 38 / 2\n}\n\nfor (;;)\n{\n ForBody()\n}\n\nrepeat 100 times Expression()\n\nfor (i = 0; i <= 23; i = i + 1)\n ForBody()\n\nfor (;i > 0;)\n{}\n\n{\n Expression1()\n Expression2()\n\n a + b + 4\n}\n\nif (1)\n if (2)\n DoSomething()\n else\n if (3)\n doOther()\n else\n print(\"String\")\n\n\nif (1)\n{\n if (2)\n DoSomething()\n else\n if (3)\n doOther()\n}\nelse\n print(\"String\")";

_testOutputHelper.WriteLine(text);

Expand All @@ -375,7 +375,7 @@ public void CanParseComplexString()
public void CanParseComplexStringWithSemicolons()
{
var text =
"number a;\nnumber b;\n\nstring arg1;\n\nstring arg2 = \"some string\";\n\nbool boolValue = false; \n \nsomeFunction(arg1, arg2);\n\nif (boolValue)\n arg1 = someFunction2(arg);\n\nif (false)\n a = someFunction3(arg);\nelse\n b = someFunction4(arg);\n\nif (predicat())\n print(\"Hello, world\");\n\nwhile(true)\n{\n Function1();\n Function2();\n Function3();\n number c = (4 + 3) * 2.5 - 38 / 2;\n}\n\nfor (;;)\n{\n ForBody();\n}\n\nrepeat Expression() until (true)\n\nfor (i = 0; i <= 23; i = i + 1)\n ForBody();\n\nfor (;i > 0;)\n{}\n\n{\n Expression1();\n Expression2();\n\n a + b + 4;\n}\n\nif (1)\n if (2)\n DoSomething();\n else\n if (3)\n doOther();\n else\n print(\"String\");\n\n\nif (1)\n{\n if (2)\n DoSomething();\n else\n if (3)\n doOther();\n}\nelse\n print(\"String\");";
"number a;\nnumber b;\n\nstring arg1;\n\nstring arg2 = \"some string\";\n\nbool boolValue = false; \n \nsomeFunction(arg1, arg2);\n\nif (boolValue)\n arg1 = someFunction2(arg);\n\nif (false)\n a = someFunction3(arg);\nelse\n b = someFunction4(arg);\n\nif (predicat())\n print(\"Hello, world\");\n\nwhile(true)\n{\n Function1();\n Function2();\n Function3();\n number c = (4 + 3) * 2.5 - 38 / 2;\n}\n\nfor (;;)\n{\n ForBody();\n}\n\nrepeat 100 times Expression()\n\nfor (i = 0; i <= 23; i = i + 1)\n ForBody();\n\nfor (;i > 0;)\n{}\n\n{\n Expression1();\n Expression2();\n\n a + b + 4;\n}\n\nif (1)\n if (2)\n DoSomething();\n else\n if (3)\n doOther();\n else\n print(\"String\");\n\n\nif (1)\n{\n if (2)\n DoSomething();\n else\n if (3)\n doOther();\n}\nelse\n print(\"String\");";

_testOutputHelper.WriteLine(text);

Expand Down Expand Up @@ -671,7 +671,7 @@ public void CanUsePredefinedFunctionsAndVariablesInLoops()
Assert.NotNull(interpreter);

const string text =
"print(\"start\")\n\nnumber someNumber = 6\n\nfor (number i = 0; i < someNumber; i = i + 1)\n print(\"current i = \" + i)\n\nnumber i = 0\n\nwhile (i > someNumber / 2)\n{\n print(i + \": PI still equals \" + PI)\n\n i = i - 1\n}\n\nnumber j = 0\n\nrepeat\n{\n print(\"Repeat print E\")\n print(E)\n\n j = j + 1\n} until (j >= 5)\n\nprint(\"done\")";
"print(\"start\")\n\nnumber someNumber = 6\n\nfor (number i = 0; i < someNumber; i = i + 1)\n print(\"current i = \" + i)\n\nnumber i = 0\n\nwhile (i > someNumber / 2)\n{\n print(i + \": PI still equals \" + PI)\n\n i = i - 1\n}\n\nnumber j = 0\n\nrepeat 5 times\n{\n print(\"Repeat print E\")\n print(E)\n}\nprint(\"done\")";

_testOutputHelper.WriteLine(text);
_testOutputHelper.WriteLine("\nresult:\n");
Expand Down
4 changes: 2 additions & 2 deletions LanguageParser/Common/SyntaxKind.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ public enum SyntaxKind
/// </summary>
Repeat,
/// <summary>
/// until keyword
/// times keyword
/// </summary>
Until,
Times,
/// <summary>
/// for keyword
/// </summary>
Expand Down
21 changes: 7 additions & 14 deletions LanguageParser/Expressions/RepeatExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,25 @@ namespace LanguageParser.Expressions;

public sealed class RepeatExpression : ExpressionBase
{
internal RepeatExpression(Token repeatToken, ExpressionBase body, Token untilToken, Token openParenthesis,
ExpressionBase condition, Token closeParenthesis) : base(SyntaxKind.RepeatExpression)
internal RepeatExpression(Token repeatToken, ExpressionBase countExpression, Token timesToken, ExpressionBase body) : base(SyntaxKind.RepeatExpression)
{
RepeatToken = repeatToken;
CountExpression = countExpression;
TimesToken = timesToken;
Body = body;
UntilToken = untilToken;
OpenParenthesis = openParenthesis;
Condition = condition;
CloseParenthesis = closeParenthesis;
}

public Token RepeatToken { get; }
public ExpressionBase CountExpression { get; }
public Token TimesToken { get; }
public ExpressionBase Body { get; }
public Token UntilToken { get; }
public Token OpenParenthesis { get; }
public ExpressionBase Condition { get; }
public Token CloseParenthesis { get; }

public override IEnumerable<ISyntaxElement> GetAllElements()
{
yield return RepeatToken;
yield return CountExpression;
yield return TimesToken;
yield return Body;
yield return UntilToken;
yield return OpenParenthesis;
yield return Condition;
yield return CloseParenthesis;
}

public override void Visit(ExpressionVisitor visitor)
Expand Down
2 changes: 1 addition & 1 deletion LanguageParser/Lexer/Syntax.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static string GetLexemeForToken(SyntaxKind kind)
SyntaxKind.If => "if",
SyntaxKind.Else => "else",
SyntaxKind.Repeat => "repeat",
SyntaxKind.Until => "until",
SyntaxKind.Times => "times",
SyntaxKind.While => "while",
SyntaxKind.For => "for",
SyntaxKind.Number => "number",
Expand Down
4 changes: 2 additions & 2 deletions LanguageParser/Lexer/Tokenizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ private Token ReadToken()
}
}

private Token AdjustKeyword(Token token)
private static Token AdjustKeyword(Token token)
{
return token.Lexeme switch
{
"if" => new Token(SyntaxKind.If, token.Lexeme, token.Range.Start),
"else" => new Token(SyntaxKind.Else, token.Lexeme, token.Range.Start),
"repeat" => new Token(SyntaxKind.Repeat, token.Lexeme, token.Range.Start),
"until" => new Token(SyntaxKind.Until, token.Lexeme, token.Range.Start),
"times" => new Token(SyntaxKind.Times, token.Lexeme, token.Range.Start),
"while" => new Token(SyntaxKind.While, token.Lexeme, token.Range.Start),
"for" => new Token(SyntaxKind.For, token.Lexeme, token.Range.Start),
"number" => new Token(SyntaxKind.Number, token.Lexeme, token.Range.Start),
Expand Down
24 changes: 8 additions & 16 deletions LanguageParser/Parser/ExpressionsParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -333,27 +333,19 @@ private bool TryParseSeparated(SyntaxKind open, SyntaxKind close, SyntaxKind sep
if (repeatToken is null)
return null;

var body = ParseExpression();
if (body is null)
return null;

var untilToken = EatToken(SyntaxKind.Until);
if (untilToken is null)
return null;

var openToken = EatToken(SyntaxKind.OpenParenthesis);
if (openToken is null)
var count = ParseExpression();
if (count is null)
return null;

var condition = ParseExpression();
if (condition is null)
var timesToken = EatToken(SyntaxKind.Times);
if (timesToken is null)
return null;

var closeToken = EatToken(SyntaxKind.CloseParenthesis);
if (closeToken is null)
var body = ParseExpression();
if (body is null)
return null;

return new RepeatExpression(repeatToken, body, untilToken, openToken, condition, closeToken);
return new RepeatExpression(repeatToken, count, timesToken, body);
}

private ExpressionBase? ParseWhileExpression()
Expand Down
2 changes: 1 addition & 1 deletion LanguageParser/Visitors/ExpressionWalker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ public override void VisitParenthesized(ParenthesizedExpression expression)

public override void VisitRepeat(RepeatExpression expression)
{
Visit(expression.CountExpression);
Visit(expression.Body);
Visit(expression.Condition);
}

public override void VisitScope(ScopeExpression expression)
Expand Down
8 changes: 4 additions & 4 deletions SimpleExecutor/Models/ExpressionsColorizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ public override void VisitRepeat(RepeatExpression expression)
{
SetForeground(expression.RepeatToken, KeywordBrush);

Visit(expression.Body);

SetForeground(expression.UntilToken, KeywordBrush);
Visit(expression.CountExpression);
SetForeground(expression.TimesToken, KeywordBrush);

Visit(expression.Condition);
Visit(expression.Body);
}

public override void VisitScope(ScopeExpression expression)
Expand Down
38 changes: 35 additions & 3 deletions SimpleExecutor/ViewModels/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,22 @@ public MainViewModel()
Task.Delay((int)time).Wait();
});

var setStepDurationFunction = new Function("setStepDuration",
var setStepFunction = new Function("setStep",
new[] { new Variable("milliseconds", typeof(double)) },
args => { StepDuration = (int)(double)args[0]; });

var setColorFunction = new Function("setColor", new[] { new Variable("color", typeof(string)) }, args =>
{
var brush = (ISolidColorBrush)Brush.Parse((string)args[0]);

Executor.TraceColor = (IImmutableSolidColorBrush)brush.ToImmutable();
Dispatcher.UIThread.Invoke(() => Executor.TraceColor = (IImmutableSolidColorBrush) brush.ToImmutable());
});

var setBackgroundFunction = new Function("setBackground", new[] {new Variable("color", typeof(string))}, args =>
{
var brush = (ISolidColorBrush)Brush.Parse((string)args[0]);

Dispatcher.UIThread.Invoke(() => Executor.Background = (IImmutableSolidColorBrush) brush.ToImmutable());
});

TokensSyntaxColorizer = new TokensSyntaxColorizer(this);
Expand All @@ -99,8 +106,9 @@ public MainViewModel()
.WithPredefinedFunction(resetFunction)
.WithPredefinedFunction(jumpFunction)
.WithPredefinedFunction(delayFunction)
.WithPredefinedFunction(setStepDurationFunction)
.WithPredefinedFunction(setStepFunction)
.WithPredefinedFunction(setColorFunction)
.WithPredefinedFunction(setBackgroundFunction)
.WithPredefinedFunction(widthFunction)
.WithPredefinedFunction(heightFunction)
.WithPredefinedFunction(timeFunction)
Expand Down Expand Up @@ -261,4 +269,28 @@ public string Output
// y = y + velocityY * deltaTime;
//
// jump(x, y);
// }

// reset()
// setBackground('black')
// setStep(10)
// setColor('transparent')
// jump(getWidth() * 0.5, getHeight() * 0.5)
//
// for (number i = 0; i <= 500; i = i + 1)
// {
// if (i % 6 == 0)
// setColor('yellow')
// else if (i % 5 == 0)
// setColor('orange')
// else if (i % 4 == 0)
// setColor('green')
// else if (i % 3 == 0)
// setColor('blue')
// else if (i % 2 == 0)
// setColor('purple')
// else setColor('red')
//
// move(i)
// rotate(59)
// }
5 changes: 5 additions & 0 deletions SimpleExecutor/Views/ExecutorView.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ private void OnRender(SKCanvas canvas, SKSurface surface)
return;

using var paint = new SKPaint();

paint.Color = _executor.Background.Color.ToSKColor();

canvas.DrawRect(Bounds.ToSKRect(), paint);

paint.IsAntialias = true;

paint.StrokeWidth = 2;
Expand Down

0 comments on commit e734cd6

Please sign in to comment.