public void CatchesSimpleImportCollision() { var fileSystem = new InMemoryFileProvider(); fileSystem.RegisterFileWithIdentifier("root.lsystem", @" #axiom Y #iterations 1000 #symbols XY #include lib0.lsyslib (Exported->X) #include lib1.lsyslib (Exported->X) "); fileSystem.RegisterFileWithIdentifier("lib0.lsyslib", @" #symbols AB #export Exported A "); fileSystem.RegisterFileWithIdentifier("lib1.lsyslib", @" #symbols CD #export Exported C "); var linker = new FileLinker(fileSystem); try { linker.LinkFiles("root.lsystem"); } catch (LinkException e) { Assert.AreEqual(LinkExceptionType.IMPORT_COLLISION, e.exceptionType); return; } Assert.Fail("linker must prevent importing symbols in such a way that it attempts to represent multiple symbols with the same character"); }
public void CatchesMissingExport() { var fileSystem = new InMemoryFileProvider(); fileSystem.RegisterFileWithIdentifier("root.lsystem", @" #axiom Y #iterations 1000 #symbols XYZ #include lib0.lsyslib (NotExported->X) "); fileSystem.RegisterFileWithIdentifier("lib0.lsyslib", @" #symbols AB #export Exported A "); var linker = new FileLinker(fileSystem); try { linker.LinkFiles("root.lsystem"); } catch (LinkException e) { Assert.AreEqual(LinkExceptionType.MISSING_EXPORT, e.exceptionType); return; } Assert.Fail("linker must prevent importing symbols which are not exported"); }
public void CatchesRunTimeVariableCollision() { var fileSystem = new InMemoryFileProvider(); fileSystem.RegisterFileWithIdentifier("root.lsystem", @" #axiom Y #iterations 1000 #symbols XY #runtime runTime 1992.01 #include lib0.lsyslib "); fileSystem.RegisterFileWithIdentifier("lib0.lsyslib", @" #symbols AB #runtime runTime 1992.01 #export Exported A "); var linker = new FileLinker(fileSystem); try { linker.LinkFiles("root.lsystem"); } catch (LinkException e) { Assert.AreEqual(LinkExceptionType.GLOBAL_VARIABLE_COLLISION, e.exceptionType); return; } Assert.Fail("linker must prevent declaration of multiple global runtime variables with the same name"); }
public void CatchesMissingInclude() { var fileSystem = new InMemoryFileProvider(); fileSystem.RegisterFileWithIdentifier("root.lsystem", @" #axiom Y #iterations 1000 #symbols XYZ #include missinglib.lsyslib "); fileSystem.RegisterFileWithIdentifier("lib0.lsyslib", @" #symbols AB "); var linker = new FileLinker(fileSystem); try { linker.LinkFiles("root.lsystem"); } catch (LinkException e) { Assert.AreEqual(LinkExceptionType.MISSING_FILE, e.exceptionType); return; } Assert.Fail("linker must gracefully fail when it cannot find a file"); }
public void AllowsImportCollisionToPreventDissonance() { var fileSystem = new InMemoryFileProvider(); fileSystem.RegisterFileWithIdentifier("root.lsystem", @" #axiom Y #iterations 1000 #symbols XY #include lib0.lsyslib (Exported->X) #include lib1.lsyslib (Exported->X) "); fileSystem.RegisterFileWithIdentifier("lib0.lsyslib", @" #symbols AB #include lib2.lsyslib (Exported->A) #export Exported A "); fileSystem.RegisterFileWithIdentifier("lib1.lsyslib", @" #symbols CD #include lib2.lsyslib (Exported->C) #export Exported C "); fileSystem.RegisterFileWithIdentifier("lib2.lsyslib", @" #symbols EF #export Exported E "); var linker = new FileLinker(fileSystem); var linkedSet = linker.LinkFiles("root.lsystem"); var rootFile = linkedSet.allFiles.data[linkedSet.fileIndexesByFullIdentifier["root.lsystem"]]; Assert.AreEqual(4, rootFile.allSymbolAssignments.Count); Assert.AreEqual(4, rootFile.allSymbolAssignments.Select(x => x.sourceCharacter).Intersect("XY[]").Count()); var lib0File = linkedSet.allFiles.data[linkedSet.fileIndexesByFullIdentifier["lib0.lsyslib"]]; Assert.AreEqual(4, lib0File.allSymbolAssignments.Count); Assert.AreEqual(4, lib0File.allSymbolAssignments.Select(x => x.sourceCharacter).Intersect("AB[]").Count()); var lib1File = linkedSet.allFiles.data[linkedSet.fileIndexesByFullIdentifier["lib1.lsyslib"]]; Assert.AreEqual(4, lib1File.allSymbolAssignments.Count); Assert.AreEqual(4, lib1File.allSymbolAssignments.Select(x => x.sourceCharacter).Intersect("CD[]").Count()); var lib2File = linkedSet.allFiles.data[linkedSet.fileIndexesByFullIdentifier["lib2.lsyslib"]]; Assert.AreEqual(4, lib2File.allSymbolAssignments.Count); Assert.AreEqual(4, lib2File.allSymbolAssignments.Select(x => x.sourceCharacter).Intersect("EF[]").Count()); var importedInRoot = rootFile.GetSymbolInFile('X'); var exportedInLib0 = lib0File.GetSymbolInFile('A'); var exportedInLib1 = lib1File.GetSymbolInFile('C'); var exportedInLib2 = lib2File.GetSymbolInFile('E'); Assert.AreEqual(exportedInLib2, exportedInLib1); Assert.AreEqual(exportedInLib2, exportedInLib0); Assert.AreEqual(exportedInLib2, importedInRoot); }
public void LinksSimpleDependencyAndExecutes() { var fileSystem = new InMemoryFileProvider(); fileSystem.RegisterFileWithIdentifier("root.lsystem", @" #axiom Y #iterations 10 #symbols XY #include lib.lsyslib (Exported->X) Y -> YX "); fileSystem.RegisterFileWithIdentifier("lib.lsyslib", @" #symbols AB #export Exported B B -> AB "); var linker = new FileLinker(fileSystem); var linkedFiles = linker.LinkFiles("root.lsystem"); using var system = linkedFiles.CompileSystem(); LSystemState <float> currentState = new DefaultLSystemState( linkedFiles.GetAxiom(), (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue)); var X = linkedFiles.GetSymbol("root.lsystem", 'X'); var Y = linkedFiles.GetSymbol("root.lsystem", 'Y'); var A = linkedFiles.GetSymbol("lib.lsyslib", 'A'); var B = linkedFiles.GetSymbol("lib.lsyslib", 'B'); Assert.AreEqual(B, X); var symbolStringMapping = new Dictionary <int, char>() { { X, 'X' }, { Y, 'Y' }, { A, 'A' } }; /** * system equivalent with remapped symbol names: * Y -> YX * X -> AX */ Assert.AreEqual("Y", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("YX", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("YXAX", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("YXAXAAX", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("YXAXAAXAAAX", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState.currentSymbols.DisposeImmediate(); }
public void LinksBuiltinLibraryAndExecutes() { var builtins = new BuiltinLibraries(); builtins.Add(new DiffusionLibrary()); var fileSystem = new InMemoryFileProvider(builtins); fileSystem.RegisterFileWithIdentifier("root.lsystem", @" #axiom n(0.5, 0, 10)ST(3) #iterations 10 #symbols naFTS #include diffusion (Node->n) (Amount->a) T(x) : x > 0 -> n(.5, 0, 10)FT(x - 1) S -> a(3)S "); var linker = new FileLinker(fileSystem); var linkedFiles = linker.LinkFiles("root.lsystem"); using var system = linkedFiles.CompileSystem(); LSystemState <float> currentState = new DefaultLSystemState( linkedFiles.GetAxiom(), (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue)); var n = linkedFiles.GetSymbol("root.lsystem", 'n'); var a = linkedFiles.GetSymbol("root.lsystem", 'a'); var F = linkedFiles.GetSymbol("root.lsystem", 'F'); var T = linkedFiles.GetSymbol("root.lsystem", 'T'); var S = linkedFiles.GetSymbol("root.lsystem", 'S'); var symbolStringMapping = new Dictionary <int, char>() { { n, 'n' }, { a, 'a' }, { F, 'F' }, { T, 'T' }, { S, 'S' }, }; Assert.AreEqual("n(0.5, 0, 10)ST(3)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("n(0.5, 0, 10)a(3)Sn(0.5, 0, 10)FT(2)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("n(0.5, 1.5, 10)aa(3)Sn(0.5, 1.5, 10)Fn(0.5, 0, 10)FT(1)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("n(0.5, 3, 10)aa(3)Sn(0.5, 2.25, 10)Fn(0.5, 0.75, 10)Fn(0.5, 0, 10)FT(0)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("n(0.5, 4.125, 10)aa(3)Sn(0.5, 3.375, 10)Fn(0.5, 1.125, 10)Fn(0.5, 0.375, 10)FT(0)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("n(0.5, 5.25, 10)aa(3)Sn(0.5, 4.125, 10)Fn(0.5, 1.875, 10)Fn(0.5, 0.75, 10)FT(0)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("n(0.5, 6.1875, 10)aa(3)Sn(0.5, 5.0625, 10)Fn(0.5, 2.4375, 10)Fn(0.5, 1.3125, 10)FT(0)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState.currentSymbols.DisposeImmediate(); }
public void LinksBuiltinLibraryWithCustomParameterAndExecutes() { var builtins = new BuiltinLibraries(); builtins.Add(new DiffusionLibrary()); var fileSystem = new InMemoryFileProvider(builtins); fileSystem.RegisterFileWithIdentifier("root.lsystem", @" #axiom n(0.25, 18, 20)Fn(0.25, 0, 20)Fn(0.25, 0, 20) #iterations 10 #symbols naF #define diffusionStepsPerStep 2 #include diffusion (Node->n) (Amount->a) "); var linker = new FileLinker(fileSystem); var linkedFiles = linker.LinkFiles("root.lsystem"); using var system = linkedFiles.CompileSystem(); LSystemState <float> currentState = new DefaultLSystemState( linkedFiles.GetAxiom(), (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue)); var n = linkedFiles.GetSymbol("root.lsystem", 'n'); var a = linkedFiles.GetSymbol("root.lsystem", 'a'); var F = linkedFiles.GetSymbol("root.lsystem", 'F'); var symbolStringMapping = new Dictionary <int, char>() { { n, 'n' }, { a, 'a' }, { F, 'F' }, }; Assert.AreEqual("n(0.25, 18, 20)Fn(0.25, 0, 20)Fn(0.25, 0, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("n(0.25, 11.25, 20)Fn(0.25, 5.625, 20)Fn(0.25, 1.125, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("n(0.25, 8.859375, 20)Fn(0.25, 5.976563, 20)Fn(0.25, 3.164063, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("n(0.25, 7.602539, 20)Fn(0.25, 5.998535, 20)Fn(0.25, 4.398926, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("n(0.25, 6.901062, 20)Fn(0.25, 5.999908, 20)Fn(0.25, 5.09903, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("n(0.25, 6.506824, 20)Fn(0.25, 5.999994, 20)Fn(0.25, 5.493181, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("n(0.25, 6.285088, 20)Fn(0.25, 6, 20)Fn(0.25, 5.714913, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("n(0.25, 6.160362, 20)Fn(0.25, 6, 20)Fn(0.25, 5.839638, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("n(0.25, 6.090203, 20)Fn(0.25, 6, 20)Fn(0.25, 5.909797, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState.currentSymbols.DisposeImmediate(); }
public void CompilesWithImmaturityMarkers() { var fileSystem = new InMemoryFileProvider(); fileSystem.RegisterFileWithIdentifier("root.lsystem", @" #axiom Y(2) #iterations 20 #symbols XY #immature Y Y(x) : x > 0 -> Y(x - 1) Y(x) : x <= 0 -> X "); var linker = new FileLinker(fileSystem); var linkedFiles = linker.LinkFiles("root.lsystem"); using var system = linkedFiles.CompileSystem(); LSystemState <float> currentState = new DefaultLSystemState( linkedFiles.GetAxiom(), (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue)); var X = linkedFiles.GetSymbol("root.lsystem", 'X'); var Y = linkedFiles.GetSymbol("root.lsystem", 'Y'); var symbolStringMapping = new Dictionary <int, char>() { { X, 'X' }, { Y, 'Y' } }; /** * system equivalent with remapped symbol names: * Y -> YX * X -> AX */ Assert.AreEqual("Y(2)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("Y(1)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); Assert.IsTrue(currentState.hasImmatureSymbols); currentState = system.StepSystem(currentState); Assert.AreEqual("Y(0)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); Assert.IsTrue(currentState.hasImmatureSymbols); currentState = system.StepSystem(currentState); Assert.AreEqual("X", currentState.currentSymbols.Data.ToString(symbolStringMapping)); Assert.IsFalse(currentState.hasImmatureSymbols); currentState = system.StepSystem(currentState); Assert.AreEqual("X", currentState.currentSymbols.Data.ToString(symbolStringMapping)); Assert.IsFalse(currentState.hasImmatureSymbols); currentState.currentSymbols.DisposeImmediate(); }
public void LoadFromFilePath(string filePath) { if (!string.IsNullOrWhiteSpace(filePath)) { var linker = new FileLinker(new FileSystemFileProvider()); linkedFiles = linker.LinkFiles(filePath); // compile the system right away and throw it out to catch any compile-time errors this.CompileToCached(); compiledSystem?.Dispose(); compiledSystem = null; } }
public void LinkCompilesBranchingSymbolWithContextMatches() { var fileSystem = new InMemoryFileProvider(); fileSystem.RegisterFileWithIdentifier("root.lsystem", @" #axiom AF[FB] #iterations 10 #symbols FAB #matches AB #symbols CD #matches CD A > [B] -> C A < B -> D "); var linker = new FileLinker(fileSystem); var linkedFiles = linker.LinkFiles("root.lsystem"); using var system = linkedFiles.CompileSystem(); LSystemState <float> currentState = new DefaultLSystemState( linkedFiles.GetAxiom(), (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue)); var lBracket = linkedFiles.GetSymbol("root.lsystem", '['); var rBracket = linkedFiles.GetSymbol("root.lsystem", ']'); var FRoot = linkedFiles.GetSymbol("root.lsystem", 'F'); var ARoot = linkedFiles.GetSymbol("root.lsystem", 'A'); var BRoot = linkedFiles.GetSymbol("root.lsystem", 'B'); var CRoot = linkedFiles.GetSymbol("root.lsystem", 'C'); var DRoot = linkedFiles.GetSymbol("root.lsystem", 'D'); var symbolStringMapping = new Dictionary <int, char>() { { lBracket, '[' }, { rBracket, ']' }, { FRoot, 'F' }, { ARoot, 'A' }, { BRoot, 'B' }, { CRoot, 'C' }, { DRoot, 'D' } }; Assert.AreEqual("AF[FB]", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("CF[FD]", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState.currentSymbols.DisposeImmediate(); }
public void TestLSystemFile( string fileText, IEnumerable <string> expectedSteps) { var fileSystem = new InMemoryFileProvider(); fileSystem.RegisterFileWithIdentifier("root.lsystem", fileText); var linker = new FileLinker(fileSystem); var linkedFiles = linker.LinkFiles("root.lsystem"); using var system = linkedFiles.CompileSystem(); LSystemState <float> state = new DefaultLSystemState( linkedFiles.GetAxiom(), (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue)); var symbolStringMapping = linkedFiles.allSymbolDefinitionsLeafFirst .Where(x => x.sourceFileDefinition == "root.lsystem") .ToDictionary(x => x.actualSymbol, x => x.characterInSourceFile); using var axiom = linkedFiles.GetAxiom(); Assert.AreEqual(axiom.ToString(symbolStringMapping), state.currentSymbols.Data.ToString(symbolStringMapping)); try { foreach (var expectedStep in expectedSteps) { state = system.StepSystem(state); Assert.AreEqual(expectedStep, state.currentSymbols.Data.ToString(symbolStringMapping)); } } catch (System.Exception e) { UnityEngine.Debug.LogException(e); UnityEngine.Debug.Log("actual result:"); state.currentSymbols.DisposeImmediate(); state = new DefaultLSystemState( linkedFiles.GetAxiom(), (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue)); for (int i = 0; i < expectedSteps.Count(); i++) { state = system.StepSystem(state); UnityEngine.Debug.Log(state.currentSymbols.Data.ToString(symbolStringMapping)); } throw; } finally { state.currentSymbols.DisposeImmediate(); } }
public void DiffusionRateCanChangeAtRuntime() { var testFile = @" #axiom n(0.5, 0, 10)Fn(0.5, 0, 10)Fn(0.5, 8, 10) #iterations 10 #symbols Fna #define diffusionStepsPerStep 1 #include diffusion (Node->n) (Amount->a) "; var fileSystem = new InMemoryFileProvider(); fileSystem.RegisterFileWithIdentifier("root.lsystem", testFile); var linker = new FileLinker(fileSystem); var linkedFiles = linker.LinkFiles("root.lsystem"); using var system = linkedFiles.CompileSystem(); LSystemState <float> state = new DefaultLSystemState( linkedFiles.GetAxiom(), (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue)); var symbolStringMapping = linkedFiles.allSymbolDefinitionsLeafFirst .Where(x => x.sourceFileDefinition == "root.lsystem") .ToDictionary(x => x.actualSymbol, x => x.characterInSourceFile); using var axiom = linkedFiles.GetAxiom(); Assert.AreEqual(axiom.ToString(symbolStringMapping), state.currentSymbols.Data.ToString(symbolStringMapping)); try { state = system.StepSystem(state); Assert.AreEqual("n(0.5, 0, 10)Fn(0.5, 4, 10)Fn(0.5, 4, 10)", state.currentSymbols.Data.ToString(symbolStringMapping)); system.customSymbols.diffusionConstantRuntimeGlobalMultiplier = 0.5f; state = system.StepSystem(state); Assert.AreEqual("n(0.5, 1, 10)Fn(0.5, 3, 10)Fn(0.5, 4, 10)", state.currentSymbols.Data.ToString(symbolStringMapping)); state = system.StepSystem(state); Assert.AreEqual("n(0.5, 1.5, 10)Fn(0.5, 2.75, 10)Fn(0.5, 3.75, 10)", state.currentSymbols.Data.ToString(symbolStringMapping)); system.customSymbols.diffusionConstantRuntimeGlobalMultiplier = 1f; state = system.StepSystem(state); Assert.AreEqual("n(0.5, 2.125, 10)Fn(0.5, 2.625, 10)Fn(0.5, 3.25, 10)", state.currentSymbols.Data.ToString(symbolStringMapping)); } finally { state.currentSymbols.DisposeImmediate(); } }
public void LinksSimpleDependencyAndAssociatesGlobals() { var fileSystem = new InMemoryFileProvider(); fileSystem.RegisterFileWithIdentifier("root.lsystem", @" #axiom Y #iterations 1000 #symbols XYZDE #global DE #include lib.lsyslib (Exported->X) Y -> ZX "); fileSystem.RegisterFileWithIdentifier("lib.lsyslib", @" #symbols ABDE #export Exported B #global D B -> AB "); var linker = new FileLinker(fileSystem); var linkedSet = linker.LinkFiles("root.lsystem"); var rootFile = linkedSet.allFiles.data[linkedSet.fileIndexesByFullIdentifier["root.lsystem"]]; Assert.AreEqual(7, rootFile.allSymbolAssignments.Count); Assert.AreEqual(7, rootFile.allSymbolAssignments.Select(x => x.sourceCharacter).Intersect("XYZDE[]").Count()); var libFile = linkedSet.allFiles.data[linkedSet.fileIndexesByFullIdentifier["lib.lsyslib"]]; Assert.AreEqual(6, libFile.allSymbolAssignments.Count); Assert.AreEqual(6, libFile.allSymbolAssignments.Select(x => x.sourceCharacter).Intersect("ABDE[]").Count()); var importedInRoot = rootFile.GetSymbolInFile('X'); var exportedInLib = libFile.GetSymbolInFile('B'); Assert.AreEqual(exportedInLib, importedInRoot); Assert.AreEqual(rootFile.GetSymbolInFile('D'), libFile.GetSymbolInFile('D')); Assert.AreNotEqual(rootFile.GetSymbolInFile('E'), libFile.GetSymbolInFile('E')); Assert.AreEqual(rootFile.GetSymbolInFile('['), libFile.GetSymbolInFile('[')); Assert.AreEqual(rootFile.GetSymbolInFile(']'), libFile.GetSymbolInFile(']')); }
public void CatchesLibraryAsOriginError() { var fileSystem = new InMemoryFileProvider(); fileSystem.RegisterFileWithIdentifier("root.lsyslib", @" #symbols AB #export Exported A "); var linker = new FileLinker(fileSystem); try { linker.LinkFiles("root.lsyslib"); } catch (LinkException e) { Assert.AreEqual(LinkExceptionType.BASE_FILE_IS_LIBRARY, e.exceptionType); return; } Assert.Fail("linker must not allow the root file to be a library file"); }
public void CatchesSimpleCycle() { var fileSystem = new InMemoryFileProvider(); fileSystem.RegisterFileWithIdentifier("root.lsystem", @" #axiom Y #iterations 1000 #symbols XYZ #include lib0.lsyslib (Exported->X) "); fileSystem.RegisterFileWithIdentifier("lib0.lsyslib", @" #symbols AB #include lib1.lsyslib (Exported->B) #export Exported A "); fileSystem.RegisterFileWithIdentifier("lib1.lsyslib", @" #symbols CD #include lib2.lsyslib (Exported->D) #export Exported C ");; fileSystem.RegisterFileWithIdentifier("lib2.lsyslib", @" #symbols EF #include lib0.lsyslib (Exported->F) #export Exported E "); var linker = new FileLinker(fileSystem); try { linker.LinkFiles("root.lsystem"); } catch (LinkException e) { Assert.AreEqual(LinkExceptionType.CYCLIC_DEPENDENCY, e.exceptionType); return; } Assert.Fail("linker must prevent cyclic dependencies"); }
public void CatchesSimpleImportDissonance() { var fileSystem = new InMemoryFileProvider(); fileSystem.RegisterFileWithIdentifier("root.lsystem", @" #axiom Y #iterations 1000 #symbols XY #include lib0.lsyslib (Exported->X) #include lib1.lsyslib (Exported->Y) "); fileSystem.RegisterFileWithIdentifier("lib0.lsyslib", @" #symbols AB #include lib2.lsyslib (Exported->A) #export Exported A "); fileSystem.RegisterFileWithIdentifier("lib1.lsyslib", @" #symbols CD #include lib2.lsyslib (Exported->C) #export Exported C "); fileSystem.RegisterFileWithIdentifier("lib2.lsyslib", @" #symbols EF #export Exported E "); var linker = new FileLinker(fileSystem); try { linker.LinkFiles("root.lsystem"); } catch (LinkException e) { Assert.AreEqual(LinkExceptionType.IMPORT_DISSONANCE, e.exceptionType); return; } Assert.Fail("linker must prevent importing symbols in such a way that would cause a single symbol to be represented as multiple character"); }
public void LinksDependencyWithoutRemapping() { var fileSystem = new InMemoryFileProvider(); fileSystem.RegisterFileWithIdentifier("root.lsystem", @" #axiom Y #iterations 1000 #symbols XYZ #include lib.lsyslib Y -> ZX "); fileSystem.RegisterFileWithIdentifier("lib.lsyslib", @" #symbols AB #export Exported B B -> AB "); var linker = new FileLinker(fileSystem); var linkedSet = linker.LinkFiles("root.lsystem"); var rootFile = linkedSet.allFiles.data[linkedSet.fileIndexesByFullIdentifier["root.lsystem"]]; Assert.AreEqual(5, rootFile.allSymbolAssignments.Count); Assert.AreEqual(5, rootFile.allSymbolAssignments.Select(x => x.sourceCharacter).Intersect("XYZ[]").Count()); var libFile = linkedSet.allFiles.data[linkedSet.fileIndexesByFullIdentifier["lib.lsyslib"]]; Assert.AreEqual(4, libFile.allSymbolAssignments.Count); Assert.AreEqual(4, libFile.allSymbolAssignments.Select(x => x.sourceCharacter).Intersect("AB[]").Count()); var exportedInLib = libFile.GetSymbolInFile('B'); Assert.IsFalse(rootFile.allSymbolAssignments.Any(x => x.remappedSymbol == exportedInLib)); }
public void LinksDependencyWithContextualMatchesAndIgnoresNonImportedSymbols() { var fileSystem = new InMemoryFileProvider(); fileSystem.RegisterFileWithIdentifier("root.lsystem", @" #axiom Y(0)A(3) #iterations 10 #symbols XYA #matches XYA #include nodes.lsyslib (Node->X) (Root->Y) A(x) : x > 0 -> I(2)[X(x)]A(x - 1) A(x) : x <= 0 -> J #symbols IFJ #matches IJ I(x) : x > 0 -> I(x - 1)F J -> I(x) > J -> JI(x) "); fileSystem.RegisterFileWithIdentifier("nodes.lsyslib", @" #symbols AB #matches AB #export Node B #export Root A A(y) < B(x) : x > 0 -> B(x - 1) A(x) > [B(y)] : y > 0 -> A(x + 1) A(x) > [B(y)][B(z)] : y > 0 && z > 0 -> A(x + 2) A(x) > [B(y)][B(z)][B(a)] : y > 0 && z > 0 && a > 0 -> A(x + 3) A(x) > [B(y)][B(z)][B(a)][B(b)] : y > 0 && z > 0 && a > 0 && b > 0 -> A(x + 4) "); var linker = new FileLinker(fileSystem); var linkedFiles = linker.LinkFiles("root.lsystem"); using var system = linkedFiles.CompileSystem(); LSystemState <float> currentState = new DefaultLSystemState( linkedFiles.GetAxiom(), (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue)); var lBracket = linkedFiles.GetSymbol("root.lsystem", '['); var rBracket = linkedFiles.GetSymbol("root.lsystem", ']'); var XRoot = linkedFiles.GetSymbol("root.lsystem", 'X'); var YRoot = linkedFiles.GetSymbol("root.lsystem", 'Y'); var ARoot = linkedFiles.GetSymbol("root.lsystem", 'A'); var IRoot = linkedFiles.GetSymbol("root.lsystem", 'I'); var FRoot = linkedFiles.GetSymbol("root.lsystem", 'F'); var JRoot = linkedFiles.GetSymbol("root.lsystem", 'J'); var Alib = linkedFiles.GetSymbol("nodes.lsyslib", 'A'); var Blib = linkedFiles.GetSymbol("nodes.lsyslib", 'B'); Assert.AreEqual(Alib, YRoot); Assert.AreEqual(Blib, XRoot); var symbolStringMapping = new Dictionary <int, char>() { { lBracket, '[' }, { rBracket, ']' }, { XRoot, 'X' }, { YRoot, 'Y' }, { ARoot, 'A' }, { IRoot, 'I' }, { FRoot, 'F' }, { JRoot, 'J' } }; Assert.AreEqual("Y(0)A(3)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("Y(0)I(2)[X(3)]A(2)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("Y(1)I(1)F[X(2)]I(2)[X(2)]A(1)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("Y(3)I(0)FF[X(1)]I(1)F[X(1)]I(2)[X(1)]A(0)", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("Y(6)I(0)FF[X(0)]I(0)FF[X(0)]I(1)F[X(0)]J", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("Y(6)I(0)FF[X(0)]I(0)FF[X(0)]JI(1)F[X(0)]", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("Y(6)I(0)FF[X(0)]JI(0)FF[X(0)]I(0)FF[X(0)]", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("Y(6)JI(0)FF[X(0)]I(0)FF[X(0)]I(0)FF[X(0)]", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState = system.StepSystem(currentState); Assert.AreEqual("Y(6)I(0)FF[X(0)]I(0)FF[X(0)]I(0)FF[X(0)]", currentState.currentSymbols.Data.ToString(symbolStringMapping)); currentState.currentSymbols.DisposeImmediate(); }