Skip to content

Commit 9cc5601

Browse files
committed
#61 - symbolId static analysis refactoring
1 parent 8e5f941 commit 9cc5601

File tree

11 files changed

+60
-69
lines changed

11 files changed

+60
-69
lines changed

src/Application/HydraScript.Application.StaticAnalysis/Exceptions/SymbolIsNotCallable.cs

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

src/Application/HydraScript.Application.StaticAnalysis/IMethodStorage.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using HydraScript.Domain.IR.Impl.SymbolIds;
12
using HydraScript.Domain.IR.Impl.Symbols;
23
using HydraScript.Domain.IR.Types;
34

@@ -7,5 +8,5 @@ public interface IMethodStorage
78
{
89
public void BindMethod(ObjectType objectType, FunctionSymbol method);
910

10-
public IReadOnlyDictionary<string, FunctionSymbol> GetAvailableMethods(ObjectType objectType);
11+
public IReadOnlyDictionary<FunctionSymbolId, FunctionSymbol> GetAvailableMethods(ObjectType objectType);
1112
}

src/Application/HydraScript.Application.StaticAnalysis/Impl/FunctionWithUndefinedReturnStorage.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes.Declarations.AfterTypesAreLoaded;
2+
using HydraScript.Domain.IR.Impl.SymbolIds;
23
using HydraScript.Domain.IR.Impl.Symbols;
34

45
namespace HydraScript.Application.StaticAnalysis.Impl;
56

67
internal class FunctionWithUndefinedReturnStorage : IFunctionWithUndefinedReturnStorage
78
{
8-
private readonly OrderedDictionary<string, FunctionDeclaration> _declarations = [];
9+
private readonly OrderedDictionary<FunctionSymbolId, FunctionDeclaration> _declarations = [];
910

1011
public void Save(FunctionSymbol symbol, FunctionDeclaration declaration)
1112
{
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
1+
using HydraScript.Domain.IR.Impl.SymbolIds;
12
using HydraScript.Domain.IR.Impl.Symbols;
23
using HydraScript.Domain.IR.Types;
34

45
namespace HydraScript.Application.StaticAnalysis.Impl;
56

67
internal class MethodStorage : IMethodStorage
78
{
8-
private readonly Dictionary<ObjectType, Dictionary<string, FunctionSymbol>> _bindings = [];
9+
private readonly Dictionary<ObjectType, Dictionary<FunctionSymbolId, FunctionSymbol>> _bindings = [];
910

1011
public void BindMethod(ObjectType objectType, FunctionSymbol method)
1112
{
1213
objectType.AddMethod(method.Id);
1314
if (!_bindings.ContainsKey(objectType))
14-
_bindings[objectType] = new Dictionary<string, FunctionSymbol>();
15+
_bindings[objectType] = new Dictionary<FunctionSymbolId, FunctionSymbol>();
1516
_bindings[objectType][method.Id] = method;
1617
}
1718

18-
public IReadOnlyDictionary<string, FunctionSymbol> GetAvailableMethods(ObjectType objectType) =>
19-
_bindings.GetValueOrDefault(objectType, new Dictionary<string, FunctionSymbol>());
19+
public IReadOnlyDictionary<FunctionSymbolId, FunctionSymbol> GetAvailableMethods(ObjectType objectType) =>
20+
_bindings.GetValueOrDefault(objectType, new Dictionary<FunctionSymbolId, FunctionSymbol>());
2021
}

src/Application/HydraScript.Application.StaticAnalysis/Impl/TypeDeclarationsResolver.cs

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,41 @@
11
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes.Declarations;
2+
using HydraScript.Domain.IR.Impl.SymbolIds;
23
using HydraScript.Domain.IR.Impl.Symbols;
34

45
namespace HydraScript.Application.StaticAnalysis.Impl;
56

6-
internal class TypeDeclarationsResolver : ITypeDeclarationsResolver
7+
internal class TypeDeclarationsResolver(
8+
IJavaScriptTypesProvider provider,
9+
ISymbolTableStorage symbolTables,
10+
IVisitor<TypeValue, Type> typeBuilder) : ITypeDeclarationsResolver
711
{
812
private readonly Queue<TypeDeclaration> _declarationsToResolve = [];
913

10-
private readonly IJavaScriptTypesProvider _provider;
11-
private readonly ISymbolTableStorage _symbolTables;
12-
private readonly IVisitor<TypeValue, Type> _typeBuilder;
13-
14-
public TypeDeclarationsResolver(
15-
IJavaScriptTypesProvider provider,
16-
ISymbolTableStorage symbolTables,
17-
IVisitor<TypeValue, Type> typeBuilder)
18-
{
19-
_provider = provider;
20-
_symbolTables = symbolTables;
21-
_typeBuilder = typeBuilder;
22-
}
23-
2414
public void Store(TypeDeclaration declaration) =>
2515
_declarationsToResolve.Enqueue(declaration);
2616

2717
public void Resolve()
2818
{
29-
var defaults = _provider.GetDefaultTypes()
19+
var defaults = provider.GetDefaultTypes()
3020
.Select(x => new TypeSymbol(x))
3121
.ToList();
3222

3323
foreach (var declarationToResolve in _declarationsToResolve)
3424
{
35-
_symbolTables[declarationToResolve.Scope].AddSymbol(
25+
symbolTables[declarationToResolve.Scope].AddSymbol(
3626
new TypeSymbol(
37-
declarationToResolve.TypeValue.Accept(_typeBuilder),
27+
declarationToResolve.TypeValue.Accept(typeBuilder),
3828
declarationToResolve.TypeId));
3929
}
4030

4131
while (_declarationsToResolve.Count != 0)
4232
{
4333
var declarationToResolve = _declarationsToResolve.Dequeue();
4434

45-
var typeSymbol = _symbolTables[declarationToResolve.Scope]
46-
.FindSymbol<TypeSymbol>(declarationToResolve.TypeId)!;
35+
var typeSymbol = symbolTables[declarationToResolve.Scope]
36+
.FindSymbol<TypeSymbol>(new TypeSymbolId(declarationToResolve.TypeId))!;
4737

48-
var resolvingCandidates = _symbolTables[declarationToResolve.Scope]
38+
var resolvingCandidates = symbolTables[declarationToResolve.Scope]
4939
.GetAvailableSymbols()
5040
.OfType<TypeSymbol>()
5141
.Except(defaults);
@@ -54,7 +44,7 @@ public void Resolve()
5444
{
5545
typeSymbol.Type.ResolveReference(
5646
referenceSymbol.Type,
57-
referenceSymbol.Id);
47+
referenceSymbol.Name);
5848
}
5949
}
6050
}

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

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes.Declarations.AfterTypesAreLoaded;
55
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes.Expressions.ComplexLiterals;
66
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes.Expressions.PrimaryExpressions;
7+
using HydraScript.Domain.IR.Impl.SymbolIds;
78
using HydraScript.Domain.IR.Impl.Symbols;
89
using HydraScript.Domain.IR.Types;
910

@@ -43,7 +44,7 @@ public VisitUnit Visit(LexicalDeclaration visitable)
4344
for (var i = 0; i < visitable.Assignments.Count; i++)
4445
{
4546
var assignment = visitable.Assignments[i];
46-
if (_symbolTables[visitable.Scope].ContainsSymbol(assignment.Destination.Id))
47+
if (_symbolTables[visitable.Scope].ContainsSymbol(new VariableSymbolId(assignment.Destination.Id)))
4748
throw new DeclarationAlreadyExists(assignment.Destination.Id);
4849

4950
var destinationType = assignment.DestinationType?.Accept(
@@ -66,18 +67,20 @@ public VisitUnit Visit(LexicalDeclaration visitable)
6667

6768
public VisitUnit Visit(FunctionDeclaration visitable)
6869
{
69-
if (_symbolTables[visitable.Parent.Scope].ContainsSymbol(visitable.Name))
70+
var parameters = visitable.Arguments.Select(x =>
71+
new VariableSymbol(
72+
name: x.Key,
73+
x.TypeValue.Accept(_typeBuilder))).ToList();
74+
if (_symbolTables[visitable.Parent.Scope].ContainsSymbol(
75+
new FunctionSymbolId(visitable.Name, parameters.Select(x => x.Type))))
7076
throw new DeclarationAlreadyExists(visitable.Name);
7177

72-
var parameters = visitable.Arguments.Select(x =>
78+
for (var i = 0; i < parameters.Count; i++)
7379
{
74-
var arg = new VariableSymbol(
75-
name: x.Key,
76-
x.TypeValue.Accept(_typeBuilder));
80+
var arg = parameters[i];
7781
arg.Initialize();
7882
_symbolTables[visitable.Scope].AddSymbol(arg);
79-
return arg;
80-
}).ToList();
83+
}
8184

8285
var functionSymbol = new FunctionSymbol(
8386
visitable.Name,

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

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes.Expressions.ComplexLiterals;
1010
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes.Expressions.PrimaryExpressions;
1111
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes.Statements;
12-
using HydraScript.Domain.IR;
12+
using HydraScript.Domain.IR.Impl.SymbolIds;
1313
using HydraScript.Domain.IR.Impl.Symbols;
1414
using HydraScript.Domain.IR.Types;
1515

@@ -138,7 +138,7 @@ public Type Visit(ExpressionStatement visitable) =>
138138

139139
public Type Visit(IdentifierReference visitable)
140140
{
141-
var symbol = _symbolTables[visitable.Scope].FindSymbol<VariableSymbol>(visitable.Name);
141+
var symbol = _symbolTables[visitable.Scope].FindSymbol<VariableSymbol>(new VariableSymbolId(visitable.Name));
142142
if (symbol is { Initialized: false })
143143
throw new AccessBeforeInitialization(visitable);
144144
return symbol?.Type ?? throw new UnknownIdentifierReference(visitable);
@@ -278,7 +278,7 @@ public Type Visit(LexicalDeclaration visitable)
278278
{
279279
var assignment = visitable.Assignments[i];
280280
var registeredSymbol = _symbolTables[visitable.Scope].FindSymbol<VariableSymbol>(
281-
assignment.Destination.Id)!;
281+
new VariableSymbolId(assignment.Destination.Id))!;
282282
var sourceType = assignment.Source.Accept(This);
283283
if (sourceType.Equals(undefined))
284284
throw new CannotDefineType(assignment.Source.Segment);
@@ -297,8 +297,8 @@ public Type Visit(LexicalDeclaration visitable)
297297
: registeredSymbol.Type;
298298
var actualSymbol = actualType switch
299299
{
300-
ObjectType objectType => new ObjectSymbol(registeredSymbol.Id, objectType, visitable.ReadOnly),
301-
_ => new VariableSymbol(registeredSymbol.Id, actualType, visitable.ReadOnly)
300+
ObjectType objectType => new ObjectSymbol(registeredSymbol.Name, objectType, visitable.ReadOnly),
301+
_ => new VariableSymbol(registeredSymbol.Name, actualType, visitable.ReadOnly)
302302
};
303303
actualSymbol.Initialize();
304304
_symbolTables[visitable.Scope].AddSymbol(actualSymbol);
@@ -326,7 +326,7 @@ public Type Visit(AssignmentExpression visitable)
326326

327327
var symbol =
328328
_symbolTables[visitable.Scope].FindSymbol<VariableSymbol>(
329-
visitable.Destination.Id) ??
329+
new VariableSymbolId(visitable.Destination.Id)) ??
330330
throw new UnknownIdentifierReference(visitable.Destination.Id);
331331

332332
if (symbol.ReadOnly)
@@ -403,23 +403,21 @@ public Type Visit(CastAsExpression visitable)
403403

404404
public Type Visit(CallExpression visitable)
405405
{
406+
var parameters = visitable.Parameters.Select(expr => expr.Accept(This)).ToList();
406407
FunctionSymbol functionSymbol;
407408
var methodCall = !visitable.Member.Empty();
408409

409410
if (methodCall)
410411
{
411412
var objectType = (ObjectType)visitable.Member.Accept(This);
412413
var availableMethods = _methodStorage.GetAvailableMethods(objectType);
413-
functionSymbol = availableMethods[objectType.LastAccessedMethod];
414+
functionSymbol = availableMethods[new FunctionSymbolId(objectType.LastAccessedMethodName, [objectType, ..parameters])];
414415
}
415416
else
416417
{
417-
var symbol =
418-
_symbolTables[visitable.Scope].FindSymbol<ISymbol>(visitable.Id)
419-
?? throw new UnknownIdentifierReference(visitable.Id);
420418
functionSymbol =
421-
symbol as FunctionSymbol
422-
?? throw new SymbolIsNotCallable(symbol.Id, visitable.Id.Segment);
419+
_symbolTables[visitable.Scope].FindSymbol<FunctionSymbol>(new FunctionSymbolId(visitable.Id, parameters))
420+
?? throw new UnknownIdentifierReference(visitable.Id);
423421
}
424422

425423
visitable.IsEmptyCall = functionSymbol.IsEmpty;
@@ -431,11 +429,10 @@ symbol as FunctionSymbol
431429
expected: functionSymbol.Parameters.Count,
432430
actual: visitable.Parameters.Count);
433431

434-
visitable.Parameters.Zip(functionSymbol.Parameters.ToArray()[(methodCall ? 1 : 0)..])
432+
visitable.Parameters.Zip(parameters).Zip(functionSymbol.Parameters.ToArray()[(methodCall ? 1 : 0)..])
435433
.ToList().ForEach(pair =>
436434
{
437-
var (expr, expected) = pair;
438-
var actualType = expr.Accept(This);
435+
var ((expr, actualType), expected) = pair;
439436
if (!actualType.Equals(expected.Type))
440437
throw new WrongTypeOfArgument(expr.Segment, expected.Type, actualType);
441438
});
@@ -455,7 +452,8 @@ symbol as FunctionSymbol
455452

456453
public Type Visit(FunctionDeclaration visitable)
457454
{
458-
var symbol = _symbolTables[visitable.Scope].FindSymbol<FunctionSymbol>(visitable.Name)!;
455+
var parameters = visitable.Arguments.Select(x => x.TypeValue.Accept(_typeBuilder)).ToList();
456+
var symbol = _symbolTables[visitable.Scope].FindSymbol<FunctionSymbol>(new FunctionSymbolId(visitable.Name, parameters))!;
459457
_functionStorage.RemoveIfPresent(symbol);
460458
visitable.Statements.Accept(This);
461459

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using HydraScript.Application.StaticAnalysis.Exceptions;
22
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes.Declarations;
3+
using HydraScript.Domain.IR.Impl.SymbolIds;
34
using HydraScript.Domain.IR.Impl.Symbols;
45
using HydraScript.Domain.IR.Types;
56

@@ -17,7 +18,7 @@ public TypeBuilder(ISymbolTableStorage symbolTables) =>
1718
_symbolTables = symbolTables;
1819

1920
public Type Visit(TypeIdentValue visitable) =>
20-
_symbolTables[visitable.Scope].FindSymbol<TypeSymbol>(visitable.TypeId)?.Type ??
21+
_symbolTables[visitable.Scope].FindSymbol<TypeSymbol>(new TypeSymbolId(visitable.TypeId))?.Type ??
2122
throw new UnknownIdentifierReference(visitable.TypeId);
2223

2324
public ArrayType Visit(ArrayTypeValue visitable)

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using HydraScript.Domain.FrontEnd.Parser;
33
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes;
44
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes.Declarations;
5+
using HydraScript.Domain.IR.Impl.SymbolIds;
56
using HydraScript.Domain.IR.Impl.Symbols;
67

78
namespace HydraScript.Application.StaticAnalysis.Visitors;
@@ -43,7 +44,7 @@ public override VisitUnit Visit(IAbstractSyntaxTreeNode visitable)
4344
public VisitUnit Visit(TypeDeclaration visitable)
4445
{
4546
var symbolTable = _symbolTables[visitable.Scope];
46-
if (symbolTable.ContainsSymbol(visitable.TypeId) ||
47+
if (symbolTable.ContainsSymbol(new TypeSymbolId(visitable.TypeId)) ||
4748
_provider.Contains(visitable.TypeId.Name))
4849
throw new DeclarationAlreadyExists(visitable.TypeId);
4950

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
namespace HydraScript.Domain.IR.Impl.SymbolIds;
22

33
public class FunctionSymbolId(
4-
string id,
4+
string name,
55
IEnumerable<Type> parameters) : SymbolId
66
{
77
protected override string Value { get; } =
8-
$"function {id}({string.Join(", ", parameters)})";
8+
$"function {name}({string.Join(", ", parameters)})";
9+
10+
public bool HasName(string askedName) => name == askedName;
911
}

0 commit comments

Comments
 (0)