Skip to content

Commit 3e0aec7

Browse files
authored
optimization simplifying refactoring: (#210)
- func decl process - return analysis
1 parent 4c73729 commit 3e0aec7

File tree

17 files changed

+86
-92
lines changed

17 files changed

+86
-92
lines changed

src/Application/HydraScript.Application.CodeGeneration/Visitors/InstructionProvider.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,7 @@ public AddressedInstructions Visit(FunctionDeclaration visitable)
132132
for (var i = 0; i < visitable.Arguments.Count; i++)
133133
{
134134
var arg = visitable.Arguments[i];
135-
if (arg is DefaultValueArgument @default)
136-
result.Add(new PopParameter(arg.Name, @default.Info.Value));
137-
else
138-
result.Add(new PopParameter(arg.Name));
135+
result.Add(new PopParameter(arg.Name, arg.Info.Value));
139136
}
140137

141138
result.AddRange(visitable.Statements.Accept(This));

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

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using HydraScript.Domain.IR.Impl.Symbols;
88
using HydraScript.Domain.IR.Impl.Symbols.Ids;
99
using HydraScript.Domain.IR.Types;
10-
using ZLinq;
1110

1211
namespace HydraScript.Application.StaticAnalysis.Visitors;
1312

@@ -79,16 +78,16 @@ public VisitUnit Visit(FunctionDeclaration visitable)
7978
visitable.AllCodePathsEndedWithReturn = returnAnalyzerResult.CodePathEndedWithReturn;
8079

8180
var parentTable = _symbolTables[visitable.Parent.Scope];
82-
var indexOfFirstDefaultArgument = visitable.Arguments.AsValueEnumerable()
83-
.Select((x, i) => new { Argument = x, Index = i })
84-
.FirstOrDefault(pair => pair.Argument is DefaultValueArgument)?.Index ?? -1;
8581

86-
var parameters = visitable.Arguments.AsValueEnumerable()
87-
.Select(x =>
88-
new VariableSymbol(
89-
x.Name,
90-
x.TypeValue.Accept(_typeBuilder))).ToList();
91-
var functionSymbolId = new FunctionSymbolId(visitable.Name, parameters.Select(x => x.Type));
82+
var parameters = new List<Type>();
83+
for (var i = 0; i < visitable.Arguments.Count; i++)
84+
{
85+
parameters.Add(visitable.Arguments[i].TypeValue.Accept(_typeBuilder));
86+
var arg = new VariableSymbol(visitable.Arguments[i].Name, parameters[i]);
87+
arg.Initialize();
88+
_symbolTables[visitable.Scope].AddSymbol(arg);
89+
}
90+
var functionSymbolId = new FunctionSymbolId(visitable.Name, parameters);
9291
_ambiguousInvocations.Clear(functionSymbolId);
9392
visitable.ComputedFunctionAddress = functionSymbolId.ToString();
9493
var functionSymbol = new FunctionSymbol(
@@ -99,18 +98,8 @@ public VisitUnit Visit(FunctionDeclaration visitable)
9998
if (functionSymbolId.Equals(parentTable.FindSymbol(functionSymbolId)?.Id))
10099
throw new OverloadAlreadyExists(visitable.Name, functionSymbolId);
101100

102-
for (var i = 0; i < parameters.Count; i++)
103-
{
104-
var arg = parameters[i];
105-
arg.Initialize();
106-
_symbolTables[visitable.Scope].AddSymbol(arg);
107-
}
108-
109-
var isMethod =
110-
parameters is [{ Type: ObjectType }, ..] &&
111-
visitable.Arguments is [{ TypeValue: TypeIdentValue }, ..];
112-
if (isMethod)
113-
_methodStorage.BindMethod((parameters[0].Type as ObjectType)!, functionSymbol, functionSymbolId);
101+
if (parameters is [ObjectType methodOwner, ..] && visitable.Arguments is [{ TypeValue: TypeIdentValue }, ..])
102+
_methodStorage.BindMethod(methodOwner, functionSymbol, functionSymbolId);
114103

115104
Type undefined = "undefined";
116105
if (functionSymbol.Type.Equals(undefined))
@@ -122,23 +111,22 @@ public VisitUnit Visit(FunctionDeclaration visitable)
122111
}
123112

124113
parentTable.AddSymbol(functionSymbol);
125-
for (var i = indexOfFirstDefaultArgument; i < visitable.Arguments.Count; i++)
114+
for (var i = visitable.IndexOfFirstDefaultArgument; i < visitable.Arguments.Count; i++)
126115
{
127-
if (i is -1) break;
128-
if (visitable.Arguments[i] is not DefaultValueArgument)
116+
if (visitable.Arguments[i].Info.Type is ValueDtoType.Name)
129117
throw new NamedArgumentAfterDefaultValueArgument(
130118
visitable.Segment,
131119
function: visitable.Name,
132120
visitable.Arguments[i]);
133121

134-
var overload = new FunctionSymbolId(visitable.Name, parameters[..i].Select(x => x.Type));
122+
var overload = new FunctionSymbolId(visitable.Name, parameters[..i]);
135123
var existing = parentTable.FindSymbol(overload);
136124
var functionToAdd = existing is not null && existing < functionSymbol
137125
? existing
138126
: functionSymbol;
139127
parentTable.AddSymbol(functionToAdd, overload);
140-
if (isMethod)
141-
_methodStorage.BindMethod((parameters[0].Type as ObjectType)!, functionToAdd, overload);
128+
if (parameters is [ObjectType overloadOwner, ..] && visitable.Arguments is [{ TypeValue: TypeIdentValue }, ..])
129+
_methodStorage.BindMethod(overloadOwner, functionToAdd, overload);
142130

143131
if (existing is not null && !existing.Id.Equals(overload))
144132
{

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

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,42 +4,53 @@
44

55
namespace HydraScript.Application.StaticAnalysis.Visitors;
66

7-
internal class ReturnAnalyzer : VisitorBase<IAbstractSyntaxTreeNode, ReturnAnalyzerResult>,
7+
internal class ReturnAnalyzer : VisitorBase<IAbstractSyntaxTreeNode, bool>,
88
IVisitor<FunctionDeclaration, ReturnAnalyzerResult>,
9-
IVisitor<IfStatement, ReturnAnalyzerResult>,
10-
IVisitor<ReturnStatement, ReturnAnalyzerResult>
9+
IVisitor<IfStatement, bool>,
10+
IVisitor<ReturnStatement, bool>
1111
{
12+
private readonly List<ReturnStatement> _returnStatements = [];
13+
1214
public ReturnAnalyzerResult Visit(FunctionDeclaration visitable)
1315
{
1416
IAbstractSyntaxTreeNode astNode = visitable;
15-
return Visit(astNode);
17+
var codePathEndedWithReturn= Visit(astNode);
18+
var returnStatements = new List<ReturnStatement>(_returnStatements);
19+
ReturnAnalyzerResult result = new(codePathEndedWithReturn, returnStatements);
20+
_returnStatements.Clear();
21+
return result;
1622
}
1723

18-
public override ReturnAnalyzerResult Visit(IAbstractSyntaxTreeNode visitable)
24+
public override bool Visit(IAbstractSyntaxTreeNode visitable)
1925
{
20-
var result = ReturnAnalyzerResult.AdditiveIdentity;
2126
for (var i = 0; i < visitable.Count; i++)
2227
{
2328
var visitableResult = visitable[i].Accept(This);
24-
if (visitableResult.CodePathEndedWithReturn)
25-
return visitableResult * result;
26-
result += visitableResult;
29+
if (visitableResult)
30+
return true;
2731
}
2832

29-
return result;
33+
return false;
3034
}
3135

32-
public ReturnAnalyzerResult Visit(IfStatement visitable)
36+
public bool Visit(IfStatement visitable)
3337
{
3438
var thenReturns = visitable.Then.Accept(This);
3539

3640
if (visitable.Else is null)
37-
return thenReturns + ReturnAnalyzerResult.AdditiveIdentity;
41+
return false;
3842
var elseReturns = visitable.Else.Accept(This);
3943

40-
return thenReturns + elseReturns;
44+
return thenReturns && elseReturns;
45+
}
46+
47+
public bool Visit(ReturnStatement visitable)
48+
{
49+
_returnStatements.Add(visitable);
50+
return true;
4151
}
52+
}
4253

43-
public ReturnAnalyzerResult Visit(ReturnStatement visitable) =>
44-
new(CodePathEndedWithReturn: true, ReturnStatements: [visitable]);
45-
}
54+
public sealed record ReturnAnalyzerResult(
55+
bool CodePathEndedWithReturn,
56+
IReadOnlyList<ReturnStatement> ReturnStatements);

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

Lines changed: 0 additions & 22 deletions
This file was deleted.

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -466,9 +466,9 @@ public Type Visit(CallExpression visitable)
466466
.Zip(parameters).Zip(functionSymbol.Parameters.AsValueEnumerable().Skip(methodCall ? 1 : 0))
467467
.ToList().ForEach(pair =>
468468
{
469-
var ((expr, actualType), expected) = pair;
470-
if (!actualType.Equals(expected.Type))
471-
throw new WrongTypeOfArgument(expr.Segment, expected.Type, actualType);
469+
var ((expr, actualType), expectedType) = pair;
470+
if (!actualType.Equals(expectedType))
471+
throw new WrongTypeOfArgument(expr.Segment, expectedType, actualType);
472472
});
473473

474474
Type undefined = "undefined";
@@ -486,7 +486,7 @@ public Type Visit(CallExpression visitable)
486486

487487
public Type Visit(FunctionDeclaration visitable)
488488
{
489-
var parameters = visitable.Arguments.Select(x => x.TypeValue.Accept(_typeBuilder));
489+
var parameters = visitable.Arguments.Select(x => x.TypeValue.Accept(_typeBuilder)).ToList();
490490
var symbol = _symbolTables[visitable.Scope].FindSymbol(new FunctionSymbolId(visitable.Name, parameters))!;
491491
_functionStorage.RemoveIfPresent(symbol);
492492
visitable.Statements.Accept(This);

src/Domain/HydraScript.Domain.BackEnd/Impl/Instructions/PopParameter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
namespace HydraScript.Domain.BackEnd.Impl.Instructions;
22

3-
public class PopParameter(string parameter, object? defaultValue = null) : Instruction
3+
public class PopParameter(string parameter, object? defaultValue) : Instruction
44
{
55
public override IAddress? Execute(IExecuteParams executeParams)
66
{

src/Domain/HydraScript.Domain.FrontEnd/Parser/Impl/Ast/Nodes/Declarations/AfterTypesAreLoaded/FunctionDeclaration.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public partial class FunctionDeclaration : AfterTypesAreLoadedDeclaration
1414
public IdentifierReference Name { get; }
1515
public TypeValue ReturnTypeValue { get; }
1616
public IReadOnlyList<IFunctionArgument> Arguments => _arguments;
17+
public int IndexOfFirstDefaultArgument { get; }
1718

1819
public BlockStatement Statements { get; }
1920
public bool IsEmpty => Statements.Count == 0;
@@ -28,11 +29,13 @@ public FunctionDeclaration(
2829
IdentifierReference name,
2930
TypeValue returnTypeValue,
3031
List<IFunctionArgument> arguments,
31-
BlockStatement blockStatement)
32+
BlockStatement blockStatement,
33+
int indexOfFirstDefaultArgument)
3234
{
3335
Name = name;
3436
ReturnTypeValue = returnTypeValue;
3537
_arguments = arguments;
38+
IndexOfFirstDefaultArgument = indexOfFirstDefaultArgument;
3639

3740
Statements = blockStatement;
3841
Statements.Parent = this;

src/Domain/HydraScript.Domain.FrontEnd/Parser/Impl/Ast/Nodes/Declarations/AfterTypesAreLoaded/IFunctionArgument.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ public interface IFunctionArgument
77
public string Name { get; }
88

99
public TypeValue TypeValue { get; }
10+
11+
public ValueDto Info { get; }
1012
}
1113

1214
public record NamedArgument(
@@ -15,6 +17,8 @@ public record NamedArgument(
1517
{
1618
public override string ToString() =>
1719
$"{Name}: {TypeValue}";
20+
21+
public ValueDto Info { get; } = ValueDto.NameDto(Name);
1822
}
1923

2024
public record DefaultValueArgument : IFunctionArgument

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ private FunctionDeclaration FunctionDeclaration()
340340

341341
Expect("LeftParen");
342342
var args = new List<IFunctionArgument>();
343+
var indexOfFirstDefaultArgument = int.MaxValue;
343344
while (CurrentIs("Ident"))
344345
{
345346
var arg = Expect("Ident").Value;
@@ -353,6 +354,9 @@ private FunctionDeclaration FunctionDeclaration()
353354
{
354355
Expect("Assign");
355356
var value = Literal();
357+
indexOfFirstDefaultArgument = args.Count < indexOfFirstDefaultArgument
358+
? args.Count
359+
: indexOfFirstDefaultArgument;
356360
args.Add(new DefaultValueArgument(arg, value));
357361
}
358362

@@ -373,7 +377,7 @@ private FunctionDeclaration FunctionDeclaration()
373377
}
374378

375379
var name = new IdentifierReference(ident.Value) { Segment = ident.Segment };
376-
return new FunctionDeclaration(name, returnType, args, BlockStatement())
380+
return new FunctionDeclaration(name, returnType, args, BlockStatement(), indexOfFirstDefaultArgument)
377381
{ Segment = ident.Segment };
378382
}
379383

src/Domain/HydraScript.Domain.IR/Impl/Symbols/FunctionSymbol.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace HydraScript.Domain.IR.Impl.Symbols;
66

77
public class FunctionSymbol(
88
string name,
9-
IReadOnlyList<ISymbol> parameters,
9+
IReadOnlyList<Type> parameters,
1010
Type type,
1111
bool isEmpty) : Symbol(name, type)
1212
{
@@ -17,9 +17,9 @@ public class FunctionSymbol(
1717
/// <summary>
1818
/// Перегрузка функции
1919
/// </summary>
20-
public override FunctionSymbolId Id { get; } = new(name, parameters.Select(x => x.Type));
20+
public override FunctionSymbolId Id { get; } = new(name, parameters);
2121

22-
public IReadOnlyList<ISymbol> Parameters { get; } = parameters;
22+
public IReadOnlyList<Type> Parameters { get; } = parameters;
2323
public bool IsEmpty { get; } = isEmpty;
2424

2525
public void DefineReturnType(Type returnType) =>

0 commit comments

Comments
 (0)