From 708b837947c3d2789458b2f4cb43305ad256e9e0 Mon Sep 17 00:00:00 2001 From: Stan H Date: Fri, 22 Feb 2019 13:09:07 +0100 Subject: [PATCH 1/8] (builtin-macros) IsDefined --- ColorzCore/ColorzCore.csproj | 3 +- ColorzCore/Parser/Macros/IsDefined.cs | 58 +++++++++++++++++++++ ColorzCore/Parser/Macros/MacroCollection.cs | 6 ++- 3 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 ColorzCore/Parser/Macros/IsDefined.cs diff --git a/ColorzCore/ColorzCore.csproj b/ColorzCore/ColorzCore.csproj index 75667fe..2ee1a63 100644 --- a/ColorzCore/ColorzCore.csproj +++ b/ColorzCore/ColorzCore.csproj @@ -1,5 +1,5 @@  - + Debug @@ -108,6 +108,7 @@ + diff --git a/ColorzCore/Parser/Macros/IsDefined.cs b/ColorzCore/Parser/Macros/IsDefined.cs new file mode 100644 index 0000000..3880267 --- /dev/null +++ b/ColorzCore/Parser/Macros/IsDefined.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using ColorzCore.Lexer; + +namespace ColorzCore.Parser.Macros +{ + class IsDefined : BuiltInMacro + { + public EAParser ParentParser { get; private set; } + + public IsDefined(EAParser parent) + { + ParentParser = parent; + } + + public override IEnumerable ApplyMacro(Token head, IList> parameters) + { + if (parameters[0].Count != 1) + { + // TODO: err somehow + yield return MakeFalseToken(head.Location); + } + else + { + Token token = parameters[0][0]; + + if ((token.Type == TokenType.IDENTIFIER) && IsReallyDefined(token.Content)) + { + yield return MakeTrueToken(head.Location); + } + else + { + yield return MakeFalseToken(head.Location); + } + } + } + + public override bool ValidNumParams(int num) + { + return num == 1; + } + + protected bool IsReallyDefined(string name) + { + return ParentParser.Definitions.ContainsKey(name) || ParentParser.Macros.ContainsName(name); + } + + protected static Token MakeTrueToken(DataTypes.Location location) + { + return new Token(TokenType.NUMBER, location, "1"); + } + + protected static Token MakeFalseToken(DataTypes.Location location) + { + return new Token(TokenType.NUMBER, location, "0"); + } + } +} diff --git a/ColorzCore/Parser/Macros/MacroCollection.cs b/ColorzCore/Parser/Macros/MacroCollection.cs index 12e40ec..b6a910a 100644 --- a/ColorzCore/Parser/Macros/MacroCollection.cs +++ b/ColorzCore/Parser/Macros/MacroCollection.cs @@ -17,7 +17,11 @@ public MacroCollection(EAParser parent) { Macros = new Dictionary>(); Parent = parent; - BuiltInMacros = new Dictionary { { "String", String.Instance } }; + + BuiltInMacros = new Dictionary { + { "String", String.Instance }, + { "IsDefined", new IsDefined(parent) }, + }; } public bool HasMacro(string name, int paramNum) From 2462c9644731a1096da2e5bfeaa6d29d949f8dd1 Mon Sep 17 00:00:00 2001 From: Stan H Date: Fri, 22 Feb 2019 13:10:25 +0100 Subject: [PATCH 2/8] (builtin-macros) non-singleton String for consistency --- ColorzCore/Parser/Macros/MacroCollection.cs | 2 +- ColorzCore/Parser/Macros/String.cs | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/ColorzCore/Parser/Macros/MacroCollection.cs b/ColorzCore/Parser/Macros/MacroCollection.cs index b6a910a..bea8046 100644 --- a/ColorzCore/Parser/Macros/MacroCollection.cs +++ b/ColorzCore/Parser/Macros/MacroCollection.cs @@ -19,7 +19,7 @@ public MacroCollection(EAParser parent) Parent = parent; BuiltInMacros = new Dictionary { - { "String", String.Instance }, + { "String", new String() }, { "IsDefined", new IsDefined(parent) }, }; } diff --git a/ColorzCore/Parser/Macros/String.cs b/ColorzCore/Parser/Macros/String.cs index afdbd3f..1074a36 100644 --- a/ColorzCore/Parser/Macros/String.cs +++ b/ColorzCore/Parser/Macros/String.cs @@ -9,12 +9,6 @@ namespace ColorzCore.Parser.Macros { class String : BuiltInMacro { - private static String instance = new String(); - - public static String Instance { get { return instance; } } - - private String() { } - public override IEnumerable ApplyMacro(Token head, IList> parameters) { yield return new Token(TokenType.IDENTIFIER, head.Location, "BYTE"); From 7a2f5b4a4a9ed93e48333adf7fb03808e145f83d Mon Sep 17 00:00:00 2001 From: Stan H Date: Fri, 22 Feb 2019 13:44:51 +0100 Subject: [PATCH 3/8] (builtin-macros) AddToPool and pool --- ColorzCore/ColorzCore.csproj | 2 + ColorzCore/Parser/EAParser.cs | 12 ++++ ColorzCore/Parser/Macros/AddToPool.cs | 56 +++++++++++++++++++ ColorzCore/Parser/Macros/MacroCollection.cs | 1 + ColorzCore/Preprocessor/DirectiveHandler.cs | 5 +- .../Preprocessor/Directives/PoolDirective.cs | 28 ++++++++++ 6 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 ColorzCore/Parser/Macros/AddToPool.cs create mode 100644 ColorzCore/Preprocessor/Directives/PoolDirective.cs diff --git a/ColorzCore/ColorzCore.csproj b/ColorzCore/ColorzCore.csproj index 2ee1a63..8af3f42 100644 --- a/ColorzCore/ColorzCore.csproj +++ b/ColorzCore/ColorzCore.csproj @@ -109,6 +109,8 @@ + + diff --git a/ColorzCore/Parser/EAParser.cs b/ColorzCore/Parser/EAParser.cs index d4ef207..9f49786 100644 --- a/ColorzCore/Parser/EAParser.cs +++ b/ColorzCore/Parser/EAParser.cs @@ -46,6 +46,9 @@ class EAParser } public ImmutableStack Inclusion { get; set; } + public List> PooledLines { get; private set; } + private long poolLabelCounter; + private readonly DirectiveHandler directiveHandler; private Stack> pastOffsets; // currentOffset, offsetInitialized @@ -79,6 +82,9 @@ public EAParser(Dictionary> raws, Log log, DirectiveHandler d Definitions = new Dictionary(); Inclusion = ImmutableStack.Nil; this.directiveHandler = directiveHandler; + + PooledLines = new List>(); + poolLabelCounter = 0; } public bool IsReservedName(string name) @@ -761,6 +767,12 @@ public bool ExpandIdentifier(MergeableGenerator tokens) return ret; } + public string MakePoolLabelName() + { + // The presence of $ in the label name guarantees that it can't be a user label + return string.Format("__POOLED${0}", poolLabelCounter++); + } + public void Message(Location? loc, string message) { log.Message(Log.MsgKind.MESSAGE, loc, message); diff --git a/ColorzCore/Parser/Macros/AddToPool.cs b/ColorzCore/Parser/Macros/AddToPool.cs new file mode 100644 index 0000000..1146b9f --- /dev/null +++ b/ColorzCore/Parser/Macros/AddToPool.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using ColorzCore.Lexer; + +namespace ColorzCore.Parser.Macros +{ + class AddToPool : BuiltInMacro + { + /* + * Macro Usage: + * AddToPool(tokens...): adds token to pool, and expands to label name referring to those tokens + * AddToPool(tokens..., alignment): adds token to pool and make sure pooled tokens are aligned given alignment + */ + + public EAParser ParentParser { get; private set; } + + public AddToPool(EAParser parent) + { + ParentParser = parent; + } + + public override IEnumerable ApplyMacro(Token head, IList> parameters) + { + List line = new List(6 + parameters[0].Count); + + string labelName = ParentParser.MakePoolLabelName(); + + if (parameters.Count == 2) + { + // Add Alignment directive + + line.Add(new Token(TokenType.IDENTIFIER, head.Location, "ALIGN")); + line.Add(parameters[1][0]); + line.Add(new Token(TokenType.SEMICOLON, head.Location, ";")); + } + + // TODO: Make label declaration global (when this feature gets implemented) + // This way the name will be available as long as it is pooled (reguardless of pool scope) + + line.Add(new Token(TokenType.IDENTIFIER, head.Location, labelName)); + line.Add(new Token(TokenType.COLON, head.Location, ":")); + + line.AddRange(parameters[0]); + line.Add(new Token(TokenType.NEWLINE, head.Location, "\n")); + + ParentParser.PooledLines.Add(line); + + yield return new Token(TokenType.IDENTIFIER, head.Location, labelName); + } + + public override bool ValidNumParams(int num) + { + return num == 1 || num == 2; + } + } +} diff --git a/ColorzCore/Parser/Macros/MacroCollection.cs b/ColorzCore/Parser/Macros/MacroCollection.cs index bea8046..40e78d0 100644 --- a/ColorzCore/Parser/Macros/MacroCollection.cs +++ b/ColorzCore/Parser/Macros/MacroCollection.cs @@ -21,6 +21,7 @@ public MacroCollection(EAParser parent) BuiltInMacros = new Dictionary { { "String", new String() }, { "IsDefined", new IsDefined(parent) }, + { "AddToPool", new AddToPool(parent) }, }; } diff --git a/ColorzCore/Preprocessor/DirectiveHandler.cs b/ColorzCore/Preprocessor/DirectiveHandler.cs index 43a65a8..3cf8ff2 100644 --- a/ColorzCore/Preprocessor/DirectiveHandler.cs +++ b/ColorzCore/Preprocessor/DirectiveHandler.cs @@ -29,8 +29,9 @@ public DirectiveHandler(IncludeFileSearcher includeSearcher, IncludeFileSearcher { "ifndef", new IfNotDefinedDirective() }, { "else", new ElseDirective() }, { "endif", new EndIfDirective() }, - { "define", new DefineDirective() }, //TODO: pool - { "undef", new UndefineDirective() } + { "define", new DefineDirective() }, + { "pool", new PoolDirective() }, + { "undef", new UndefineDirective() }, }; } diff --git a/ColorzCore/Preprocessor/Directives/PoolDirective.cs b/ColorzCore/Preprocessor/Directives/PoolDirective.cs new file mode 100644 index 0000000..7ac1ea3 --- /dev/null +++ b/ColorzCore/Preprocessor/Directives/PoolDirective.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using ColorzCore.DataTypes; +using ColorzCore.Lexer; +using ColorzCore.Parser; +using ColorzCore.Parser.AST; + +namespace ColorzCore.Preprocessor.Directives +{ + class PoolDirective : IDirective + { + public int MinParams => 0; + public int? MaxParams => 0; + public bool RequireInclusion => true; + + public Maybe Execute(EAParser p, Token self, IList parameters, MergeableGenerator tokens) + { + foreach (List line in p.PooledLines) + { + tokens.PrependEnumerator(line.GetEnumerator()); + } + + p.PooledLines.Clear(); + + return new Nothing(); + } + } +} From c7dc132f85f9915daeb9fec6acae652f87b9e5a0 Mon Sep 17 00:00:00 2001 From: Stan H Date: Fri, 22 Feb 2019 15:36:32 +0100 Subject: [PATCH 4/8] (builtin-macros) move pool label generated to AddToPool --- ColorzCore/Parser/EAParser.cs | 8 -------- ColorzCore/Parser/Macros/AddToPool.cs | 11 ++++++++++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/ColorzCore/Parser/EAParser.cs b/ColorzCore/Parser/EAParser.cs index 9f49786..d24ec57 100644 --- a/ColorzCore/Parser/EAParser.cs +++ b/ColorzCore/Parser/EAParser.cs @@ -47,7 +47,6 @@ class EAParser public ImmutableStack Inclusion { get; set; } public List> PooledLines { get; private set; } - private long poolLabelCounter; private readonly DirectiveHandler directiveHandler; @@ -84,7 +83,6 @@ public EAParser(Dictionary> raws, Log log, DirectiveHandler d this.directiveHandler = directiveHandler; PooledLines = new List>(); - poolLabelCounter = 0; } public bool IsReservedName(string name) @@ -767,12 +765,6 @@ public bool ExpandIdentifier(MergeableGenerator tokens) return ret; } - public string MakePoolLabelName() - { - // The presence of $ in the label name guarantees that it can't be a user label - return string.Format("__POOLED${0}", poolLabelCounter++); - } - public void Message(Location? loc, string message) { log.Message(Log.MsgKind.MESSAGE, loc, message); diff --git a/ColorzCore/Parser/Macros/AddToPool.cs b/ColorzCore/Parser/Macros/AddToPool.cs index 1146b9f..99276cc 100644 --- a/ColorzCore/Parser/Macros/AddToPool.cs +++ b/ColorzCore/Parser/Macros/AddToPool.cs @@ -14,16 +14,19 @@ class AddToPool : BuiltInMacro public EAParser ParentParser { get; private set; } + private long poolLabelCounter; + public AddToPool(EAParser parent) { ParentParser = parent; + poolLabelCounter = 0; } public override IEnumerable ApplyMacro(Token head, IList> parameters) { List line = new List(6 + parameters[0].Count); - string labelName = ParentParser.MakePoolLabelName(); + string labelName = MakePoolLabelName(); if (parameters.Count == 2) { @@ -52,5 +55,11 @@ public override bool ValidNumParams(int num) { return num == 1 || num == 2; } + + protected string MakePoolLabelName() + { + // The presence of $ in the label name guarantees that it can't be a user label + return string.Format("__POOLED${0}", poolLabelCounter++); + } } } From 90ffd4b2cd5685d1933124f828db701c28d1a663 Mon Sep 17 00:00:00 2001 From: Stan H Date: Fri, 22 Feb 2019 16:00:56 +0100 Subject: [PATCH 5/8] (builtin-macros) #pool expands to BlockNode instead of tokens --- ColorzCore/Preprocessor/Directives/PoolDirective.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/ColorzCore/Preprocessor/Directives/PoolDirective.cs b/ColorzCore/Preprocessor/Directives/PoolDirective.cs index 7ac1ea3..a0f33cd 100644 --- a/ColorzCore/Preprocessor/Directives/PoolDirective.cs +++ b/ColorzCore/Preprocessor/Directives/PoolDirective.cs @@ -15,14 +15,23 @@ class PoolDirective : IDirective public Maybe Execute(EAParser p, Token self, IList parameters, MergeableGenerator tokens) { + BlockNode result = new BlockNode(); + foreach (List line in p.PooledLines) { - tokens.PrependEnumerator(line.GetEnumerator()); + MergeableGenerator tempGenerator = new MergeableGenerator(line); + tempGenerator.MoveNext(); + + while (!tempGenerator.EOS) + { + p.ParseLine(tempGenerator, p.GlobalScope).IfJust( + (lineNode) => result.Children.Add(lineNode)); + } } p.PooledLines.Clear(); - return new Nothing(); + return new Just(result); } } } From 878646333b97d8afbc38cbd9f79d46497a498ea1 Mon Sep 17 00:00:00 2001 From: Stan H Date: Fri, 22 Feb 2019 16:28:10 +0100 Subject: [PATCH 6/8] (builtin-macros) proper errors on unpooled data --- ColorzCore/EAInterpreter.cs | 10 +++++++++- ColorzCore/Parser/Macros/AddToPool.cs | 4 +++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ColorzCore/EAInterpreter.cs b/ColorzCore/EAInterpreter.cs index e770924..15a6a49 100644 --- a/ColorzCore/EAInterpreter.cs +++ b/ColorzCore/EAInterpreter.cs @@ -3,6 +3,7 @@ using ColorzCore.Lexer; using ColorzCore.Parser; using ColorzCore.Parser.AST; +using ColorzCore.Parser.Macros; using ColorzCore.Raws; using System; using System.Collections.Generic; @@ -100,7 +101,14 @@ public bool Interpret() foreach (Token errCause in undefinedIds) { - myParser.Error(errCause.Location, "Undefined identifier: " + errCause.Content); + if (errCause.Content.StartsWith(AddToPool.pooledLabelPrefix, StringComparison.Ordinal)) + { + myParser.Error(errCause.Location, "Unpooled data (forgot #pool?)"); + } + else + { + myParser.Error(errCause.Location, "Undefined identifier: " + errCause.Content); + } } /* Last step: assembly */ diff --git a/ColorzCore/Parser/Macros/AddToPool.cs b/ColorzCore/Parser/Macros/AddToPool.cs index 99276cc..7d2a7c0 100644 --- a/ColorzCore/Parser/Macros/AddToPool.cs +++ b/ColorzCore/Parser/Macros/AddToPool.cs @@ -12,6 +12,8 @@ class AddToPool : BuiltInMacro * AddToPool(tokens..., alignment): adds token to pool and make sure pooled tokens are aligned given alignment */ + public static readonly string pooledLabelPrefix = "__POOLED$"; + public EAParser ParentParser { get; private set; } private long poolLabelCounter; @@ -59,7 +61,7 @@ public override bool ValidNumParams(int num) protected string MakePoolLabelName() { // The presence of $ in the label name guarantees that it can't be a user label - return string.Format("__POOLED${0}", poolLabelCounter++); + return string.Format("{0}{1}", pooledLabelPrefix, poolLabelCounter++); } } } From 2fd3e567e3c2d812ec5868cdce01e244fa00302d Mon Sep 17 00:00:00 2001 From: Stan H Date: Fri, 22 Feb 2019 17:06:20 +0100 Subject: [PATCH 7/8] (builtin-macros) fix scope issues with AddToPool/pool --- ColorzCore/ColorzCore.csproj | 1 + ColorzCore/EAInterpreter.cs | 3 +- ColorzCore/Parser/AST/MacroInvocationNode.cs | 10 +++-- ColorzCore/Parser/EAParser.cs | 22 +++++----- ColorzCore/Parser/Macros/AddToPool.cs | 18 ++------- ColorzCore/Parser/Macros/BuiltInMacro.cs | 3 +- ColorzCore/Parser/Macros/IMacro.cs | 5 ++- ColorzCore/Parser/Macros/IsDefined.cs | 3 +- ColorzCore/Parser/Macros/Macro.cs | 5 ++- ColorzCore/Parser/Macros/String.cs | 5 ++- ColorzCore/Parser/Pool.cs | 40 +++++++++++++++++++ .../Directives/DefineDirective.cs | 2 +- .../Preprocessor/Directives/PoolDirective.cs | 8 ++-- 13 files changed, 81 insertions(+), 44 deletions(-) create mode 100644 ColorzCore/Parser/Pool.cs diff --git a/ColorzCore/ColorzCore.csproj b/ColorzCore/ColorzCore.csproj index 8af3f42..89b082d 100644 --- a/ColorzCore/ColorzCore.csproj +++ b/ColorzCore/ColorzCore.csproj @@ -111,6 +111,7 @@ + diff --git a/ColorzCore/EAInterpreter.cs b/ColorzCore/EAInterpreter.cs index 15a6a49..4068e7e 100644 --- a/ColorzCore/EAInterpreter.cs +++ b/ColorzCore/EAInterpreter.cs @@ -3,7 +3,6 @@ using ColorzCore.Lexer; using ColorzCore.Parser; using ColorzCore.Parser.AST; -using ColorzCore.Parser.Macros; using ColorzCore.Raws; using System; using System.Collections.Generic; @@ -101,7 +100,7 @@ public bool Interpret() foreach (Token errCause in undefinedIds) { - if (errCause.Content.StartsWith(AddToPool.pooledLabelPrefix, StringComparison.Ordinal)) + if (errCause.Content.StartsWith(Pool.pooledLabelPrefix, StringComparison.Ordinal)) { myParser.Error(errCause.Location, "Unpooled data (forgot #pool?)"); } diff --git a/ColorzCore/Parser/AST/MacroInvocationNode.cs b/ColorzCore/Parser/AST/MacroInvocationNode.cs index 69b5f6f..b33b996 100644 --- a/ColorzCore/Parser/AST/MacroInvocationNode.cs +++ b/ColorzCore/Parser/AST/MacroInvocationNode.cs @@ -19,15 +19,17 @@ public MacroException(MacroInvocationNode min) } } - private EAParser p; - private Token invokeToken; + private readonly EAParser p; + private readonly Token invokeToken; + private readonly ImmutableStack scope; public IList> Parameters { get; } - public MacroInvocationNode(EAParser p, Token invokeTok, IList> parameters) + public MacroInvocationNode(EAParser p, Token invokeTok, IList> parameters, ImmutableStack scopes) { this.p = p; this.invokeToken = invokeTok; this.Parameters = parameters; + this.scope = scopes; } public ParamType Type => ParamType.MACRO; @@ -52,7 +54,7 @@ public string PrettyPrint() public IEnumerable ExpandMacro() { - return p.Macros.GetMacro(invokeToken.Content, Parameters.Count).ApplyMacro(invokeToken, Parameters); + return p.Macros.GetMacro(invokeToken.Content, Parameters.Count).ApplyMacro(invokeToken, Parameters, scope); } public Either TryEvaluate() diff --git a/ColorzCore/Parser/EAParser.cs b/ColorzCore/Parser/EAParser.cs index d24ec57..80de851 100644 --- a/ColorzCore/Parser/EAParser.cs +++ b/ColorzCore/Parser/EAParser.cs @@ -46,7 +46,7 @@ class EAParser } public ImmutableStack Inclusion { get; set; } - public List> PooledLines { get; private set; } + public Pool Pool { get; private set; } private readonly DirectiveHandler directiveHandler; @@ -82,7 +82,7 @@ public EAParser(Dictionary> raws, Log log, DirectiveHandler d Inclusion = ImmutableStack.Nil; this.directiveHandler = directiveHandler; - PooledLines = new List>(); + Pool = new Pool(); } public bool IsReservedName(string name) @@ -139,7 +139,7 @@ private BlockNode ParseBlock(MergeableGenerator tokens, ImmutableStack ParseStatement(MergeableGenerator tokens, ImmutableStack scopes) { - while (ExpandIdentifier(tokens)) ; + while (ExpandIdentifier(tokens, scopes)) { } head = tokens.Current; tokens.MoveNext(); //TODO: Replace with real raw information, and error if not valid. @@ -383,7 +383,7 @@ private Maybe ParseParam(MergeableGenerator tokens, Immutable return new Just(new StringNode(head)); case TokenType.MAYBE_MACRO: //TODO: Move this and the one in ExpandId to a separate ParseMacroNode that may return an Invocation. - if (expandDefs && ExpandIdentifier(tokens)) + if (expandDefs && ExpandIdentifier(tokens, scopes)) { return ParseParam(tokens, scopes); } @@ -392,10 +392,10 @@ private Maybe ParseParam(MergeableGenerator tokens, Immutable tokens.MoveNext(); IList> param = ParseMacroParamList(tokens); //TODO: Smart errors if trying to redefine a macro with the same num of params. - return new Just(new MacroInvocationNode(this, head, param)); + return new Just(new MacroInvocationNode(this, head, param, scopes)); } case TokenType.IDENTIFIER: - if (expandDefs && Definitions.ContainsKey(head.Content) && ExpandIdentifier(tokens)) + if (expandDefs && Definitions.ContainsKey(head.Content) && ExpandIdentifier(tokens, scopes)) return ParseParam(tokens, scopes, expandDefs); else return ParseAtom(tokens,scopes,expandDefs).Fmap((IAtomNode x) => (IParamNode)x); @@ -527,7 +527,7 @@ private Maybe ParseAtom(MergeableGenerator tokens, ImmutableSt { if (lookAhead.Type == TokenType.IDENTIFIER) { - if (expandDefs && ExpandIdentifier(tokens)) + if (expandDefs && ExpandIdentifier(tokens, scopes)) continue; if (lookAhead.Content.ToUpper() == "CURRENTOFFSET") grammarSymbols.Push(new Left(new NumberNode(lookAhead, CurrentOffset))); @@ -536,7 +536,7 @@ private Maybe ParseAtom(MergeableGenerator tokens, ImmutableSt } else if (lookAhead.Type == TokenType.MAYBE_MACRO) { - ExpandIdentifier(tokens); + ExpandIdentifier(tokens, scopes); continue; } else if (lookAhead.Type == TokenType.NUMBER) @@ -640,7 +640,7 @@ public Maybe ParseLine(MergeableGenerator tokens, ImmutableSta { case TokenType.IDENTIFIER: case TokenType.MAYBE_MACRO: - if (ExpandIdentifier(tokens)) + if (ExpandIdentifier(tokens, scopes)) { return ParseLine(tokens, scopes); } @@ -728,7 +728,7 @@ private Maybe ParsePreprocessor(MergeableGenerator tokens, Imm * Postcondition: tokens.Current is fully reduced (i.e. not a macro, and not a definition) * Returns: true iff tokens was actually expanded. */ - public bool ExpandIdentifier(MergeableGenerator tokens) + public bool ExpandIdentifier(MergeableGenerator tokens, ImmutableStack scopes) { bool ret = false; //Macros and Definitions. @@ -739,7 +739,7 @@ public bool ExpandIdentifier(MergeableGenerator tokens) IList> parameters = ParseMacroParamList(tokens); if (Macros.HasMacro(head.Content, parameters.Count)) { - tokens.PrependEnumerator(Macros.GetMacro(head.Content, parameters.Count).ApplyMacro(head, parameters).GetEnumerator()); + tokens.PrependEnumerator(Macros.GetMacro(head.Content, parameters.Count).ApplyMacro(head, parameters, scopes).GetEnumerator()); } else { diff --git a/ColorzCore/Parser/Macros/AddToPool.cs b/ColorzCore/Parser/Macros/AddToPool.cs index 7d2a7c0..565b265 100644 --- a/ColorzCore/Parser/Macros/AddToPool.cs +++ b/ColorzCore/Parser/Macros/AddToPool.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using ColorzCore.DataTypes; using ColorzCore.Lexer; namespace ColorzCore.Parser.Macros @@ -12,23 +13,18 @@ class AddToPool : BuiltInMacro * AddToPool(tokens..., alignment): adds token to pool and make sure pooled tokens are aligned given alignment */ - public static readonly string pooledLabelPrefix = "__POOLED$"; - public EAParser ParentParser { get; private set; } - private long poolLabelCounter; - public AddToPool(EAParser parent) { ParentParser = parent; - poolLabelCounter = 0; } - public override IEnumerable ApplyMacro(Token head, IList> parameters) + public override IEnumerable ApplyMacro(Token head, IList> parameters, ImmutableStack scopes) { List line = new List(6 + parameters[0].Count); - string labelName = MakePoolLabelName(); + string labelName = ParentParser.Pool.MakePoolLabelName(); if (parameters.Count == 2) { @@ -48,7 +44,7 @@ public override IEnumerable ApplyMacro(Token head, IList> pa line.AddRange(parameters[0]); line.Add(new Token(TokenType.NEWLINE, head.Location, "\n")); - ParentParser.PooledLines.Add(line); + ParentParser.Pool.Lines.Add(new Pool.PooledLine(scopes, line)); yield return new Token(TokenType.IDENTIFIER, head.Location, labelName); } @@ -57,11 +53,5 @@ public override bool ValidNumParams(int num) { return num == 1 || num == 2; } - - protected string MakePoolLabelName() - { - // The presence of $ in the label name guarantees that it can't be a user label - return string.Format("{0}{1}", pooledLabelPrefix, poolLabelCounter++); - } } } diff --git a/ColorzCore/Parser/Macros/BuiltInMacro.cs b/ColorzCore/Parser/Macros/BuiltInMacro.cs index 5e46b91..a38209d 100644 --- a/ColorzCore/Parser/Macros/BuiltInMacro.cs +++ b/ColorzCore/Parser/Macros/BuiltInMacro.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using ColorzCore.DataTypes; using ColorzCore.Lexer; namespace ColorzCore.Parser.Macros @@ -10,6 +11,6 @@ namespace ColorzCore.Parser.Macros abstract class BuiltInMacro : IMacro { public abstract bool ValidNumParams(int num); - public abstract IEnumerable ApplyMacro(Token head, IList> parameters); + public abstract IEnumerable ApplyMacro(Token head, IList> parameters, ImmutableStack scopes); } } diff --git a/ColorzCore/Parser/Macros/IMacro.cs b/ColorzCore/Parser/Macros/IMacro.cs index b8ccf55..0cbd03f 100644 --- a/ColorzCore/Parser/Macros/IMacro.cs +++ b/ColorzCore/Parser/Macros/IMacro.cs @@ -1,4 +1,5 @@ -using ColorzCore.Lexer; +using ColorzCore.DataTypes; +using ColorzCore.Lexer; using System; using System.Collections.Generic; using System.Linq; @@ -9,6 +10,6 @@ namespace ColorzCore.Parser.Macros { public interface IMacro { - IEnumerable ApplyMacro(Token head, IList> parameters); + IEnumerable ApplyMacro(Token head, IList> parameters, ImmutableStack scopes); } } diff --git a/ColorzCore/Parser/Macros/IsDefined.cs b/ColorzCore/Parser/Macros/IsDefined.cs index 3880267..135c840 100644 --- a/ColorzCore/Parser/Macros/IsDefined.cs +++ b/ColorzCore/Parser/Macros/IsDefined.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using ColorzCore.DataTypes; using ColorzCore.Lexer; namespace ColorzCore.Parser.Macros @@ -13,7 +14,7 @@ public IsDefined(EAParser parent) ParentParser = parent; } - public override IEnumerable ApplyMacro(Token head, IList> parameters) + public override IEnumerable ApplyMacro(Token head, IList> parameters, ImmutableStack scopes) { if (parameters[0].Count != 1) { diff --git a/ColorzCore/Parser/Macros/Macro.cs b/ColorzCore/Parser/Macros/Macro.cs index 6eee1c2..78581ae 100644 --- a/ColorzCore/Parser/Macros/Macro.cs +++ b/ColorzCore/Parser/Macros/Macro.cs @@ -1,4 +1,5 @@ -using ColorzCore.Lexer; +using ColorzCore.DataTypes; +using ColorzCore.Lexer; using ColorzCore.Parser.AST; using System; using System.Collections.Generic; @@ -26,7 +27,7 @@ public Macro(IList parameters, IList body) /*** * Precondition: parameters.Count = max(keys(idToParamNum)) */ - public IEnumerable ApplyMacro(Token head, IList> parameters) + public IEnumerable ApplyMacro(Token head, IList> parameters, ImmutableStack scopes) { foreach(Token t in body) { diff --git a/ColorzCore/Parser/Macros/String.cs b/ColorzCore/Parser/Macros/String.cs index 1074a36..4366673 100644 --- a/ColorzCore/Parser/Macros/String.cs +++ b/ColorzCore/Parser/Macros/String.cs @@ -1,4 +1,5 @@ -using ColorzCore.Lexer; +using ColorzCore.DataTypes; +using ColorzCore.Lexer; using System; using System.Collections.Generic; using System.Linq; @@ -9,7 +10,7 @@ namespace ColorzCore.Parser.Macros { class String : BuiltInMacro { - public override IEnumerable ApplyMacro(Token head, IList> parameters) + public override IEnumerable ApplyMacro(Token head, IList> parameters, ImmutableStack scopes) { yield return new Token(TokenType.IDENTIFIER, head.Location, "BYTE"); foreach (byte num in Encoding.ASCII.GetBytes(parameters[0][0].Content.ToCharArray())) //TODO: Errors if not adherent? diff --git a/ColorzCore/Parser/Pool.cs b/ColorzCore/Parser/Pool.cs new file mode 100644 index 0000000..b8b73c5 --- /dev/null +++ b/ColorzCore/Parser/Pool.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using ColorzCore.DataTypes; +using ColorzCore.Lexer; + +namespace ColorzCore.Parser +{ + class Pool + { + public struct PooledLine + { + public ImmutableStack Scope { get; private set; } + public List Tokens { get; private set; } + + public PooledLine(ImmutableStack scope, List tokens) + { + Scope = scope; + Tokens = tokens; + } + } + + public static readonly string pooledLabelPrefix = "__POOLED$"; + + public List Lines { get; private set; } + + private long poolLabelCounter; + + public Pool() + { + Lines = new List(); + poolLabelCounter = 0; + } + + public string MakePoolLabelName() + { + // The presence of $ in the label name guarantees that it can't be a user label + return string.Format("{0}{1}", pooledLabelPrefix, poolLabelCounter++); + } + } +} diff --git a/ColorzCore/Preprocessor/Directives/DefineDirective.cs b/ColorzCore/Preprocessor/Directives/DefineDirective.cs index 2b06626..51e9ebd 100644 --- a/ColorzCore/Preprocessor/Directives/DefineDirective.cs +++ b/ColorzCore/Preprocessor/Directives/DefineDirective.cs @@ -148,7 +148,7 @@ private static IEnumerable ExpandAllIdentifiers(EAParser p, Queue IList> param = p.ParseMacroParamList(new MergeableGenerator(tokens)); //TODO: I don't like wrapping this in a mergeable generator..... Maybe interface the original better? if (!seenMacros.Contains(new Tuple(current.Content, param.Count)) && p.Macros.HasMacro(current.Content, param.Count)) { - foreach(Token t in p.Macros.GetMacro(current.Content, param.Count).ApplyMacro(current, param)) + foreach(Token t in p.Macros.GetMacro(current.Content, param.Count).ApplyMacro(current, param, p.GlobalScope)) { yield return t; } diff --git a/ColorzCore/Preprocessor/Directives/PoolDirective.cs b/ColorzCore/Preprocessor/Directives/PoolDirective.cs index a0f33cd..33d48ab 100644 --- a/ColorzCore/Preprocessor/Directives/PoolDirective.cs +++ b/ColorzCore/Preprocessor/Directives/PoolDirective.cs @@ -17,19 +17,19 @@ public Maybe Execute(EAParser p, Token self, IList parame { BlockNode result = new BlockNode(); - foreach (List line in p.PooledLines) + foreach (Pool.PooledLine line in p.Pool.Lines) { - MergeableGenerator tempGenerator = new MergeableGenerator(line); + MergeableGenerator tempGenerator = new MergeableGenerator(line.Tokens); tempGenerator.MoveNext(); while (!tempGenerator.EOS) { - p.ParseLine(tempGenerator, p.GlobalScope).IfJust( + p.ParseLine(tempGenerator, line.Scope).IfJust( (lineNode) => result.Children.Add(lineNode)); } } - p.PooledLines.Clear(); + p.Pool.Lines.Clear(); return new Just(result); } From 22784a7daa0e5733c40553568ac733eed59aa220 Mon Sep 17 00:00:00 2001 From: Stan H Date: Fri, 22 Feb 2019 17:48:56 +0100 Subject: [PATCH 8/8] (builtin-macros) fix nested AddToPool --- ColorzCore/Preprocessor/Directives/PoolDirective.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ColorzCore/Preprocessor/Directives/PoolDirective.cs b/ColorzCore/Preprocessor/Directives/PoolDirective.cs index 33d48ab..fbd057c 100644 --- a/ColorzCore/Preprocessor/Directives/PoolDirective.cs +++ b/ColorzCore/Preprocessor/Directives/PoolDirective.cs @@ -17,8 +17,13 @@ public Maybe Execute(EAParser p, Token self, IList parame { BlockNode result = new BlockNode(); - foreach (Pool.PooledLine line in p.Pool.Lines) + // Iterating indices (and not values via foreach) + // to avoid crashes occuring with AddToPool within AddToPool + + for (int i = 0; i < p.Pool.Lines.Count; ++i) { + Pool.PooledLine line = p.Pool.Lines[i]; + MergeableGenerator tempGenerator = new MergeableGenerator(line.Tokens); tempGenerator.MoveNext();