Skip to content

Commit 12c583f

Browse files
authored
Перегрузка функций +semver:feature (#151)
* #61 - черновик иерархии ключей символов * #61 - использование ключа символа в домене * Revert "#61 - использование ключа символа в домене" This reverts commit fff91c7. * #61 - Symbol ctor param id -> name * #61 - новая иерархия ключей символов * #61 - use SymbolId in ISymbol * #61 - use symbolId in symbolTable * #61 - symbolId static analysis refactoring * fix AsString - add int support * #61 - added xxx test * #61 - codegen fix * #61 - overload tests
1 parent 7384664 commit 12c583f

File tree

34 files changed

+202
-98
lines changed

34 files changed

+202
-98
lines changed

ExtendedJavaScriptSubset.sln

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{04AB
6666
samples\vec2d.js = samples\vec2d.js
6767
samples\cycled.js = samples\cycled.js
6868
samples\scope.js = samples\scope.js
69+
samples\xxx.js = samples\xxx.js
70+
samples\overload_object.js = samples\overload_object.js
71+
samples\overload.js = samples\overload.js
6972
EndProjectSection
7073
EndProject
7174
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Src", "Src", "{FB8F6EE1-1942-46D6-954E-9A1647BBDF10}"

samples/overload.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function func(x:number){
2+
>>>x
3+
}
4+
5+
function func(x:number, y:number){
6+
return x + y
7+
}
8+
9+
func(123)
10+
11+
>>> func(-1,5)

samples/overload_object.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
function func(obj:TestObj, x:number){
2+
>>>x
3+
}
4+
5+
function func(obj:TestObj, x:number, y:number){
6+
return x + y
7+
}
8+
9+
type TestObj = {}
10+
11+
let tObj:TestObj = {}
12+
13+
tObj.func(123)
14+
15+
>>> tObj.func(-1,5)

samples/xxx.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
type x = number
2+
let x:x
3+
function x(x:x) {
4+
>>>x
5+
}
6+
7+
x(x)

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

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,6 @@ public AddressedInstructions Visit(CallExpression visitable)
262262
return [];
263263

264264
var methodCall = !visitable.Empty();
265-
string functionId;
266265
AddressedInstructions result = [];
267266

268267
if (methodCall)
@@ -271,12 +270,6 @@ public AddressedInstructions Visit(CallExpression visitable)
271270
var lastMemberInstruction = (DotRead)memberInstructions[memberInstructions.End];
272271
memberInstructions.Remove(lastMemberInstruction);
273272
result.AddRange(memberInstructions);
274-
275-
functionId = lastMemberInstruction.Property;
276-
}
277-
else
278-
{
279-
functionId = visitable.Id;
280273
}
281274

282275
if (methodCall)
@@ -298,7 +291,7 @@ public AddressedInstructions Visit(CallExpression visitable)
298291
}
299292

300293
result.Add(new CallFunction(
301-
new FunctionInfo(functionId),
294+
new FunctionInfo(visitable.ComputedFunctionAddress),
302295
visitable.HasReturnValue));
303296

304297
return result;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ public AddressedInstructions Visit(FunctionDeclaration visitable)
118118
if (!visitable.Statements.Any())
119119
return [];
120120

121-
var functionInfo = new FunctionInfo(visitable.Name);
121+
var functionInfo = new FunctionInfo(visitable.ComputedFunctionAddress);
122122

123123
var result = new AddressedInstructions
124124
{

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: 12 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,21 @@ 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+
var functionSymbolId = new FunctionSymbolId(visitable.Name, parameters.Select(x => x.Type));
75+
visitable.ComputedFunctionAddress = functionSymbolId.ToString();
76+
if (_symbolTables[visitable.Parent.Scope].ContainsSymbol(functionSymbolId))
7077
throw new DeclarationAlreadyExists(visitable.Name);
7178

72-
var parameters = visitable.Arguments.Select(x =>
79+
for (var i = 0; i < parameters.Count; i++)
7380
{
74-
var arg = new VariableSymbol(
75-
id: x.Key,
76-
x.TypeValue.Accept(_typeBuilder));
81+
var arg = parameters[i];
7782
arg.Initialize();
7883
_symbolTables[visitable.Scope].AddSymbol(arg);
79-
return arg;
80-
}).ToList();
84+
}
8185

8286
var functionSymbol = new FunctionSymbol(
8387
visitable.Name,

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

Lines changed: 15 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,25 +403,24 @@ 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

423+
visitable.ComputedFunctionAddress = functionSymbol.Id.ToString();
425424
visitable.IsEmptyCall = functionSymbol.IsEmpty;
426425
var functionReturnType = functionSymbol.Type;
427426

@@ -431,11 +430,10 @@ symbol as FunctionSymbol
431430
expected: functionSymbol.Parameters.Count,
432431
actual: visitable.Parameters.Count);
433432

434-
visitable.Parameters.Zip(functionSymbol.Parameters.ToArray()[(methodCall ? 1 : 0)..])
433+
visitable.Parameters.Zip(parameters).Zip(functionSymbol.Parameters.ToArray()[(methodCall ? 1 : 0)..])
435434
.ToList().ForEach(pair =>
436435
{
437-
var (expr, expected) = pair;
438-
var actualType = expr.Accept(This);
436+
var ((expr, actualType), expected) = pair;
439437
if (!actualType.Equals(expected.Type))
440438
throw new WrongTypeOfArgument(expr.Segment, expected.Type, actualType);
441439
});
@@ -455,7 +453,8 @@ symbol as FunctionSymbol
455453

456454
public Type Visit(FunctionDeclaration visitable)
457455
{
458-
var symbol = _symbolTables[visitable.Scope].FindSymbol<FunctionSymbol>(visitable.Name)!;
456+
var parameters = visitable.Arguments.Select(x => x.TypeValue.Accept(_typeBuilder)).ToList();
457+
var symbol = _symbolTables[visitable.Scope].FindSymbol<FunctionSymbol>(new FunctionSymbolId(visitable.Name, parameters))!;
459458
_functionStorage.RemoveIfPresent(symbol);
460459
visitable.Statements.Accept(This);
461460

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)

0 commit comments

Comments
 (0)