Skip to content

Commit e3889a1

Browse files
committed
Basic constraints added back
1 parent 7a48da9 commit e3889a1

File tree

3 files changed

+73
-4
lines changed

3 files changed

+73
-4
lines changed

src/Draco.Compiler/Internal/Solver/ConstraintSolver.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public Argument Arg(SyntaxNode? syntax, BindingTask<BoundLvalue> lvalue, Diagnos
6868
/// <param name="diagnostics">The bag to report diagnostics to.</param>
6969
public void Solve(DiagnosticBag diagnostics)
7070
{
71-
while (this.ApplyRulesOnce()) { }
71+
while (this.ApplyRulesOnce(diagnostics)) { }
7272

7373
// Check for uninferred locals
7474
this.CheckForUninferredLocals(diagnostics);

src/Draco.Compiler/Internal/Solver/ConstraintSolver_Rules.cs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
using System;
2+
using Draco.Compiler.Internal.Diagnostics;
3+
using Draco.Compiler.Internal.Solver.Constraints;
4+
using Draco.Compiler.Internal.Symbols;
25

36
namespace Draco.Compiler.Internal.Solver;
47

@@ -8,9 +11,39 @@ internal sealed partial class ConstraintSolver
811
/// Tries to apply a rule to the current set of constraints.
912
/// This is a fixpoint iteration method. Once it returns false, no more rules can be applied.
1013
/// </summary>
14+
/// <param name="diagnostics">The diagnostics to report to.</param>
1115
/// <returns>True, if a change was made, false otherwise.</returns>
12-
private bool ApplyRulesOnce()
16+
private bool ApplyRulesOnce(DiagnosticBag diagnostics)
1317
{
18+
// Trivial same-type constraint, unify all
19+
if (this.constraintStore.TryRemove<Same>(out var same))
20+
{
21+
for (var i = 1; i < same.Types.Length; ++i)
22+
{
23+
if (Unify(same.Types[0], same.Types[i])) continue;
24+
// Type-mismatch
25+
same.ReportDiagnostic(diagnostics, builder => builder
26+
.WithFormatArgs(same.Types[0].Substitution, same.Types[i].Substitution));
27+
break;
28+
}
29+
return true;
30+
}
31+
32+
// Assignable can be resolved directly, if both types are ground-types
33+
if (this.constraintStore.TryRemove<Assignable>(out var assignable, assignable => assignable.TargetType.IsGroundType
34+
&& assignable.AssignedType.IsGroundType))
35+
{
36+
var targetType = assignable.TargetType;
37+
var assignedType = assignable.AssignedType;
38+
if (!SymbolEqualityComparer.Default.IsBaseOf(targetType, assignedType))
39+
{
40+
// Error
41+
assignable.ReportDiagnostic(diagnostics, diag => diag
42+
.WithFormatArgs(targetType, assignedType));
43+
}
44+
return true;
45+
}
46+
1447
return false;
1548
}
1649

src/Draco.Compiler/Internal/Solver/ConstraintStore.cs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Diagnostics.CodeAnalysis;
34
using System.Linq;
5+
using Draco.Compiler.Internal.Solver.Constraints;
46

57
namespace Draco.Compiler.Internal.Solver;
68

@@ -14,13 +16,13 @@ internal sealed class ConstraintStore
1416
/// </summary>
1517
public int Count => this.constraints.Values.Sum(list => list.Count);
1618

17-
private readonly Dictionary<Type, List<Constraints.Constraint>> constraints = [];
19+
private readonly Dictionary<Type, List<Constraint>> constraints = [];
1820

1921
/// <summary>
2022
/// Adds a constraint to the store.
2123
/// </summary>
2224
/// <param name="constraint">The constraint to add.</param>
23-
public void Add(Constraints.Constraint constraint)
25+
public void Add(Constraint constraint)
2426
{
2527
if (!this.constraints.TryGetValue(constraint.GetType(), out var list))
2628
{
@@ -29,4 +31,38 @@ public void Add(Constraints.Constraint constraint)
2931
}
3032
list.Add(constraint);
3133
}
34+
35+
/// <summary>
36+
/// Removes the first constraint of a given type.
37+
/// </summary>
38+
/// <typeparam name="TConstraint">The type of the constraint to remove.</typeparam>
39+
/// <param name="predicate">The predicate to match the constraint.</param>
40+
/// <param name="constraint">The constraint removed.</param>
41+
/// <returns>True if the constraint was found and removed, false otherwise.</returns>
42+
public bool TryRemove<TConstraint>([MaybeNullWhen(false)] out TConstraint constraint, Func<TConstraint, bool>? predicate = null)
43+
where TConstraint : Constraint
44+
{
45+
if (!this.constraints.TryGetValue(typeof(TConstraint), out var list))
46+
{
47+
constraint = null;
48+
return false;
49+
}
50+
if (list.Count == 0)
51+
{
52+
constraint = null;
53+
return false;
54+
}
55+
predicate ??= _ => true;
56+
for (var i = list.Count - 1; i >= 0; --i)
57+
{
58+
var constraintAtI = (TConstraint)list[i];
59+
if (!predicate(constraintAtI)) continue;
60+
61+
list.RemoveAt(i);
62+
constraint = constraintAtI;
63+
return true;
64+
}
65+
constraint = null;
66+
return false;
67+
}
3268
}

0 commit comments

Comments
 (0)