Skip to content

Commit

Permalink
Add method to recover expression from string item effect.
Browse files Browse the repository at this point in the history
  • Loading branch information
homothetyhk committed Feb 3, 2024
1 parent 4458f52 commit f4a4e0b
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 0 deletions.
73 changes: 73 additions & 0 deletions RandomizerCore/StringItems/StringItem.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using RandomizerCore.Logic;
using RandomizerCore.LogicItems;
using RandomizerCore.StringParsing;

namespace RandomizerCore.StringItems
{
Expand Down Expand Up @@ -39,6 +40,17 @@ public abstract record StringItemEffect
public abstract bool AddTo(ProgressionManager pm);
public abstract bool CheckForEffect(ProgressionManager pm);
public abstract IEnumerable<Term> GetAffectedTerms();
/// <summary>
/// Converts the effect to an expression tree, with standardized formatting. May differ from the expression implied by <see cref="StringItem.EffectString"/>.
/// </summary>
public abstract IExpression<ItemExpressionType> ToExpression();
/// <summary>
/// Converts the effect to an effect string. By default, this prints the result of <see cref="ToExpression"/>, and may differ from <see cref="StringItem.EffectString"/>.
/// </summary>
public virtual string ToEffectString() => ToExpression().Print();
internal static ItemExpressionFactory ExpressionFactory { get; } = new ItemExpressionFactory();
internal static ItemOperatorProvider OperatorProvider { get; } = new ItemOperatorProvider();
internal static ExpressionBuilder<ItemExpressionType> ExpressionBuilder { get; } = new(OperatorProvider, ExpressionFactory);
}

public sealed record EmptyEffect : StringItemEffect
Expand All @@ -47,6 +59,7 @@ public sealed record EmptyEffect : StringItemEffect
public override bool AddTo(ProgressionManager pm) => false;
public override bool CheckForEffect(ProgressionManager pm) => false;
public override IEnumerable<Term> GetAffectedTerms() => Enumerable.Empty<Term>();
public override IExpression<ItemExpressionType> ToExpression() => ExpressionBuilder.NameAtom(ItemExpressionFactory.EmptyEffect);
}

public record AllOfEffect : StringItemEffect
Expand Down Expand Up @@ -74,6 +87,21 @@ public override IEnumerable<Term> GetAffectedTerms()
{
return Effects.SelectMany(e => e.GetAffectedTerms());
}

public override IExpression<ItemExpressionType> ToExpression()
{
return ExpressionBuilder.ApplyInfixOperatorLeftAssoc(Effects.Select(e => e.ToExpression()), ExpressionBuilder.Op(ItemOperatorProvider.Chaining));
}

public virtual bool Equals(AllOfEffect? other)
{
return other is not null && other.Effects.SequenceEqual(Effects);
}

public override int GetHashCode()
{
return Effects[0].GetHashCode() ^ Effects.Length;
}
}

public record FirstOfEffect : StringItemEffect
Expand All @@ -100,6 +128,22 @@ public override IEnumerable<Term> GetAffectedTerms()
{
return Effects.SelectMany(e => e.GetAffectedTerms());
}


public override IExpression<ItemExpressionType> ToExpression()
{
return ExpressionBuilder.ApplyInfixOperatorLeftAssoc(Effects.Select(e => e.ToExpression()), ExpressionBuilder.Op(ItemOperatorProvider.ShortCircuitChaining));
}

public virtual bool Equals(FirstOfEffect? other)
{
return other is not null && other.Effects.SequenceEqual(Effects);
}

public override int GetHashCode()
{
return Effects[0].GetHashCode() ^ Effects.Length;
}
}

public record IncrementEffect(int Value, Term Term) : StringItemEffect
Expand All @@ -119,6 +163,18 @@ public override IEnumerable<Term> GetAffectedTerms()
{
yield return Term;
}

public override IExpression<ItemExpressionType> ToExpression()
{
if (Value == 1)
{
return ExpressionBuilder.ApplyPostfixOperator(ExpressionBuilder.NameAtom(Term.Name), ExpressionBuilder.Op(ItemOperatorProvider.Increment));
}
else
{
return ExpressionBuilder.ApplyInfixOperator(ExpressionBuilder.NameAtom(Term.Name), ExpressionBuilder.Op(ItemOperatorProvider.AdditionAssignment), ExpressionBuilder.NumberAtom(Value));
}
}
}

public record MaxWithEffect(int Value, Term Term) : StringItemEffect
Expand All @@ -142,6 +198,11 @@ public override IEnumerable<Term> GetAffectedTerms()
{
yield return Term;
}

public override IExpression<ItemExpressionType> ToExpression()
{
return ExpressionBuilder.ApplyInfixOperator(ExpressionBuilder.NameAtom(Term.Name), ExpressionBuilder.Op(ItemOperatorProvider.MaxAssignment), ExpressionBuilder.NumberAtom(Value));
}
}

public record ConditionalEffect(LogicDef Logic, StringItemEffect Effect, bool Negated = false) : StringItemEffect
Expand All @@ -164,6 +225,13 @@ public override IEnumerable<Term> GetAffectedTerms()
{
return Effect.GetAffectedTerms();
}

public override IExpression<ItemExpressionType> ToExpression()
{
IExpression<ItemExpressionType> logicExpr = ExpressionBuilder.StringAtom(Logic.InfixSource);
if (Negated) logicExpr = ExpressionBuilder.ApplyPrefixOperator(ExpressionBuilder.Op(ItemOperatorProvider.Negation), logicExpr);
return ExpressionBuilder.ApplyInfixOperator(logicExpr, ExpressionBuilder.Op(ItemOperatorProvider.Conditional), Effect.ToExpression());
}
}

public record ReferenceEffect(LogicItem Item) : StringItemEffect
Expand Down Expand Up @@ -191,5 +259,10 @@ public override IEnumerable<Term> GetAffectedTerms()
{
return Item.GetAffectedTerms();
}

public override IExpression<ItemExpressionType> ToExpression()
{
return ExpressionBuilder.ApplyPrefixOperator(ExpressionBuilder.Op(ItemOperatorProvider.Reference), ExpressionBuilder.NameAtom(Item.Name));
}
}
}
5 changes: 5 additions & 0 deletions RandomizerCore/StringParsing/ExpressionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ public IExpression<T> ApplyInfixOperator(IExpression<T> argL, OperatorToken op,
return expressionFactory.CreateInfixExpression(argL, op, argR);
}

public IExpression<T> ApplyInfixOperatorLeftAssoc(IEnumerable<IExpression<T>> args, OperatorToken op)
{
return args.Aggregate((expr, operand) => ApplyInfixOperator(expr, op, operand));
}

public IExpression<T> ApplyPrefixOperator(OperatorToken op, IExpression<T> operand)
{
int? pOperand = GetBindingPower(operand, true);
Expand Down
55 changes: 55 additions & 0 deletions RandomizerCoreTests/EffectToExpressionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using FluentAssertions;
using RandomizerCore.Logic;
using RandomizerCore.StringItems;
using RandomizerCore.StringParsing;

namespace RandomizerCoreTests
{
public class EffectToExpressionTests
{
[Theory]
[InlineData("_")]
[InlineData("A++")]
[InlineData("A++ >> B++")]
[InlineData("A++ >> B++ >> C++")]
[InlineData("A++ >> B++ >|> C++")]
[InlineData("`A<1` => B++")]
[InlineData("!`A<1` => B++")]
[InlineData("*I")]
public void IdentityTest(string infix)
{
LogicManagerBuilder lmb = new();
string[] terms = ["A", "B", "C"];
foreach (string s in terms) lmb.GetOrAddTerm(s);
lmb.AddItem(new StringItemTemplate("I", "_"));

lmb.AddItem(new StringItemTemplate("Test_Item", infix));

LogicManager lm = new(lmb);

StringItem item = (StringItem)lm.GetItemStrict("Test_Item");

item.Effect.ToEffectString().Should().Be(infix);
}

[Theory]
[InlineData("A++ >> (B++ >> C++)", "A++ >> B++ >> C++")]
[InlineData("A += 1", "A++")]
[InlineData("A+=2", "A += 2")]
public void NonidentityTest(string infix, string result)
{
LogicManagerBuilder lmb = new();
string[] terms = ["A", "B", "C"];
foreach (string s in terms) lmb.GetOrAddTerm(s);
lmb.AddItem(new StringItemTemplate("I", "_"));

lmb.AddItem(new StringItemTemplate("Test_Item", infix));

LogicManager lm = new(lmb);

StringItem item = (StringItem)lm.GetItemStrict("Test_Item");

item.Effect.ToEffectString().Should().Be(result);
}
}
}

0 comments on commit f4a4e0b

Please sign in to comment.