Skip to content

Commit

Permalink
Slotted mixins
Browse files Browse the repository at this point in the history
  • Loading branch information
cheese3660 committed Feb 17, 2024
1 parent 95618ce commit adfa158
Show file tree
Hide file tree
Showing 17 changed files with 2,132 additions and 1,724 deletions.
15 changes: 14 additions & 1 deletion src/PatchManager.SassyPatching/Execution/Environment.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using JetBrains.Annotations;
using PatchManager.SassyPatching.Nodes;
using PatchManager.SassyPatching.Nodes.Statements.SelectionLevel;

namespace PatchManager.SassyPatching.Execution;

Expand All @@ -20,6 +22,16 @@ public class Environment
/// </summary>
public Dictionary<string, DataValue> ScopedValues;


[CanBeNull] private List<Node> _slotActions;

[CanBeNull]
public List<Node> SlotActions
{
get => _slotActions ?? Parent?.SlotActions;
set => _slotActions = value;
}

/// <summary>
/// Creates a new environment
/// </summary>
Expand Down Expand Up @@ -76,7 +88,8 @@ public Environment Snapshot()
var parent = Parent?.Snapshot();
return new Environment(GlobalEnvironment, parent)
{
ScopedValues = scopedValues
ScopedValues = scopedValues,
_slotActions = _slotActions
};
}
}
86 changes: 46 additions & 40 deletions src/PatchManager.SassyPatching/Execution/PatchMixin.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using JetBrains.Annotations;
using PatchManager.SassyPatching.Exceptions;
using PatchManager.SassyPatching.Interfaces;
using PatchManager.SassyPatching.Nodes;
using PatchManager.SassyPatching.Nodes.Statements.SelectionLevel;
using PatchManager.SassyPatching.Nodes.Statements.TopLevel;

Expand All @@ -17,48 +18,10 @@ public PatchMixin(Mixin mixin)

public void Include(Environment env, List<PatchArgument> arguments, ISelectable selectable, [CanBeNull] IModifiable modifiable)
{
Environment subEnvironment = new Environment(env.GlobalEnvironment, env);
var subEnvironment = new Environment(env.GlobalEnvironment, env);
foreach (var arg in Function.Arguments)
{
// As per usual we consume
bool foundPositional = false;
DataValue argument = null;
int removalIndex = -1;
for (int i = 0; i < arguments.Count; i++)
{
if (!foundPositional && arguments[i].ArgumentName == null)
{
foundPositional = true;
removalIndex = i;
argument = arguments[i].ArgumentDataValue;
}

if (arguments[i].ArgumentName != arg.Name) continue;
removalIndex = i;
argument = arguments[i].ArgumentDataValue;
break;
}

if (removalIndex >= 0)
{
arguments.RemoveAt(removalIndex);
}
if (argument == null)
{
if (arg.Value != null)
{
subEnvironment[arg.Name] = arg.Value.Compute(subEnvironment);
}
else
{
throw new InvocationException($"No value found for argument: {arg.Name}");
}
}
else
{
// args.Add(CheckParameter(parameter, argument));
subEnvironment[arg.Name] = argument;
}
ConsumeMixinArgument(arguments, arg, subEnvironment);
}

if (arguments.Count > 0)
Expand All @@ -78,4 +41,47 @@ public void Include(Environment env, List<PatchArgument> arguments, ISelectable
}

}

private static void ConsumeMixinArgument(List<PatchArgument> arguments, Argument arg, Environment subEnvironment)
{
// As per usual we consume
var foundPositional = false;
DataValue argument = null;
var removalIndex = -1;
for (var i = 0; i < arguments.Count; i++)
{
if (!foundPositional && arguments[i].ArgumentName == null)
{
foundPositional = true;
removalIndex = i;
argument = arguments[i].ArgumentDataValue;
}

if (arguments[i].ArgumentName != arg.Name) continue;
removalIndex = i;
argument = arguments[i].ArgumentDataValue;
break;
}

if (removalIndex >= 0)
{
arguments.RemoveAt(removalIndex);
}
if (argument == null)
{
if (arg.Value != null)
{
subEnvironment[arg.Name] = arg.Value.Compute(subEnvironment);
}
else
{
throw new InvocationException($"No value found for argument: {arg.Name}");
}
}
else
{
// args.Add(CheckParameter(parameter, argument));
subEnvironment[arg.Name] = argument;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using PatchManager.SassyPatching.Exceptions;
using PatchManager.SassyPatching.Interfaces;
using Environment = PatchManager.SassyPatching.Execution.Environment;

namespace PatchManager.SassyPatching.Nodes.Statements.SelectionLevel;

/// <summary>
/// Represents a mixin block include (i.e. slotting actions into a mixin)
/// </summary>
public class MixinBlockInclude : Node, ISelectionAction
{
/// <summary>
/// The name of the mixin being included
/// </summary>
public readonly string MixinName;
/// <summary>
/// The list of arguments to the mixin being included
/// </summary>
public readonly List<CallArgument> Arguments;

/// <summary>
/// The actions to be slotted into the mixin
/// </summary>
public readonly List<Node> SlotActions;

internal MixinBlockInclude(Coordinate c, string mixinName, List<CallArgument> arguments, List<Node> slotActions) : base(c)
{
MixinName = mixinName;
Arguments = arguments;
SlotActions = slotActions;
}

/// <inheritdoc />
public override void ExecuteIn(Environment environment)
{
}

/// <inheritdoc />
public void ExecuteOn(Environment environment, ISelectable selectable, IModifiable modifiable)
{
if (environment.GlobalEnvironment.AllMixins.TryGetValue(MixinName, out var mixin))
{
try
{
var subEnv = new Environment(environment.GlobalEnvironment, environment)
{
SlotActions = SlotActions
};
mixin.Include(subEnv,Arguments.Select(x => x.Compute(environment)).ToList(),selectable,modifiable);
}
catch (InvocationException e)
{
throw new InterpreterException(Coordinate, e.ToString());
}
}
else
{
throw new InterpreterException(Coordinate, $"{MixinName} is not a valid mixin");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using PatchManager.SassyPatching.Exceptions;
using PatchManager.SassyPatching.Interfaces;
using Environment = PatchManager.SassyPatching.Execution.Environment;

namespace PatchManager.SassyPatching.Nodes.Statements.SelectionLevel;

public class MixinSlot(Coordinate c) : Node(c), ISelectionAction
{
public override void ExecuteIn(Environment environment)
{
}

public void ExecuteOn(Environment environment, ISelectable selectable, IModifiable modifiable)
{
var actions = environment.SlotActions;
if (actions == null)
{
throw new InterpreterException(Coordinate, "Attempting to insert into a mixin slot without there being any actions passed for this purpose");
}

foreach (var action in actions)
{
if (action is ISelectionAction selectionAction)
{
selectionAction.ExecuteOn(environment, selectable, modifiable);
}
else
{
action.ExecuteIn(environment);
}
}
}
}
Loading

0 comments on commit adfa158

Please sign in to comment.