Skip to content
This repository was archived by the owner on Nov 18, 2020. It is now read-only.

Commit 400b508

Browse files
add reachability annotations to method symbols
1 parent bd4cf42 commit 400b508

17 files changed

+277
-16
lines changed

Framework/EnumerableExtensions.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,18 @@ public static bool AnyTrue(this IEnumerable<bool> values)
125125

126126
[DebuggerStepThrough]
127127
[MethodImpl(MethodImplOptions.AggressiveInlining)]
128-
public static IEnumerable<T> NotNull<T>(this IEnumerable<T?> values)
128+
public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> values)
129129
where T : class
130130
{
131-
return values.Where(v => !(v is null)).Select(v => v!);
131+
return values.Where(v => !(v is null))!;
132+
}
133+
134+
[DebuggerStepThrough]
135+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
136+
public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> values)
137+
where T : struct
138+
{
139+
return values.Where(v => !(v is null)).Select(v => v!.Value);
132140
}
133141
}
134142
}

Parsing/Tree/NameExpressionSyntax.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public IEnumerable<IPromise<NamedBindingSymbol>> LookupInContainingScope()
5151
// If name is unknown, no symbols
5252
if (Name is null) return Enumerable.Empty<IPromise<NamedBindingSymbol>>();
5353

54-
return containingLexicalScope.Lookup(Name).Select(p => p.As<NamedBindingSymbol>()).NotNull();
54+
return containingLexicalScope.Lookup(Name).Select(p => p.As<NamedBindingSymbol>()).WhereNotNull();
5555
}
5656

5757
protected override OperatorPrecedence ExpressionPrecedence => OperatorPrecedence.Primary;

Parsing/Tree/TypeNameSyntax.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public TypeNameSyntax(TextSpan span, TypeName name)
4343
public IEnumerable<IPromise<TypeSymbol>> LookupInContainingScope()
4444
{
4545
if (containingLexicalScope != null)
46-
return containingLexicalScope.Lookup(Name).Select(p => p.As<TypeSymbol>()).NotNull();
46+
return containingLexicalScope.Lookup(Name).Select(p => p.As<TypeSymbol>()).WhereNotNull();
4747

4848
throw new InvalidOperationException($"Can't lookup type name without {nameof(ContainingLexicalScope)}");
4949
}

Parsing/Tree/UnqualifiedInvocationExpressionSyntax.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public IEnumerable<IPromise<FunctionSymbol>> LookupInContainingScope()
5353
// If name is unknown, no symbols
5454
if (InvokedName is null) return Enumerable.Empty<IPromise<FunctionSymbol>>();
5555

56-
return containingLexicalScope.Lookup(InvokedName).Select(p => p.As<FunctionSymbol>()).NotNull();
56+
return containingLexicalScope.Lookup(InvokedName).Select(p => p.As<FunctionSymbol>()).WhereNotNull();
5757
}
5858

5959
protected override OperatorPrecedence ExpressionPrecedence => OperatorPrecedence.Primary;

Semantics/Symbols/Entities/EntitySymbolBuilder.cs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
using Adamant.Tools.Compiler.Bootstrap.Core;
55
using Adamant.Tools.Compiler.Bootstrap.CST;
66
using Adamant.Tools.Compiler.Bootstrap.Framework;
7+
using Adamant.Tools.Compiler.Bootstrap.Names;
78
using Adamant.Tools.Compiler.Bootstrap.Semantics.Errors;
89
using Adamant.Tools.Compiler.Bootstrap.Semantics.Types;
910
using Adamant.Tools.Compiler.Bootstrap.Symbols;
11+
using Adamant.Tools.Compiler.Bootstrap.Symbols.Reachability;
1012
using Adamant.Tools.Compiler.Bootstrap.Symbols.Trees;
1113
using Adamant.Tools.Compiler.Bootstrap.Types;
1214
using ExhaustiveMatching;
@@ -80,7 +82,8 @@ private void BuildMethodSymbol(IMethodDeclarationSyntax method)
8082
var selfParameterType = ResolveSelfParameterType(method.SelfParameter, method.DeclaringClass);
8183
var parameterTypes = ResolveParameterTypes(resolver, method.Parameters, method.DeclaringClass);
8284
var returnType = ResolveReturnType(method.ReturnType, resolver);
83-
var symbol = new MethodSymbol(declaringClassSymbol, method.Name, selfParameterType, parameterTypes, returnType);
85+
var reachabilityAnnotations = BuildReachabilityAnnotations(method);
86+
var symbol = new MethodSymbol(declaringClassSymbol, method.Name, selfParameterType, parameterTypes, returnType, reachabilityAnnotations);
8487
method.Symbol.Fulfill(symbol);
8588
symbolTree.Add(symbol);
8689
BuildSelParameterSymbol(symbol, method.SelfParameter, selfParameterType);
@@ -260,6 +263,62 @@ private static DataType ResolveReturnType(
260263
return returnType;
261264
}
262265

266+
private static FixedSet<ReachabilityAnnotation>? BuildReachabilityAnnotations(IInvocableDeclarationSyntax invocable)
267+
{
268+
var annotation = BuildReachabilityAnnotation(invocable);
269+
return annotation is null ? null : new FixedSet<ReachabilityAnnotation>(annotation.Yield());
270+
}
271+
272+
private static ReachabilityAnnotation? BuildReachabilityAnnotation(IInvocableDeclarationSyntax invocable)
273+
{
274+
var parameters = invocable.Parameters.Select((p, i) => new { Param = p, Index = i })
275+
.Where(x => x.Param is INamedParameterSyntax)
276+
.ToDictionary(x => ((INamedParameterSyntax)x.Param).Name, x => ParameterReference.Create(x.Index));
277+
278+
ReachabilityAnnotation? annotation = null;
279+
280+
var canReach = ToReferences(invocable.ReachabilityAnnotations.CanReachAnnotation, parameters);
281+
if (canReach.Count != 0)
282+
{
283+
var refs = new ReachableReferences(canReach);
284+
annotation = new ReachabilityAnnotation(ReturnReference.Instance, refs);
285+
}
286+
287+
var reachableFrom = ToReferences(invocable.ReachabilityAnnotations.ReachableFromAnnotation, parameters);
288+
if (reachableFrom.Count != 0)
289+
{
290+
var chain = (ReachabilityChain?)annotation ?? new ReachableReferences(ReturnReference.Instance);
291+
annotation = new ReachabilityAnnotation(reachableFrom, chain);
292+
}
293+
294+
return annotation;
295+
}
296+
297+
private static FixedSet<Reference> ToReferences(
298+
IReachabilityAnnotationSyntax? annotation,
299+
Dictionary<Name, ParameterReference> parameters)
300+
{
301+
return annotation?.Parameters.Select(p => ToSymbolReference(p, parameters))
302+
.WhereNotNull().ToFixedSet() ?? FixedSet<Reference>.Empty;
303+
}
304+
305+
private static Reference? ToSymbolReference(
306+
IParameterNameSyntax paramName,
307+
IReadOnlyDictionary<Name, ParameterReference> parameters)
308+
{
309+
switch (paramName)
310+
{
311+
default:
312+
throw ExhaustiveMatch.Failed(paramName);
313+
case INamedParameterNameSyntax syn:
314+
if (syn.Name != null && parameters.TryGetValue(syn.Name, out var reference))
315+
return reference;
316+
return null;
317+
case ISelfParameterNameSyntax _:
318+
return SelfParameterReference.Instance;
319+
}
320+
}
321+
263322
private void ResolveReachabilityAnnotations(IInvocableDeclarationSyntax invocable)
264323
{
265324
var canReach = invocable.ReachabilityAnnotations.CanReachAnnotation?.Parameters

Symbols/ConstructorSymbol.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Linq;
33
using Adamant.Tools.Compiler.Bootstrap.Framework;
44
using Adamant.Tools.Compiler.Bootstrap.Names;
5+
using Adamant.Tools.Compiler.Bootstrap.Symbols.Reachability;
56
using Adamant.Tools.Compiler.Bootstrap.Types;
67

78
namespace Adamant.Tools.Compiler.Bootstrap.Symbols
@@ -14,16 +15,19 @@ public sealed class ConstructorSymbol : InvocableSymbol
1415
public ConstructorSymbol(
1516
ObjectTypeSymbol containingSymbol,
1617
Name? name,
17-
FixedList<DataType> parameterDataTypes)
18-
: base(containingSymbol, name, parameterDataTypes, containingSymbol.DeclaresDataType.ToConstructorReturn())
18+
FixedList<DataType> parameterDataTypes,
19+
FixedSet<ReachabilityAnnotation>? reachabilityAnnotations = null)
20+
: base(containingSymbol, name, parameterDataTypes,
21+
containingSymbol.DeclaresDataType.ToConstructorReturn(),
22+
reachabilityAnnotations ?? FixedSet<ReachabilityAnnotation>.Empty)
1923
{
2024
ContainingSymbol = containingSymbol;
2125
ReturnDataType = containingSymbol.DeclaresDataType.ToConstructorReturn();
2226
}
2327

2428
public static ConstructorSymbol CreateDefault(ObjectTypeSymbol containingSymbol)
2529
{
26-
return new ConstructorSymbol(containingSymbol, null, FixedList<DataType>.Empty);
30+
return new ConstructorSymbol(containingSymbol, null, FixedList<DataType>.Empty, FixedSet<ReachabilityAnnotation>.Empty);
2731
}
2832

2933
public override bool Equals(Symbol? other)

Symbols/FunctionOrMethodSymbol.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Adamant.Tools.Compiler.Bootstrap.Framework;
22
using Adamant.Tools.Compiler.Bootstrap.Names;
3+
using Adamant.Tools.Compiler.Bootstrap.Symbols.Reachability;
34
using Adamant.Tools.Compiler.Bootstrap.Types;
45
using ExhaustiveMatching;
56

@@ -12,8 +13,13 @@ public abstract class FunctionOrMethodSymbol : InvocableSymbol
1213
{
1314
public new Name Name { get; }
1415

15-
protected FunctionOrMethodSymbol(Symbol containingSymbol, Name name, FixedList<DataType> parameterDataTypes, DataType returnDataType)
16-
: base(containingSymbol, name, parameterDataTypes, returnDataType)
16+
protected FunctionOrMethodSymbol(
17+
Symbol containingSymbol,
18+
Name name,
19+
FixedList<DataType> parameterDataTypes,
20+
DataType returnDataType,
21+
FixedSet<ReachabilityAnnotation> reachabilityAnnotations)
22+
: base(containingSymbol, name, parameterDataTypes, returnDataType, reachabilityAnnotations)
1723
{
1824
Name = name;
1925
}

Symbols/FunctionSymbol.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Linq;
33
using Adamant.Tools.Compiler.Bootstrap.Framework;
44
using Adamant.Tools.Compiler.Bootstrap.Names;
5+
using Adamant.Tools.Compiler.Bootstrap.Symbols.Reachability;
56
using Adamant.Tools.Compiler.Bootstrap.Types;
67

78
namespace Adamant.Tools.Compiler.Bootstrap.Symbols
@@ -17,12 +18,22 @@ public FunctionSymbol(
1718
Symbol containingSymbol,
1819
Name name,
1920
FixedList<DataType> parameterDataTypes,
20-
DataType? returnDataType = null)
21-
: base(containingSymbol, name, parameterDataTypes, returnDataType ?? DataType.Void)
21+
DataType returnDataType,
22+
FixedSet<ReachabilityAnnotation>? reachabilityAnnotations = null)
23+
: base(containingSymbol, name, parameterDataTypes, returnDataType, reachabilityAnnotations ?? FixedSet<ReachabilityAnnotation>.Empty)
2224
{
2325
Name = name;
2426
}
2527

28+
public FunctionSymbol(
29+
Symbol containingSymbol,
30+
Name name,
31+
FixedList<DataType> parameterDataTypes,
32+
FixedSet<ReachabilityAnnotation>? reachabilityAnnotations = null)
33+
: this(containingSymbol, name, parameterDataTypes, DataType.Void, reachabilityAnnotations ?? FixedSet<ReachabilityAnnotation>.Empty)
34+
{
35+
}
36+
2637
public override bool Equals(Symbol? other)
2738
{
2839
if (other is null) return false;

Symbols/InvocableSymbol.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Adamant.Tools.Compiler.Bootstrap.Framework;
22
using Adamant.Tools.Compiler.Bootstrap.Names;
3+
using Adamant.Tools.Compiler.Bootstrap.Symbols.Reachability;
34
using Adamant.Tools.Compiler.Bootstrap.Types;
45
using ExhaustiveMatching;
56

@@ -15,14 +16,21 @@ public abstract class InvocableSymbol : Symbol
1516
public FixedList<DataType> ParameterDataTypes { get; }
1617
public int Arity => ParameterDataTypes.Count;
1718
public DataType ReturnDataType { get; }
19+
public FixedSet<ReachabilityAnnotation> ReachabilityAnnotations { get; }
1820

19-
protected InvocableSymbol(Symbol containingSymbol, Name? name, FixedList<DataType> parameterDataTypes, DataType returnDataType)
21+
protected InvocableSymbol(
22+
Symbol containingSymbol,
23+
Name? name,
24+
FixedList<DataType> parameterDataTypes,
25+
DataType returnDataType,
26+
FixedSet<ReachabilityAnnotation> reachabilityAnnotations)
2027
: base(containingSymbol, name)
2128
{
2229
ContainingSymbol = containingSymbol;
2330
Name = name;
2431
ParameterDataTypes = parameterDataTypes;
2532
ReturnDataType = returnDataType;
33+
ReachabilityAnnotations = reachabilityAnnotations;
2634
}
2735
}
2836
}

Symbols/MethodSymbol.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Linq;
33
using Adamant.Tools.Compiler.Bootstrap.Framework;
44
using Adamant.Tools.Compiler.Bootstrap.Names;
5+
using Adamant.Tools.Compiler.Bootstrap.Symbols.Reachability;
56
using Adamant.Tools.Compiler.Bootstrap.Types;
67

78
namespace Adamant.Tools.Compiler.Bootstrap.Symbols
@@ -17,8 +18,9 @@ public MethodSymbol(
1718
Name name,
1819
DataType selfDataType,
1920
FixedList<DataType> parameterDataTypes,
20-
DataType returnDataType)
21-
: base(containingSymbol, name, parameterDataTypes, returnDataType)
21+
DataType returnDataType,
22+
FixedSet<ReachabilityAnnotation>? reachabilityAnnotations = null)
23+
: base(containingSymbol, name, parameterDataTypes, returnDataType, reachabilityAnnotations ?? FixedSet<ReachabilityAnnotation>.Empty)
2224
{
2325
ContainingSymbol = containingSymbol;
2426
Name = name;

0 commit comments

Comments
 (0)