From fd051dd2c258b4272c54179abd635bcf88997802 Mon Sep 17 00:00:00 2001 From: Martin Evans Date: Thu, 6 May 2021 14:13:58 +0100 Subject: [PATCH] Improved yasm in response to feedback from Azurethi (working on ISAN). - Added comments - Better error messages - Error out when too many substitutions are made (instead of freezing forever) - Added braces which get removed from compiled output --- YololAssembler/Grammar/AST/BaseDefine.cs | 20 +++- YololAssembler/Grammar/AST/Comment.cs | 13 ++ YololAssembler/Grammar/AST/EvalReplacement.cs | 2 +- YololAssembler/Grammar/AST/FunctionDefine.cs | 3 +- YololAssembler/Grammar/AST/Other.cs | 15 ++- YololAssembler/Grammar/AST/Program.cs | 41 +++---- .../Grammar/Errors/BaseCompileException.cs | 5 + .../Grammar/Errors/CannotParseEval.cs | 2 +- .../Grammar/Errors/CannotParseImport.cs | 2 +- .../Grammar/Errors/CannotResolveImport.cs | 4 +- YololAssembler/Grammar/Errors/EvalNotConst.cs | 2 +- .../Grammar/Errors/TooManySubstitutions.cs | 11 ++ YololAssembler/Grammar/YololAssembler.pegasus | 9 +- YololAssembler/Program.cs | 27 ++--- YololAssembler/Properties/launchSettings.json | 2 +- YololAssembler/Scripts/binary_add.yasm | 58 +++++++++ YololAssembler/Scripts/binary_add.yolol | 6 + YololAssembler/Scripts/lib.yasm | 2 +- YololAssembler/YololAssembler.csproj | 2 +- YololAssembler/readme.md | 113 +++++++++++++----- YololEmulator.Tests/Ladder/BinaryAddition.cs | 43 +++++++ .../Ladder/SimpleNavigationPositioning.cs | 65 ++++++++++ YololEmulator/YololEmulator.csproj | 2 +- 23 files changed, 356 insertions(+), 93 deletions(-) create mode 100644 YololAssembler/Grammar/AST/Comment.cs create mode 100644 YololAssembler/Grammar/Errors/TooManySubstitutions.cs create mode 100644 YololAssembler/Scripts/binary_add.yasm create mode 100644 YololAssembler/Scripts/binary_add.yolol create mode 100644 YololEmulator.Tests/Ladder/BinaryAddition.cs create mode 100644 YololEmulator.Tests/Ladder/SimpleNavigationPositioning.cs diff --git a/YololAssembler/Grammar/AST/BaseDefine.cs b/YololAssembler/Grammar/AST/BaseDefine.cs index 32165da..4c825c6 100644 --- a/YololAssembler/Grammar/AST/BaseDefine.cs +++ b/YololAssembler/Grammar/AST/BaseDefine.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Text.RegularExpressions; +using YololAssembler.Grammar.Errors; namespace YololAssembler.Grammar.AST { @@ -15,9 +16,9 @@ public string Apply(string input) var r = Replace(match.Groups["body"].Value); r = Other.Trim(r); - var v = input.Substring(0, match.Index) + var v = input[..match.Index] + r - + input.Substring(0 + match.Index + match.Length); + + input[(0 + match.Index + match.Length)..]; return v; } @@ -31,8 +32,11 @@ public string Apply(string input) /// /// /// - internal static string Apply(string block, IEnumerable defines) + internal static string Apply(string block, IReadOnlyList defines) { + var original = block; + var matches = 0; + var changed = true; while (changed) { @@ -41,8 +45,16 @@ internal static string Apply(string block, IEnumerable defines) { var input = block; block = item.Apply(input); - changed |= !block.Equals(input); + + if (!block.Equals(input)) + { + changed = true; + matches++; + } } + + if (matches >= 100) + throw new TooManySubstitutions(original, block, matches); } return block; diff --git a/YololAssembler/Grammar/AST/Comment.cs b/YololAssembler/Grammar/AST/Comment.cs new file mode 100644 index 0000000..43429d3 --- /dev/null +++ b/YololAssembler/Grammar/AST/Comment.cs @@ -0,0 +1,13 @@ +namespace YololAssembler.Grammar.AST +{ + internal class Comment + : BaseStatement + { + public string Value { get; } + + public Comment(string value) + { + Value = value; + } + } +} diff --git a/YololAssembler/Grammar/AST/EvalReplacement.cs b/YololAssembler/Grammar/AST/EvalReplacement.cs index 65b534e..e0f0aa7 100644 --- a/YololAssembler/Grammar/AST/EvalReplacement.cs +++ b/YololAssembler/Grammar/AST/EvalReplacement.cs @@ -12,7 +12,7 @@ internal class EvalReplacement protected override string Replace(string part) { // Convert the floating expression into a statement assigning a variable; - const string name = "_95efe616"; + const string name = "eval"; var stmtCode = $"{name}={part}"; // Try to parse this tiny little program diff --git a/YololAssembler/Grammar/AST/FunctionDefine.cs b/YololAssembler/Grammar/AST/FunctionDefine.cs index 983a3ab..f0d72ff 100644 --- a/YololAssembler/Grammar/AST/FunctionDefine.cs +++ b/YololAssembler/Grammar/AST/FunctionDefine.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using YololAssembler.Grammar.Errors; diff --git a/YololAssembler/Grammar/AST/Other.cs b/YololAssembler/Grammar/AST/Other.cs index f9d5d49..d786118 100644 --- a/YololAssembler/Grammar/AST/Other.cs +++ b/YololAssembler/Grammar/AST/Other.cs @@ -11,17 +11,30 @@ internal class Other public Other(string content) { Content = content; + + // Find comments and trim them out + var idx = Content.IndexOf("##", StringComparison.OrdinalIgnoreCase); + if (idx != -1) + { + // Remove the comment + Content = Content.Substring(0, idx); + + // If there was space trailing the line leading up to the comment, remove it + Content = Content.TrimEnd(' '); + } } internal static string Trim(string input) { - return string.Join("", + var trimmed = string.Join("", input .Split(new[] {"\r\n", "\r", "\n"}, StringSplitOptions.RemoveEmptyEntries) .Select(l => l.TrimStart(' ')) .Select(l => l.TrimStart('\t')) .Select(l => l.Replace(";", " ")) ); + + return trimmed; } } } diff --git a/YololAssembler/Grammar/AST/Program.cs b/YololAssembler/Grammar/AST/Program.cs index 000f6c3..ff13b83 100644 --- a/YololAssembler/Grammar/AST/Program.cs +++ b/YololAssembler/Grammar/AST/Program.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Net; using YololAssembler.Grammar.Errors; -using Result = Yolol.Grammar.Parser.Result; namespace YololAssembler.Grammar.AST { @@ -17,32 +16,25 @@ public Program(IEnumerable statements) Statements = statements.ToArray(); } - public Result Compile(bool compress = true) + public string Compile() { // Apply replacements to all blocks of `Other` - var lines = Apply(Defines().ToArray(), Others().ToArray()).ToArray(); + var lines = Apply(Defines(), Others().ToArray()).ToArray(); // Replace line labels - lines = Apply(Labels().ToArray(), lines.ToArray()).ToArray(); + lines = Apply(Labels(), lines.ToArray()).ToArray(); // Replace implicit line labels lines = ApplyImplicitLabels(lines).ToArray(); + // Remove all of the {} characters now that substitutions are done + lines = lines.Select(l => l.Replace("{", "").Replace("}", "")).ToArray(); + // Run all `eval` replacements lines = Apply(new[] { new EvalReplacement() }, lines).ToArray(); - // Early out if compression should not be applied - var yolol = string.Join("\n", lines); - if (!compress) - return new Result(yolol); - - // Parse as yolol to apply compression - var parsedYolol = Yolol.Grammar.Parser.ParseProgram(yolol); - if (!parsedYolol.IsOk) - return new Result(parsedYolol.Err); - - // remove unnecessary spaces from the program - return new Result(Compress(parsedYolol.Ok)); + // Return compiled program + return string.Join("\n", lines); } private static IEnumerable ApplyImplicitLabels(IEnumerable lines) @@ -55,27 +47,22 @@ private static IEnumerable ApplyImplicitLabels(IEnumerable lines } } - private static string Compress(Yolol.Grammar.AST.Program yolol) - { - //todo: compress - return yolol.ToString(); - } - private static IEnumerable Apply(IReadOnlyList defines, IReadOnlyList blocks) { foreach (var block in blocks) yield return BaseDefine.Apply(block, defines); } - private IEnumerable Labels() + private IReadOnlyList Labels() { return Statements .OfType() .Select((s, i) => (s.Name, (i + 1).ToString())) - .Select(a => new FindAndReplace(a.Name, a.Item2)); + .Select(a => new FindAndReplace(a.Name, a.Item2)) + .ToArray(); } - private IEnumerable Defines() + private IReadOnlyList Defines() { // Find all things defined in this file var defines = Statements.OfType(); @@ -83,10 +70,10 @@ private IEnumerable Defines() // Resolve imports var imports = Statements.OfType().SelectMany(Resolve); - return defines.Concat(imports); + return defines.Concat(imports).ToArray(); } - private static IEnumerable Resolve(Import import) + private static IReadOnlyList Resolve(Import import) { string Fetch() { diff --git a/YololAssembler/Grammar/Errors/BaseCompileException.cs b/YololAssembler/Grammar/Errors/BaseCompileException.cs index 434f926..6bdb5e1 100644 --- a/YololAssembler/Grammar/Errors/BaseCompileException.cs +++ b/YololAssembler/Grammar/Errors/BaseCompileException.cs @@ -9,5 +9,10 @@ public BaseCompileException(string message) : base(message) { } + + public override string ToString() + { + return Message; + } } } diff --git a/YololAssembler/Grammar/Errors/CannotParseEval.cs b/YololAssembler/Grammar/Errors/CannotParseEval.cs index f341bd6..8aa4785 100644 --- a/YololAssembler/Grammar/Errors/CannotParseEval.cs +++ b/YololAssembler/Grammar/Errors/CannotParseEval.cs @@ -7,7 +7,7 @@ public class CannotParseEval public Yolol.Grammar.Parser.ParseError ParseError { get; } public CannotParseEval(string expression, Yolol.Grammar.Parser.ParseError parseError) - : base($"Cannot parse expression pass to eval `{expression}`.") + : base($"Cannot parse expression as Yolol in `Eval({expression})`.\n\n{parseError}") { Expression = expression; ParseError = parseError; diff --git a/YololAssembler/Grammar/Errors/CannotParseImport.cs b/YololAssembler/Grammar/Errors/CannotParseImport.cs index 1fb215a..15066b8 100644 --- a/YololAssembler/Grammar/Errors/CannotParseImport.cs +++ b/YololAssembler/Grammar/Errors/CannotParseImport.cs @@ -7,7 +7,7 @@ public class CannotParseImport public Yolol.Grammar.Parser.ParseError ParseError { get; } public CannotParseImport(string path, Yolol.Grammar.Parser.ParseError parseError) - : base($"Cannot parse file import from `{path}`.") + : base($"Cannot parse file import from `{path}` as YASM.") { Path = path; ParseError = parseError; diff --git a/YololAssembler/Grammar/Errors/CannotResolveImport.cs b/YololAssembler/Grammar/Errors/CannotResolveImport.cs index 6d6fe7e..2ec93f0 100644 --- a/YololAssembler/Grammar/Errors/CannotResolveImport.cs +++ b/YololAssembler/Grammar/Errors/CannotResolveImport.cs @@ -3,8 +3,8 @@ public class CannotResolveImport : BaseCompileException { - public CannotResolveImport(string message) - : base($"Cannot interpret imported path `{message}` as a file path or a Uri") + public CannotResolveImport(string path) + : base($"Cannot interpret imported path `{path}` as a file path or a Uri") { } } diff --git a/YololAssembler/Grammar/Errors/EvalNotConst.cs b/YololAssembler/Grammar/Errors/EvalNotConst.cs index 9322f41..b072787 100644 --- a/YololAssembler/Grammar/Errors/EvalNotConst.cs +++ b/YololAssembler/Grammar/Errors/EvalNotConst.cs @@ -6,7 +6,7 @@ public class EvalNotConst public Yolol.Grammar.AST.Expressions.BaseExpression Expression { get; } public EvalNotConst(Yolol.Grammar.AST.Expressions.BaseExpression expression) - : base($"Expression pass to eval is not constant `{expression}`.") + : base($"Attempted to evaluate a non-constant expression: `Eval({expression})`") { Expression = expression; } diff --git a/YololAssembler/Grammar/Errors/TooManySubstitutions.cs b/YololAssembler/Grammar/Errors/TooManySubstitutions.cs new file mode 100644 index 0000000..7b1ae2c --- /dev/null +++ b/YololAssembler/Grammar/Errors/TooManySubstitutions.cs @@ -0,0 +1,11 @@ +namespace YololAssembler.Grammar.Errors +{ + public class TooManySubstitutions + : BaseCompileException + { + internal TooManySubstitutions(string original, string result, int matches) + : base($"Too many substitutions made while processing input:\n\n\t`{original}`\n\nResult after {matches} substitutions:\n\n\t`{result}`") + { + } + } +} diff --git a/YololAssembler/Grammar/YololAssembler.pegasus b/YololAssembler/Grammar/YololAssembler.pegasus index d8cd014..d4eb1bb 100644 --- a/YololAssembler/Grammar/YololAssembler.pegasus +++ b/YololAssembler/Grammar/YololAssembler.pegasus @@ -13,15 +13,20 @@ program statement = line_label + / line_nolabel / define / import + / comment / other line_label = "@" i:identifier ":" { new LineLabel(i) } -//comment -// = "#" c:(!newline .)* { new Comment(string.Concat(c)) } +line_nolabel + = "@:" { new LineLabel(Guid.NewGuid().ToString()) } + +comment + = _ "##" c:(!newline .)* { new Comment(string.Concat(c)) } import = "#import" _ p:(!newline .)* { new Import(string.Concat(p)) } diff --git a/YololAssembler/Program.cs b/YololAssembler/Program.cs index 4dbec30..586ab1f 100644 --- a/YololAssembler/Program.cs +++ b/YololAssembler/Program.cs @@ -20,9 +20,6 @@ private class Options [Option('w', "watch", HelpText = "If set, the assembler will automatically run every time the input file changes", Required = false)] public bool Watch { get; set; } - - [Option('c', "compress", HelpText = "If set, the assembler will automatically compress the output code", Required = false)] - public bool Compress { get; set; } // ReSharper restore UnusedAutoPropertyAccessor.Local } @@ -36,7 +33,7 @@ private static void Run(Options options) var input = options.InputFile!; var output = options.OutputFile!; - ProcessFile(options.InputFile!, options.OutputFile!, options.Compress); + ProcessFile(options.InputFile!, options.OutputFile!); if (options.Watch) { @@ -52,7 +49,7 @@ private static void Run(Options options) void OnChanged(object sender, FileSystemEventArgs fileSystemEventArgs) { Thread.Sleep(100); - ProcessFile(input, output, options.Compress); + ProcessFile(input, output); } // Add event handlers. @@ -68,12 +65,12 @@ void OnChanged(object sender, FileSystemEventArgs fileSystemEventArgs) while (Console.ReadKey(true).Key != ConsoleKey.Q && File.Exists(options.InputFile)) { Thread.Sleep(100); - ProcessFile(input, output, options.Compress); + ProcessFile(input, output); } } } - private static void ProcessFile(string inputPath, string outputPath, bool compress) + private static void ProcessFile(string inputPath, string outputPath) { var timer = new Stopwatch(); timer.Start(); @@ -89,22 +86,13 @@ private static void ProcessFile(string inputPath, string outputPath, bool compre var parseResult = Grammar.Parser.ParseProgram(File.ReadAllText(inputPath)); if (!parseResult.IsOk) { - Console.WriteLine("# yasm parse error"); + Console.WriteLine("# Yasm Parse Error"); Console.WriteLine("------------------"); Console.WriteLine(parseResult.Err.ToString()); break; } - var compileResult = parseResult.Ok.Compile(compress); - if (!compileResult.IsOk) - { - Console.WriteLine("# yolol parse error"); - Console.WriteLine("-------------------"); - Console.WriteLine(compileResult.Err.ToString()); - break; - } - - var yolol = compileResult.Ok; + var yolol = parseResult.Ok.Compile(); yolol += "\n\n"; yolol += "// <-------------- this line is 70 characters long ------------------>"; @@ -117,7 +105,10 @@ private static void ProcessFile(string inputPath, string outputPath, bool compre } catch (BaseCompileException e) { + Console.WriteLine("# YASM Compiler Error"); + Console.WriteLine("---------------------"); Console.WriteLine(e); + Console.WriteLine(); break; } } diff --git a/YololAssembler/Properties/launchSettings.json b/YololAssembler/Properties/launchSettings.json index 4729e27..e64b663 100644 --- a/YololAssembler/Properties/launchSettings.json +++ b/YololAssembler/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "YololAssembler": { "commandName": "Project", - "commandLineArgs": "-i Persistence.yasm -o Persistence.yolol --watch", + "commandLineArgs": "-i IsanDemo/isan.yasm -o IsanDemo/isan.yolol --watch", "workingDirectory": "C:\\Users\\Martin\\Documents\\dotnet\\YololEmulator\\YololAssembler\\Scripts" } } diff --git a/YololAssembler/Scripts/binary_add.yasm b/YololAssembler/Scripts/binary_add.yasm new file mode 100644 index 0000000..36e86b2 --- /dev/null +++ b/YololAssembler/Scripts/binary_add.yasm @@ -0,0 +1,58 @@ +#import lib.yasm + +#define carry c + +#define l_bit d +#define r_bit e + +#define init_one_bit() { + l_bit=pop_char(:a); + r_bit=pop_char(:b) + + :o=(l_bit!=r_bit)+"" + carry=l_bit+r_bit>10 +} + +#define add_one_bit() { + l_bit=pop_char(:a); + r_bit=pop_char(:b) + + :o=(l_bit!=r_bit!=carry)+:o; + carry=l_bit+r_bit+carry-0>10 +} + +@init: + init_one_bit() + +@loop: + add_one_bit() + + :done=:a<0 + gotoloop-:done + + + + +@end1: + +@end2: + +a b c | s c +0 0 0 | 0 0 +0 1 0 | 1 0 +1 0 0 | 1 0 +1 1 0 | 0 1 +0 0 1 | 1 0 +0 1 1 | 0 1 +1 0 1 | 0 1 +1 1 1 | 1 1 + +s = a xor b xor c +c = a and b or c and (a xor b) + +and(d) = sum>1 +or(e) = sum>0 +xor(a,b) = a!=b + +s=a!=b!=c +c=a and b or c and (a or b) \ No newline at end of file diff --git a/YololAssembler/Scripts/binary_add.yolol b/YololAssembler/Scripts/binary_add.yolol new file mode 100644 index 0000000..ec0cb30 --- /dev/null +++ b/YololAssembler/Scripts/binary_add.yolol @@ -0,0 +1,6 @@ +d=:a---:a e=:b---:b:o=(d!=e)+""c=d+e>10 +d=:a---:a e=:b---:b:o=(d!=e!=c)+:o c=d+e+c-0>10:done=:a<0goto2-:done + +a b c | s c0 0 0 | 0 00 1 0 | 1 01 0 0 | 1 01 1 0 | 0 10 0 1 | 1 00 1 1 | 0 11 0 1 | 0 11 1 1 | 1 1s = a xor b xor cc = a and b or c and (a xor b)and(d) = sum>1or(e) = sum>0xor(a,b) = a!=bs=a!=b!=cc=a and b or c and (a or b) + +// <-------------- this line is 70 characters long ------------------> \ No newline at end of file diff --git a/YololAssembler/Scripts/lib.yasm b/YololAssembler/Scripts/lib.yasm index 7e30b64..2564e4f 100644 --- a/YololAssembler/Scripts/lib.yasm +++ b/YololAssembler/Scripts/lib.yasm @@ -1,4 +1,4 @@ -#define undefined _ +#define undefined u #define err_if_not(expr) undefined/=expr #define continue_if(expr) undefined/=expr diff --git a/YololAssembler/YololAssembler.csproj b/YololAssembler/YololAssembler.csproj index 14a01c4..a9d6bad 100644 --- a/YololAssembler/YololAssembler.csproj +++ b/YololAssembler/YololAssembler.csproj @@ -7,7 +7,7 @@ YololAssembler.Program Martin Evans Cylon - 2.0.0 + 3.0.0 diff --git a/YololAssembler/readme.md b/YololAssembler/readme.md index ebc724f..4f4d2d9 100644 --- a/YololAssembler/readme.md +++ b/YololAssembler/readme.md @@ -22,49 +22,42 @@ YASM is a macro language - the compiler simply substitutes blocks of text in pla There are example scripts [here](Scripts). These scripts have been written as competition entries for the `Referee` Yolol code golf challenges where every space and every tick is important for scoring so they are written to be as compact as possible! +## Comments + +A Comment is started with the `##` character, all text after the comment marker will be completely removed from the compiled output. All of the whitespace before the comment marker will also be removed. + +```yasm +a=1 ## All of this text is a comment +``` + ## Line Labels YASM code is written line-by-line and there is no automatic rearranging of code from one line to another, this leaves exact control of code flow and timing in the hands of the programmer. All yasm code must be defined within a line label block, any code outside of a block is ignored. A new line is defined with the `@` sigil before the name of the line: ```yasm -@setup: // define a line called `setup` - a=1 // Put some code into this line +@setup: ## define a line called `setup` + a=1 ## Put some code into this line -@loop: // define a line called `loop` - a++ // Put some code on this line +@loop: ## define a line called `loop` + a++ ## Put some code on this line if a>100 then - goto exit // `exit` is a macro that is replaced with the correct line number + goto exit ## `exit` is a macro that is replaced with the correct line number end - goto @ // `@` is a macro that is replaced with the current line number + goto @ ## `@` is a macro that is replaced with the current line number @exit: :done=1 ``` -## Spaces - -Control over the layout of code is extremely important for compact Yolol programs. Spaces and tabs at the _start_ of the line are stripped to allow for indentation, but all other spaces and tabs are preserved so that the compiled Yolol can be spaced out as necessary. +A line label can be blank, this can be useful for lines which you never need to jump to (such as one off setup) or for lines which simply jump to themselves. ```yasm -@test: - a=1 //<-- there is a space there - b=2 -``` - -```yolol -a=1 b=2 -``` - -While you _can_ use invisible spaces at the end of your lines of code it's not advisable! YASM replaces semicolons (`;`) with an empty space so that code can be properly spaced out. - -```yasm -@test: - a=1; - b=2 -``` - -```yolol -a=1 b=2 +@: + a=1 + +@: + a++ + goto @ ``` ## Defines @@ -99,7 +92,6 @@ function-like macros can have a body containing multiple lines of code by enclos longfunc(a, b, c) // Compiles to "a+=b a/=c" ``` - ## Imports A YASM program can import other YASM files, this allows libraries of re-usable code to be written and imported into multiple projects. There is a standard library of generic macros available [here](Scripts/lib.yasm) (lib.yasm). When a file is imported everything defined in the file is available for use in the file it was imported into. @@ -109,4 +101,67 @@ A YASM program can import other YASM files, this allows libraries of re-usable c @line1: continue_if(1==2) // Use a macro defined in lib.yasm +``` + +## Spaces + +Control over the layout of code is extremely important for compact Yolol programs. Spaces and tabs at the _start_ of the line are stripped to allow for indentation, but all (see comment section below for the one exception) other spaces and tabs are preserved so that the compiled Yolol can be spaced out as necessary. + +```yasm +@test: + a=1 + ## The previous line ends with a space, but you can't see it! + b=2 +``` + +Compiles to: + +```yolol +a=1 b=2 +``` + +While you _can_ use invisible spaces at the end of your lines of code it's not advisable! YASM replaces semicolons (`;`) with an empty space so that code can be properly spaced out. + +```yasm +@test: + a=1; + b=2 +``` + +```yolol +a=1 b=2 +``` + +## Braces + +Because control over spacing is extremely important for Yolol sometimes YASM code needs to be written without spaces, which looks ugly: + +``` +@line10: + gotolinelabel6 +``` + +Braces `{` and `}` are removed from the compiled output of the program. This allows you to separate blocks of code. + +``` +@line10: + goto{linelabel6} +``` + +Braces are removed from the output _after_ macros are substituted, this can also be used to disambiguate macro uses. For example if you have three macros `foo`, `bar` and `foobar` defined, the following code is ambiguous: + +``` +#define foo 1 +#define bar 2 +#define foobar 3 + +@: + x=foobar +``` + +This could match `foo` and `bar`, or it could match `foobar`. To fix this: + +``` +@: + x={foo}{bar} ``` \ No newline at end of file diff --git a/YololEmulator.Tests/Ladder/BinaryAddition.cs b/YololEmulator.Tests/Ladder/BinaryAddition.cs new file mode 100644 index 0000000..87fc581 --- /dev/null +++ b/YololEmulator.Tests/Ladder/BinaryAddition.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Yolol.Execution; + +namespace YololEmulator.Tests.Ladder +{ + [TestClass] + public class BinaryAddition + : BaseGenerator + { + [TestMethod] + public void GenerateBinaryAddition() + { + Run(568456, 3000, true, Generator.ScoreMode.BasicScoring); + } + + string B(uint value) + { + return Convert.ToString(value, 2).PadLeft(32, '0'); + } + + protected override bool GenerateCase(Random random, int index, Dictionary inputs, Dictionary outputs) + { + var a = (uint)random.Next(); + var b = (uint)random.Next(); + + var bina = B(a); + var binb = B(b); + + inputs.Add("a", bina); + inputs.Add("b", binb); + + checked + { + var sum = B(a + b); + outputs.Add("o", sum); + } + + return true; + } + } +} diff --git a/YololEmulator.Tests/Ladder/SimpleNavigationPositioning.cs b/YololEmulator.Tests/Ladder/SimpleNavigationPositioning.cs new file mode 100644 index 0000000..07c8f12 --- /dev/null +++ b/YololEmulator.Tests/Ladder/SimpleNavigationPositioning.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Yolol.Execution; + +namespace YololEmulator.Tests.Ladder +{ + [TestClass] + public class SimpleNavigationPositioning + { + [TestMethod] + public void GenerateSimpleNavigationPositioning() + { + var input = new List>(); + var output = new List>(); + + var beacons = new[] { + (28315.983, 14274.694, 92145.269), + (19522.454, 53912.719, 24633.070), + (05817.744, 97945.275, 82659.224), + (82188.145, 28074.805, 33777.522), + }; + + Number Distance((double x, double y, double z) beacon, Number x, Number y, Number z) + { + var dx = beacon.x - (double)x; + var dy = beacon.y - (double)y; + var dz = beacon.z - (double)z; + + var d = Math.Sqrt(dx * dx + dy * dy + dz * dz); + + return (Number)d; + } + + void SingleCase(Number x, Number y, Number z) + { + output.Add(new Dictionary { + { "x", x }, + { "y", y }, + { "z", z }, + }); + + input.Add(new Dictionary { + { "d0", Distance(beacons[0], x, y, z) }, + { "d1", Distance(beacons[1], x, y, z) }, + { "d2", Distance(beacons[2], x, y, z) }, + { "d3", Distance(beacons[3], x, y, z) }, + }); + } + + var rng = new Random(5873); + + for (var i = 1; i < 25000; i++) + { + SingleCase( + ((Number)(rng.NextDouble() * 50000 + 25000)), + ((Number)(rng.NextDouble() * 50000 + 25000)), + ((Number)(rng.NextDouble() * 50000 + 25000)) + ); + } + + Generator.YololLadderGenerator(input, output, true, Generator.ScoreMode.Approximate); + } + } +} \ No newline at end of file diff --git a/YololEmulator/YololEmulator.csproj b/YololEmulator/YololEmulator.csproj index bc5f1d3..482fd75 100644 --- a/YololEmulator/YololEmulator.csproj +++ b/YololEmulator/YololEmulator.csproj @@ -7,7 +7,7 @@ 8.0 enable AnyCPU;x64 - 9.0.0 + 10.0.0