Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/slots and variables #56

Merged
merged 19 commits into from
Feb 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion src/ManiaTemplates/Components/MtComponentAttributes.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,35 @@
namespace ManiaTemplates.Components;
using ManiaTemplates.ControlElements;

namespace ManiaTemplates.Components;

public class MtComponentAttributes : Dictionary<string, string>
{
/// <summary>
/// Checks the attribute list for if-condition and if found removes & returns it, else null.
/// </summary>
public string? PullIfCondition()
{
return ContainsKey("if") ? Pull("if") : null;
}

/// <summary>
/// Checks the attribute list for loop-condition and returns it, else null.
/// </summary>
public MtForeach? PullForeachCondition(MtDataContext context, int nodeId, int loopDepth)
{
return ContainsKey("foreach")
? MtForeach.FromString(Pull("foreach"), context, nodeId, loopDepth)
: null;
}

/// <summary>
/// Checks the attribute list for name and if found removes & returns it, else "default".
/// </summary>
public string PullName()
{
return ContainsKey("name") ? Pull("name") : "default";
}

public string Pull(string name)
{
var value = this[name];
Expand Down
4 changes: 1 addition & 3 deletions src/ManiaTemplates/Components/MtComponentMap.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System.Collections.Generic;

namespace ManiaTemplates.Components;
namespace ManiaTemplates.Components;

public class MtComponentMap : Dictionary<string, MtComponentImport>
{
Expand Down
42 changes: 40 additions & 2 deletions src/ManiaTemplates/Components/MtComponentProperty.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,46 @@
namespace ManiaTemplates.Components;
using ManiaTemplates.Interfaces;

public class MtComponentProperty
namespace ManiaTemplates.Components;

public class MtComponentProperty : IStringMethods
{
public required string Type { get; init; }
public required string Name { get; init; }
public string? Default { get; init; }

/// <summary>
/// Determines whether a component property is a string type.
/// </summary>
public bool IsStringType() => IStringMethods.IsStringType(Type);

/// <summary>
/// Gets the default value for this property and wraps it in quotes, if string type.
/// </summary>
public string? GetDefaultWrapped()
{
if (Default == null)
{
return null;
}

return IsStringType() ? IStringMethods.WrapStringInQuotes(Default) : Default;
}

/// <summary>
/// Converts the property to method argument format.
/// </summary>
public string ToMethodArgument()
{
return Default == null
? $"{Type} {Name}"
: $"{Type} {Name} = {GetDefaultWrapped()}";
}

/// <summary>
/// Converts the property to constant for use in render methods.
/// </summary>
public string ToLocalConstant()
{
return $"const {ToMethodArgument()};";
}
}
17 changes: 17 additions & 0 deletions src/ManiaTemplates/ControlElements/MtContextAlias.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace ManiaTemplates.ControlElements;

public class MtContextAlias
{
public MtDataContext Context { get; init; }
public Dictionary<string, string> Aliases { get; } = new();

public MtContextAlias(MtDataContext context)
{
Context = context;
foreach (var (variableName, variableType) in Context)
{
var variableAlias = variableName + (new Random()).Next();
Aliases[variableName] = variableAlias;
}
}
}
8 changes: 7 additions & 1 deletion src/ManiaTemplates/ControlElements/MtDataContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,16 @@ public MtDataContext(string? name = null, MtDataContext? previousContext = null)
public MtDataContext NewContext(MtDataContext otherContext)
{
var clone = new MtDataContext($"{_name}_{otherContext._name}", this);
foreach (var (name, type) in otherContext)

foreach (var (name, type) in this)
{
clone[name] = type;
}

foreach (var (name, type) in otherContext)
{
clone[name] = type; //TODO: prevent duplicate?
}

return clone;
}
Expand Down
14 changes: 9 additions & 5 deletions src/ManiaTemplates/ControlElements/MtForeach.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class MtForeach
private static readonly Regex ForeachVariablesRegex = new(@"^\(?(.+?)(?:$|,\s*(.+)\))");
private static readonly Regex ForeachVariablesTypeSplitterRegex = new(@"^(.+?)(?:$|\s+(.+)$)");

public static MtForeach FromString(string foreachAttributeValue, MtDataContext context, int nodeId)
public static MtForeach FromString(string foreachAttributeValue, MtDataContext context, int nodeId, int loopDepth)
{
//Match the value of the foreach-attribute of the XmlNode.
//Split it into type, variables (var x, var (x,y), ...) and the source.
Expand Down Expand Up @@ -60,7 +60,6 @@ public static MtForeach FromString(string foreachAttributeValue, MtDataContext c

if (nameOrEmpty.Length == 0)
{
// Console.WriteLine($"add: {typeOrVariable.Value} -> {type}");
foundVariables.Add(new MtForeachVariable
{
Type = type,
Expand All @@ -75,7 +74,6 @@ public static MtForeach FromString(string foreachAttributeValue, MtDataContext c
"You may not use var in foreach loops, please specify type.");
}

// Console.WriteLine($"add: {variableOrEmpty.Value} -> {typeOrVariable.Value}");
foundVariables.Add(new MtForeachVariable
{
Type = typeOrName.Value,
Expand All @@ -90,9 +88,15 @@ public static MtForeach FromString(string foreachAttributeValue, MtDataContext c
throw new ParsingForeachLoopFailedException("User defined variables must not start with __.");
}

var indexVariable = "__index";
if (loopDepth > 0)
{
indexVariable += (loopDepth + 1);
}

var newContext = new MtDataContext($"ForEachLoop{nodeId}")
{
{ "__index", "int" }
{ indexVariable, "int" },
};

foreach (var variable in foundVariables)
Expand All @@ -104,7 +108,7 @@ public static MtForeach FromString(string foreachAttributeValue, MtDataContext c
{
Condition = foreachAttributeValue,
Variables = foundVariables,
Context = context.NewContext(newContext)
Context = newContext.NewContext(context)
};
}
}
83 changes: 83 additions & 0 deletions src/ManiaTemplates/Interfaces/ICurlyBraceMethods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using System.Text.RegularExpressions;
using ManiaTemplates.Exceptions;

namespace ManiaTemplates.Interfaces;

public interface ICurlyBraceMethods
{
protected static readonly Regex TemplateInterpolationRegex = new(@"\{\{\s*(.+?)\s*\}\}");

/// <summary>
/// Takes the contents of double curly braces in a string and wraps them into something else. The second Argument takes a string-argument and returns the newly wrapped string.
/// </summary>
public static string ReplaceCurlyBraces(string value, Func<string, string> curlyContentWrapper)
{
PreventCurlyBraceCountMismatch(value);
PreventInterpolationRecursion(value);

var matches = TemplateInterpolationRegex.Match(value);
var output = value;

while (matches.Success)
{
var match = matches.Groups[0].Value.Trim();
var content = matches.Groups[1].Value.Trim();

output = output.Replace(match, curlyContentWrapper(content));

matches = matches.NextMatch();
}

return output;
}

/// <summary>
/// Checks whether double interpolation exists ({{ {{ a }} {{ b }} }}) and throws exception if so.
/// </summary>
public static void PreventInterpolationRecursion(string value)
{
//TODO: find proper algorithm
// var openCurlyBraces = 0;
// foreach (var character in value.ToCharArray())
// {
// if (character == '{')
// {
// openCurlyBraces++;
//
// if (openCurlyBraces >= 4)
// {
// throw new InterpolationRecursionException(
// $"Double interpolation found in: {value}. You must not use double curly braces inside other double curly braces.");
// }
// }
// else if (character == '}')
// {
// openCurlyBraces--;
// }
// }
}

/// <summary>
/// Checks whether double interpolation exists ({{ {{ a }} {{ b }} }}) and throws exception if so.
/// </summary>
public static void PreventCurlyBraceCountMismatch(string value)
{
var openCurlyBraces = 0;
foreach (var character in value.ToCharArray())
{
if (character == '{')
{
openCurlyBraces++;
}
else if (character == '}')
{
openCurlyBraces--;
}
}

if (openCurlyBraces != 0)
{
throw new CurlyBraceCountMismatchException($"Found curly brace count mismatch in: {value}.");
}
}
}
3 changes: 1 addition & 2 deletions src/ManiaTemplates/Interfaces/IManiaTemplate.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Threading.Tasks;
using ManiaTemplates.Components;
using ManiaTemplates.Components;

namespace ManiaTemplates.Interfaces;

Expand Down
1 change: 1 addition & 0 deletions src/ManiaTemplates/Interfaces/IManiaTemplateLanguage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ public interface IManiaTemplateLanguage
public Snippet FeatureBlock(string content);
public string FeatureBlockStart();
public string FeatureBlockEnd();
public string OptimizeOutput(string generatedContent) => generatedContent;
}
16 changes: 16 additions & 0 deletions src/ManiaTemplates/Interfaces/IStringMethods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace ManiaTemplates.Interfaces;

public interface IStringMethods
{
/// <summary>
/// Determines whether a component property is a string type.
/// </summary>
public static bool IsStringType(string typeString)
=> typeString.ToLower().Contains("string"); //TODO: find better way to determine string

/// <summary>
/// Wraps a string in quotes.
/// </summary>
public static string WrapStringInQuotes(string str)
=> $@"$""{str}""";
}
62 changes: 62 additions & 0 deletions src/ManiaTemplates/Interfaces/IXmlMethods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System.Xml;
using ManiaTemplates.Components;

namespace ManiaTemplates.Interfaces;

public interface IXmlMethods: ICurlyBraceMethods
{
/// <summary>
/// Parses the attributes of a XmlNode to an MtComponentAttributes-instance.
/// </summary>
public static MtComponentAttributes GetAttributes(XmlNode node)
{
var attributeList = new MtComponentAttributes();
if (node.Attributes == null) return attributeList;

foreach (XmlAttribute attribute in node.Attributes)
{
attributeList.Add(attribute.Name, attribute.Value);
}

return attributeList;
}

/// <summary>
/// Creates a xml opening tag for the given string and attribute list.
/// </summary>
public static string CreateOpeningTag(string tag, MtComponentAttributes attributeList, bool hasChildren, Func<string, string> curlyContentWrapper)
{
var output = $"<{tag}";

foreach (var (attributeName, attributeValue) in attributeList)
{
output += @$" {attributeName}=""{ReplaceCurlyBraces(attributeValue, curlyContentWrapper)}""";
}

if (!hasChildren)
{
output += " /";
}

return output + ">";
}

/// <summary>
/// Creates a xml closing tag for the given string.
/// </summary>
public static string CreateClosingTag(string tag)
{
return $"</{tag}>";
}

/// <summary>
/// Converts any valid XML-string into an XmlNode-element.
/// </summary>
public static XmlNode NodeFromString(string content)
{
var doc = new XmlDocument();
doc.LoadXml($"<doc>{content}</doc>");

return doc.FirstChild!;
}
}
Loading
Loading