private void ResolveConstantReferences(StyleCompileContext context) { foreach (StyleConstant constant in context.constantsWithReferences.Values) { Resolve(context, constant); } }
private StyleConstant ResolveReference(StyleCompileContext context, ConstReferenceNode constReference) { if (currentlyResolvingConstants.Contains(constReference.identifier)) { throw new CompileException(constReference, "Circular dependency detected!"); } for (int i = 0; i < context.constants.Count; i++) { StyleConstant constant = context.constants[i]; if (constant.name == constReference.identifier) { // reference resolved return(constant); } } // now we have to recursively resolve the reference of the reference: // const x: string = @y; // we're here... // const y: string = @z: // ....referencing this // const z: string = "whatup"; // ...which will resolve to this. if (context.constantsWithReferences.ContainsKey(constReference.identifier)) { currentlyResolvingConstants.Add(constReference.identifier); StyleConstant resolvedConstant = Resolve(context, context.constantsWithReferences[constReference.identifier]); currentlyResolvingConstants.Remove(constReference.identifier); return(resolvedConstant); } throw new CompileException(constReference, $"Could not resolve reference {constReference}. Known references are: " + context.PrintConstants()); }
public StyleCompileContext CreateContext(LightList <StyleASTNode> rootNodes, MaterialDatabase materialDatabase) { StyleCompileContext context = new StyleCompileContext(materialDatabase); // first all imports must be collected as they can be referenced in exports and consts for (int i = 0; i < rootNodes.size; i++) { switch (rootNodes[i]) { case ImportNode importNode: StyleSheet importedStyle = styleSheetImporter.ImportStyleSheetFromFile(importNode.source, materialDatabase); LightList <StyleConstant> importedStyleConstants = new LightList <StyleConstant>(importedStyle.constants.Length); for (int constantIndex = 0; constantIndex < importedStyle.constants.Length; constantIndex++) { StyleConstant importedStyleConstant = importedStyle.constants[constantIndex]; if (importedStyleConstant.exported) { importedStyleConstants.Add(importedStyleConstant); } } context.importedStyleConstants.Add(importNode.alias, importedStyleConstants); break; } } // collect all constants that could be referenced for (int index = 0; index < rootNodes.size; index++) { switch (rootNodes[index]) { case ExportNode exportNode: TransformConstNode(context, exportNode.constNode, true); break; case ConstNode constNode: TransformConstNode(context, constNode, false); break; } } ResolveConstantReferences(context); context.constantsWithReferences.Clear(); return(context); }
private StyleConstant Resolve(StyleCompileContext context, StyleConstant constant) { // shortcut return for constants that have been resolved already for (int index = 0; index < context.constants.Count; index++) { StyleConstant c = context.constants[index]; if (c.name == constant.name) { return(c); } } StyleConstant referencedConstant; if (constant.constReferenceNode.children.Count > 0) { if (context.importedStyleConstants.ContainsKey(constant.constReferenceNode.identifier)) { DotAccessNode importedConstant = (DotAccessNode)constant.constReferenceNode.children[0]; referencedConstant = context.importedStyleConstants[constant.constReferenceNode.identifier] .Find(importedConstant.propertyName, s_FindStyleConstant); if (referencedConstant.name == null) { throw new CompileException(importedConstant, "Could not find referenced property in imported scope."); } } else { throw new CompileException(constant.constReferenceNode, "Constants cannot reference members of other constants."); } } else { referencedConstant = ResolveReference(context, constant.constReferenceNode); } StyleConstant styleConstant = new StyleConstant { name = constant.name, value = referencedConstant.value, exported = constant.exported }; context.constants.Add(styleConstant); return(styleConstant); }
private void TransformConstNode(StyleCompileContext context, ConstNode constNode, bool exported) { if (constNode.value is ConstReferenceNode) { context.constantsWithReferences.Add(constNode.constName, new StyleConstant { name = constNode.constName, constReferenceNode = (ConstReferenceNode)constNode.value, exported = exported }); } else { context.constants.Add(new StyleConstant { name = constNode.constName, value = constNode.value, exported = exported }); } }
// public StyleSheet Compile(string filePath, string contents) { // return Compile(filePath, StyleParser.Parse(contents)); // } // todo -- deprecate, use other method public StyleSheet Compile(string filePath, LightList <StyleASTNode> rootNodes, MaterialDatabase materialDatabase = default) { try { context = new StyleSheetConstantImporter(styleSheetImporter).CreateContext(rootNodes, materialDatabase); context.resourceManager = resourceManager; // context = new StyleCompileContext(); // todo resolve constants. should be done a per file level, should store all used constants without needing to later reference other files // StyleCompileContext.Create(styleSheetImporter) //new StyleSheetConstantImporter(styleSheetImporter).CreateContext(rootNodes); } catch (CompileException e) { e.SetFileName(filePath); throw; } context.fileName = filePath; // todo add imported style groups rootNodes.Sort((node1, node2) => { int left = (int)node1.type; int right = (int)node2.type; return(left - right); }); int containerCount = 0; int animationCount = 0; int soundCount = 0; for (int index = 0; index < rootNodes.Count; index++) { switch (rootNodes[index]) { case StyleRootNode _: containerCount++; break; case AnimationRootNode _: case SpriteSheetNode _: animationCount++; break; case SoundRootNode _: soundCount++; break; } } StyleSheet styleSheet = new StyleSheet( styleSheetImporter.ImportedStyleSheetCount, context.constants?.ToArray(), containerCount > 0 ? new UIStyleGroupContainer[containerCount] : ArrayPool <UIStyleGroupContainer> .Empty, animationCount > 0 ? new AnimationData[animationCount] : ArrayPool <AnimationData> .Empty, soundCount > 0 ? new UISoundData[soundCount] : ArrayPool <UISoundData> .Empty ); int containerIndex = 0; int animationIndex = 0; int soundIndex = 0; for (int index = 0; index < rootNodes.Count; index++) { switch (rootNodes[index]) { // we sorted the root nodes so all animations run first case SpriteSheetNode spriteSheetNode: styleSheet.animations[animationIndex] = CompileSpriteSheetAnimation(spriteSheetNode, styleSheet.animations, styleSheet.sounds); animationIndex++; break; case AnimationRootNode animNode: styleSheet.animations[animationIndex] = CompileAnimation(animNode, styleSheet.animations, styleSheet.sounds); animationIndex++; break; case SoundRootNode soundRootNode: styleSheet.sounds[soundIndex] = CompileSound(soundRootNode); soundIndex++; break; case StyleRootNode styleRoot: styleSheet.styleGroupContainers[containerIndex] = CompileStyleGroup(styleRoot, styleSheet.animations, styleSheet.sounds); styleSheet.styleGroupContainers[containerIndex].styleSheet = styleSheet; containerIndex++; break; } } context.Release(); return(styleSheet); }