예제 #1
0
        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());
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        /// <summary>
        /// Returns a referenced StyleASTNode if the passed in node is a ReferenceNode.
        /// Only called once all references have been resolved in the constants list.
        /// </summary>
        /// <param name="node">A node that can be a ReferenceNode or something else.</param>
        /// <returns>The referenced node or the node itself if it's a regular one.</returns>
        /// <exception cref="CompileException">thrown in case a reference cannot be resolved.</exception>
        public StyleASTNode GetValueForReference(StyleASTNode node)
        {
            if (node is ConstReferenceNode referenceNode)
            {
                for (int index = 0; index < constants.Count; index++)
                {
                    StyleConstant c = constants[index];
                    if (c.name == referenceNode.identifier)
                    {
                        return(c.value);
                    }
                }

                if (referenceNode.children.Count > 0)
                {
                    if (importedStyleConstants.ContainsKey(referenceNode.identifier))
                    {
                        DotAccessNode importedConstant = (DotAccessNode)referenceNode.children[0];

                        StyleConstant importedStyleConstant = importedStyleConstants[referenceNode.identifier]
                                                              .Find(importedConstant.propertyName, s_FindStyleConstant);

                        if (importedStyleConstant.name == null)
                        {
                            throw new CompileException(importedConstant, $"Could not find referenced property '{importedConstant.propertyName}' in imported scope '{referenceNode.identifier}'.");
                        }

                        return(importedStyleConstant.value);
                    }

                    throw new CompileException(referenceNode, "Constants cannot reference members of other constants.");
                }


                throw new CompileException(referenceNode, $"Couldn't resolve reference {referenceNode}. Known references are: {PrintConstants()}");
            }

            return(node);
        }