Skip to content

Commit b75d596

Browse files
committed
#55 - запрет на присваивание void (#120)
* #55 - test * #55 - исправление бага * #55 - доработка вычисления отрезка для выражения вызова * #55 - доработка теста
1 parent c070ce8 commit b75d596

File tree

8 files changed

+57
-10
lines changed

8 files changed

+57
-10
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
using System.Diagnostics.CodeAnalysis;
2+
3+
namespace HydraScript.Application.StaticAnalysis.Exceptions;
4+
5+
[ExcludeFromCodeCoverage]
6+
public class CannotAssignVoid(string segment) : SemanticException(segment, "Cannot assign void");

src/Application/HydraScript.Application.StaticAnalysis/Visitors/SemanticChecker.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ public Type Visit(UnaryExpression visitable)
262262

263263
public Type Visit(LexicalDeclaration visitable)
264264
{
265-
Type undefined = "undefined";
265+
Type undefined = "undefined", @void = "void";
266266

267267
for (var i = 0; i < visitable.Assignments.Count; i++)
268268
{
@@ -272,6 +272,8 @@ public Type Visit(LexicalDeclaration visitable)
272272
var sourceType = assignment.Source.Accept(This);
273273
if (sourceType.Equals(undefined))
274274
throw new CannotDefineType(assignment.Source.Segment);
275+
if (sourceType.Equals(@void))
276+
throw new CannotAssignVoid(assignment.Source.Segment);
275277
if (!registeredSymbol.Type.Equals(undefined) && !registeredSymbol.Type.Equals(sourceType))
276278
throw new IncompatibleTypesOfOperands(
277279
assignment.Segment,

src/Domain/HydraScript.Domain.FrontEnd/Lexer/Token.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,17 @@ public record Segment(Coordinates Start, Coordinates End)
3434

3535
public static implicit operator string(Segment segment) =>
3636
segment.ToString();
37+
38+
public static implicit operator Segment(string segment)
39+
{
40+
var coords = segment.Split("-")
41+
.Select(x => x[1..^1].Replace(" ", string.Empty))
42+
.Select(x => x.Split(',').Select(int.Parse).ToArray())
43+
.ToArray();
44+
return new Segment(
45+
new Coordinates(coords[0][0], coords[0][1]),
46+
new Coordinates(coords[1][0], coords[1][1]));
47+
}
3748
}
3849

3950
[ExcludeFromCodeCoverage]

src/Domain/HydraScript.Domain.FrontEnd/Parser/Impl/TopDownParser.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ private Expression CallExpression()
404404
var member = MemberExpression();
405405
if (CurrentIs("LeftParen"))
406406
{
407-
var lp = Expect("LeftParen");
407+
Expect("LeftParen");
408408
var expressions = new List<Expression>();
409409
if (CurrentIs("Ident") || CurrentIsLiteral() ||
410410
CurrentIs("LeftParen") || CurrentIsOperator("-") ||
@@ -420,9 +420,9 @@ private Expression CallExpression()
420420
expressions.Add(Expression());
421421
}
422422

423-
Expect("RightParen");
423+
var rp = Expect("RightParen");
424424
return new CallExpression((member as MemberExpression)!, expressions)
425-
{ Segment = lp.Segment };
425+
{ Segment = member.Segment + rp.Segment };
426426
}
427427

428428
return member;
@@ -436,7 +436,7 @@ private Expression MemberExpression()
436436
!CurrentIs("Assign") && !CurrentIs("LeftParen"))
437437
return primary;
438438

439-
var identRef = primary as IdentifierReference;
439+
var identRef = (primary as IdentifierReference)!;
440440
var accessChain = new List<AccessExpression>();
441441
while (CurrentIs("LeftBracket") || CurrentIs("Dot"))
442442
{
@@ -464,9 +464,12 @@ private Expression MemberExpression()
464464
}
465465

466466
return new MemberExpression(
467-
identRef!,
467+
identRef,
468468
accessChain.FirstOrDefault(),
469-
tail: accessChain.LastOrDefault());
469+
tail: accessChain.LastOrDefault())
470+
{
471+
Segment = identRef.Segment
472+
};
470473
}
471474

472475
private Expression CastExpression()

tests/HydraScript.IntegrationTests/ErrorPrograms/VariableInitializationTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.CommandLine.Parsing;
2-
using FluentAssertions;
32

43
namespace HydraScript.IntegrationTests.ErrorPrograms;
54

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System.CommandLine.Parsing;
2+
3+
namespace HydraScript.IntegrationTests.ErrorPrograms;
4+
5+
public class VoidAssignmentTests(TestHostFixture fixture) : IClassFixture<TestHostFixture>
6+
{
7+
[Fact]
8+
public void FunctionDeclared_VoidReturnAssigned_ExitCodeHydraScriptError()
9+
{
10+
const string script =
11+
"""
12+
function func(b: boolean) {
13+
if (b)
14+
return
15+
return
16+
}
17+
let x = func(true)
18+
""";
19+
var runner = fixture.GetRunner(configureTestServices:
20+
services => services.SetupInMemoryScript(script));
21+
var code = runner.Invoke(fixture.InMemoryScript);
22+
code.Should().Be(ExitCodes.HydraScriptError);
23+
fixture.LogMessages.Should()
24+
.Contain(x => x.Contains("Cannot assign void"));
25+
}
26+
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
// Global using directives
22

3-
global using Xunit;
3+
global using Xunit;
4+
global using FluentAssertions;

tests/HydraScript.IntegrationTests/SuccessfulProgramsTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.CommandLine.Parsing;
2-
using FluentAssertions;
32

43
namespace HydraScript.IntegrationTests;
54

0 commit comments

Comments
 (0)