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

Add IsDefined builtin and AddToPool/#pool #40

Merged
merged 8 commits into from
Mar 21, 2019
Merged
Show file tree
Hide file tree
Changes from 7 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
6 changes: 5 additions & 1 deletion ColorzCore/ColorzCore.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
Expand Down Expand Up @@ -108,6 +108,10 @@
<Compile Include="Raws\Raw.cs" />
<Compile Include="IO\Log.cs" />
<Compile Include="IO\IncludeFileSearcher.cs" />
<Compile Include="Parser\Macros\IsDefined.cs" />
<Compile Include="Parser\Macros\AddToPool.cs" />
<Compile Include="Preprocessor\Directives\PoolDirective.cs" />
<Compile Include="Parser\Pool.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
Expand Down
9 changes: 8 additions & 1 deletion ColorzCore/EAInterpreter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,14 @@ public bool Interpret()

foreach (Token errCause in undefinedIds)
{
myParser.Error(errCause.Location, "Undefined identifier: " + errCause.Content);
if (errCause.Content.StartsWith(Pool.pooledLabelPrefix, StringComparison.Ordinal))
{
myParser.Error(errCause.Location, "Unpooled data (forgot #pool?)");
}
else
{
myParser.Error(errCause.Location, "Undefined identifier: " + errCause.Content);
}
}

/* Last step: assembly */
Expand Down
10 changes: 6 additions & 4 deletions ColorzCore/Parser/AST/MacroInvocationNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Closure> scope;
public IList<IList<Token>> Parameters { get; }

public MacroInvocationNode(EAParser p, Token invokeTok, IList<IList<Token>> parameters)
public MacroInvocationNode(EAParser p, Token invokeTok, IList<IList<Token>> parameters, ImmutableStack<Closure> scopes)
{
this.p = p;
this.invokeToken = invokeTok;
this.Parameters = parameters;
this.scope = scopes;
}

public ParamType Type => ParamType.MACRO;
Expand All @@ -52,7 +54,7 @@ public string PrettyPrint()

public IEnumerable<Token> 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<int, string> TryEvaluate()
Expand Down
22 changes: 13 additions & 9 deletions ColorzCore/Parser/EAParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class EAParser
}
public ImmutableStack<bool> Inclusion { get; set; }

public Pool Pool { get; private set; }

private readonly DirectiveHandler directiveHandler;

private Stack<Tuple<int, bool>> pastOffsets; // currentOffset, offsetInitialized
Expand Down Expand Up @@ -79,6 +81,8 @@ public EAParser(Dictionary<string, IList<Raw>> raws, Log log, DirectiveHandler d
Definitions = new Dictionary<string, Definition>();
Inclusion = ImmutableStack<bool>.Nil;
this.directiveHandler = directiveHandler;

Pool = new Pool();
}

public bool IsReservedName(string name)
Expand Down Expand Up @@ -135,7 +139,7 @@ private BlockNode ParseBlock(MergeableGenerator<Token> tokens, ImmutableStack<Cl
}
private Maybe<StatementNode> ParseStatement(MergeableGenerator<Token> tokens, ImmutableStack<Closure> scopes)
{
while (ExpandIdentifier(tokens)) ;
while (ExpandIdentifier(tokens, scopes)) { }
head = tokens.Current;
tokens.MoveNext();
//TODO: Replace with real raw information, and error if not valid.
Expand Down Expand Up @@ -379,7 +383,7 @@ private Maybe<IParamNode> ParseParam(MergeableGenerator<Token> tokens, Immutable
return new Just<IParamNode>(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);
}
Expand All @@ -388,10 +392,10 @@ private Maybe<IParamNode> ParseParam(MergeableGenerator<Token> tokens, Immutable
tokens.MoveNext();
IList<IList<Token>> param = ParseMacroParamList(tokens);
//TODO: Smart errors if trying to redefine a macro with the same num of params.
return new Just<IParamNode>(new MacroInvocationNode(this, head, param));
return new Just<IParamNode>(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);
Expand Down Expand Up @@ -523,7 +527,7 @@ private Maybe<IAtomNode> ParseAtom(MergeableGenerator<Token> 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<IAtomNode, Token>(new NumberNode(lookAhead, CurrentOffset)));
Expand All @@ -532,7 +536,7 @@ private Maybe<IAtomNode> ParseAtom(MergeableGenerator<Token> tokens, ImmutableSt
}
else if (lookAhead.Type == TokenType.MAYBE_MACRO)
{
ExpandIdentifier(tokens);
ExpandIdentifier(tokens, scopes);
continue;
}
else if (lookAhead.Type == TokenType.NUMBER)
Expand Down Expand Up @@ -636,7 +640,7 @@ public Maybe<ILineNode> ParseLine(MergeableGenerator<Token> tokens, ImmutableSta
{
case TokenType.IDENTIFIER:
case TokenType.MAYBE_MACRO:
if (ExpandIdentifier(tokens))
if (ExpandIdentifier(tokens, scopes))
{
return ParseLine(tokens, scopes);
}
Expand Down Expand Up @@ -724,7 +728,7 @@ private Maybe<ILineNode> ParsePreprocessor(MergeableGenerator<Token> 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<Token> tokens)
public bool ExpandIdentifier(MergeableGenerator<Token> tokens, ImmutableStack<Closure> scopes)
{
bool ret = false;
//Macros and Definitions.
Expand All @@ -735,7 +739,7 @@ public bool ExpandIdentifier(MergeableGenerator<Token> tokens)
IList<IList<Token>> 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
{
Expand Down
57 changes: 57 additions & 0 deletions ColorzCore/Parser/Macros/AddToPool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using ColorzCore.DataTypes;
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<Token> ApplyMacro(Token head, IList<IList<Token>> parameters, ImmutableStack<Closure> scopes)
{
List<Token> line = new List<Token>(6 + parameters[0].Count);

string labelName = ParentParser.Pool.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.Pool.Lines.Add(new Pool.PooledLine(scopes, line));

yield return new Token(TokenType.IDENTIFIER, head.Location, labelName);
}

public override bool ValidNumParams(int num)
{
return num == 1 || num == 2;
}
}
}
3 changes: 2 additions & 1 deletion ColorzCore/Parser/Macros/BuiltInMacro.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ColorzCore.DataTypes;
using ColorzCore.Lexer;

namespace ColorzCore.Parser.Macros
{
abstract class BuiltInMacro : IMacro
{
public abstract bool ValidNumParams(int num);
public abstract IEnumerable<Token> ApplyMacro(Token head, IList<IList<Token>> parameters);
public abstract IEnumerable<Token> ApplyMacro(Token head, IList<IList<Token>> parameters, ImmutableStack<Closure> scopes);
}
}
5 changes: 3 additions & 2 deletions ColorzCore/Parser/Macros/IMacro.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ColorzCore.Lexer;
using ColorzCore.DataTypes;
using ColorzCore.Lexer;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -9,6 +10,6 @@ namespace ColorzCore.Parser.Macros
{
public interface IMacro
{
IEnumerable<Token> ApplyMacro(Token head, IList<IList<Token>> parameters);
IEnumerable<Token> ApplyMacro(Token head, IList<IList<Token>> parameters, ImmutableStack<Closure> scopes);
}
}
59 changes: 59 additions & 0 deletions ColorzCore/Parser/Macros/IsDefined.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using ColorzCore.DataTypes;
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<Token> ApplyMacro(Token head, IList<IList<Token>> parameters, ImmutableStack<Closure> scopes)
{
if (parameters[0].Count != 1)
{
// TODO: err somehow
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably do some param checking in the invocation of built in macros akin to how it is for preproc defs.

(you don't need to address this comment if you don't want to; I intend to)

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);
Crazycolorz5 marked this conversation as resolved.
Show resolved Hide resolved
}

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");
}
}
}
5 changes: 3 additions & 2 deletions ColorzCore/Parser/Macros/Macro.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ColorzCore.Lexer;
using ColorzCore.DataTypes;
using ColorzCore.Lexer;
using ColorzCore.Parser.AST;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -26,7 +27,7 @@ public Macro(IList<Token> parameters, IList<Token> body)
/***
* Precondition: parameters.Count = max(keys(idToParamNum))
*/
public IEnumerable<Token> ApplyMacro(Token head, IList<IList<Token>> parameters)
public IEnumerable<Token> ApplyMacro(Token head, IList<IList<Token>> parameters, ImmutableStack<Closure> scopes)
{
foreach(Token t in body)
{
Expand Down
7 changes: 6 additions & 1 deletion ColorzCore/Parser/Macros/MacroCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ public MacroCollection(EAParser parent)
{
Macros = new Dictionary<string, Dictionary<int, IMacro>>();
Parent = parent;
BuiltInMacros = new Dictionary<string, BuiltInMacro> { { "String", String.Instance } };

BuiltInMacros = new Dictionary<string, BuiltInMacro> {
{ "String", new String() },
{ "IsDefined", new IsDefined(parent) },
{ "AddToPool", new AddToPool(parent) },
};
}

public bool HasMacro(string name, int paramNum)
Expand Down
11 changes: 3 additions & 8 deletions ColorzCore/Parser/Macros/String.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ColorzCore.Lexer;
using ColorzCore.DataTypes;
using ColorzCore.Lexer;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -9,13 +10,7 @@ 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<Token> ApplyMacro(Token head, IList<IList<Token>> parameters)
public override IEnumerable<Token> ApplyMacro(Token head, IList<IList<Token>> parameters, ImmutableStack<Closure> 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?
Expand Down
40 changes: 40 additions & 0 deletions ColorzCore/Parser/Pool.cs
Original file line number Diff line number Diff line change
@@ -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<Closure> Scope { get; private set; }
public List<Token> Tokens { get; private set; }

public PooledLine(ImmutableStack<Closure> scope, List<Token> tokens)
{
Scope = scope;
Tokens = tokens;
}
}

public static readonly string pooledLabelPrefix = "__POOLED$";

public List<PooledLine> Lines { get; private set; }

private long poolLabelCounter;

public Pool()
{
Lines = new List<PooledLine>();
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++);
}
}
}
Loading