From 6eb2810baf40a51763623363a4502dcf75224a55 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Wed, 4 Oct 2023 19:12:30 +0200 Subject: [PATCH] Added outline for decision tree --- .../Internal/FlowAnalysis/DecisionTree.cs | 137 ++++++++++++++++++ .../FlowAnalysis/Domain/ValueDomain.cs | 10 -- 2 files changed, 137 insertions(+), 10 deletions(-) create mode 100644 src/Draco.Compiler/Internal/FlowAnalysis/DecisionTree.cs diff --git a/src/Draco.Compiler/Internal/FlowAnalysis/DecisionTree.cs b/src/Draco.Compiler/Internal/FlowAnalysis/DecisionTree.cs new file mode 100644 index 000000000..0a8c5ece5 --- /dev/null +++ b/src/Draco.Compiler/Internal/FlowAnalysis/DecisionTree.cs @@ -0,0 +1,137 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Draco.Compiler.Internal.BoundTree; + +namespace Draco.Compiler.Internal.FlowAnalysis; + +/// +/// Represents a decision tree computed for a match expression. +/// It helps guiding the rewriter to generate code as well as reporting things like redundant branches or +/// missing cases. +/// +/// The action type being performed, when a branch is matched. +internal sealed class DecisionTree +{ + /// + /// A single arm in the match construct. + /// + /// The matched pattern. + /// The taken action if matches. + public readonly record struct Arm(BoundPattern Pattern, TAction Action); + + /// + /// Represents a redundant arm. + /// + /// The arm that covers the one already. + /// The arm that is redundant, because already + /// matches. + public readonly record struct Redundance(Arm CoveredBy, Arm Redundant); + + /// + /// A single node in the decision tree. + /// + public abstract class Node + { + /// + /// The parent node of this one. + /// + public virtual Node? Parent => null; + + /// + /// The index of the row this node originated from in the parent. + /// + public virtual int? ParentRowIndex => null; + + /// + /// True, if this is an action node, meaning that there is a match. + /// + public virtual bool IsAction => false; + + /// + /// The action that's associated with the node. + /// + [MemberNotNullWhen(true, nameof(IsAction))] + public virtual TAction? Action => default; + + /// + /// True, if this is a failure node. + /// + public virtual bool IsFail => false; + + /// + /// The counterexample of this node, if it's a failure node and a counterexample could be produced. + /// The counterexample in this case means a pattern that was not covered. + /// + public virtual BoundPattern? Counterexample => null; + + /// + /// The expression being matched on, if any. + /// + public virtual BoundExpression? MatchedOn => null; + + /// + /// The child nodes of this one, associated to the pattern to match to take the route to the child. + /// + public virtual ImmutableArray> Children => + ImmutableArray>.Empty; + } + + /// + /// Builds a decision tree from the given data. + /// + /// The matched value. + /// The arms of the match. + /// The constructed decision tree. + public static DecisionTree Build(BoundExpression matchedValue, ImmutableArray arms) => + throw new NotImplementedException(); + + /// + /// Stringifies the given to a user-readable format. + /// + /// The pattern to stringify. + /// The user-readable form of . + public static string ToDisplayString(BoundPattern pattern) => pattern switch + { + _ => throw new ArgumentOutOfRangeException(nameof(pattern)), + }; + + /// + /// The matched value. + /// + public BoundExpression MatchedValue { get; } + + /// + /// The arms of the root construct. + /// + public ImmutableArray Arms { get; } + + /// + /// The root node of this tree. + /// + public Node Root { get; } + + /// + /// All redundancies in the tree. + /// + public ImmutableArray Redundancies { get; } + + /// + /// True, if this tree is exhaustive. + /// + public bool IsExhaustive { get; } + + /// + /// An example of an uncovered pattern, if any. + /// + public BoundPattern? UncoveredExample { get; } + + private DecisionTree() + { + // TODO + } +} diff --git a/src/Draco.Compiler/Internal/FlowAnalysis/Domain/ValueDomain.cs b/src/Draco.Compiler/Internal/FlowAnalysis/Domain/ValueDomain.cs index fd02dc797..32fcb909e 100644 --- a/src/Draco.Compiler/Internal/FlowAnalysis/Domain/ValueDomain.cs +++ b/src/Draco.Compiler/Internal/FlowAnalysis/Domain/ValueDomain.cs @@ -26,16 +26,6 @@ public static ValueDomain CreateDomain(IntrinsicSymbols intrinsics, TypeSymbol t throw new ArgumentOutOfRangeException(nameof(type)); } - /// - /// Stringifies the given to a user-readable format. - /// - /// The pattern to stringify. - /// The user-readable form of . - public static string ToDisplayString(BoundPattern pattern) => pattern switch - { - _ => throw new ArgumentOutOfRangeException(nameof(pattern)), - }; - /// /// True, if this domain has been emptied. ///