Пример #1
0
        internal async Task <LocalizedAssemblyView> GetCoreLibrary(ParserContext parser)
        {
            ExternalAssemblyMetadata coreLib = await this.GetAssemblyMetadataFromAnyPossibleKey("en", "Core");

            string name = coreLib.GetName(parser.CurrentLocale);

            return(await this.GetOrImportAssembly(parser, null, name));
        }
Пример #2
0
 public void RegisterDependencies(ExternalAssemblyMetadata assembly)
 {
     if (this.directDependencies == null)
     {
         this.directDependencies = new Dictionary <string, ExternalAssemblyMetadata>();
     }
     this.directDependencies[assembly.ID] = assembly;
 }
Пример #3
0
 public CompilationScope(
     ParserContext context,
     ExternalAssemblyMetadata metadata,
     Locale locale,
     ProgrammingLanguage programmingLanguage)
 {
     this.Locale = locale;
     this.ProgrammingLanguage = programmingLanguage;
     this.ScopeNumId          = context.ScopeIdAlloc++;
     this.Metadata            = metadata;
     this.ScopeKey            = this.Metadata.CanonicalKey;
 }
Пример #4
0
        public bool IsAllowedImport(ExternalAssemblyMetadata fromAssembly)
        {
            if (this.IsImportRestricted)
            {
                // Non-empty list means it must be only accessible from a specific library and not top-level user code.
                if (fromAssembly.IsUserDefined)
                {
                    return(false);
                }

                // Is the current library on the list?
                return(this.OnlyImportableFrom.Contains(fromAssembly.ID));
            }
            return(true);
        }
Пример #5
0
        private static void LibraryDepTreeFlattenerRecursive(
            Dictionary <string, ExternalAssemblyMetadata> libsOut,
            ExternalAssemblyMetadata current)
        {
            string id = current.ID;

            if (!libsOut.ContainsKey(id))
            {
                libsOut[id] = current;
                foreach (ExternalAssemblyMetadata dep in current.DirectDependencies)
                {
                    LibraryDepTreeFlattenerRecursive(libsOut, dep);
                }
            }
        }
Пример #6
0
        private static ExternalAssemblyMetadata CreateRootAssembly(Locale locale)
        {
            ExternalAssemblyMetadata m = new ExternalAssemblyMetadata();

            m.ID               = ".";
            m.InternalLocale   = locale;
            m.CanonicalKey     = ".";
            m.SupportedLocales = new HashSet <Locale>()
            {
                locale
            };
            m.OnlyImportableFrom = new HashSet <string>();
            m.IsUserDefined      = true;
            return(m);
        }
Пример #7
0
        private static void LibraryUsagePostOrderTraversal(
            ExternalAssemblyMetadata libraryToUse,
            List <ExternalAssemblyMetadata> libraryOrderOut,
            HashSet <ExternalAssemblyMetadata> usedLibraries,
            HashSet <ExternalAssemblyMetadata> cycleCheck,
            Stack <ExternalAssemblyMetadata> breadcrumbs)
        {
            if (usedLibraries.Contains(libraryToUse))
            {
                return;
            }

            breadcrumbs.Push(libraryToUse);

            if (cycleCheck.Contains(libraryToUse))
            {
                System.Text.StringBuilder message = new System.Text.StringBuilder();
                message.Append("There is a dependency cycle in your libraries: ");
                bool first = true;
                foreach (ExternalAssemblyMetadata breadcrumb in breadcrumbs)
                {
                    if (first)
                    {
                        first = false;
                    }
                    else
                    {
                        message.Append(" -> ");
                    }
                    message.Append(breadcrumb.ID);
                }
                throw new InvalidOperationException(message.ToString());
            }
            cycleCheck.Add(libraryToUse);

            foreach (ExternalAssemblyMetadata dependency in libraryToUse.DirectDependencies)
            {
                LibraryUsagePostOrderTraversal(dependency, libraryOrderOut, usedLibraries, cycleCheck, breadcrumbs);
            }
            cycleCheck.Remove(libraryToUse);
            breadcrumbs.Pop();

            usedLibraries.Add(libraryToUse);
            libraryOrderOut.Add(libraryToUse);
        }
Пример #8
0
        private async Task <ExternalAssemblyMetadata> GetAssemblyMetadataFromAnyPossibleKey(string localeId, string name)
        {
            string key = (localeId == null || localeId == "") ? name : (localeId + ":" + name);

            if (!this.assemblyCache.ContainsKey(key))
            {
                Dictionary <string, object> response = await this.wax.SendRequest("assembly", new Dictionary <string, object>() {
                    { "command", "GetAssemblyMetadataFromAnyPossibleKey" },
                    { "locale", localeId },
                    { "name", name },
                    { "localDeps", this.localDeps },
                    { "projectDir", this.projectDirectory },
                    { "includeSource", true },
                });

                if (!(bool)response["found"])
                {
                    this.assemblyCache[key] = null;
                }
                else
                {
                    Dictionary <string, string> nameByLocale = DictionaryUtil.FlattenedDictionaryToDictionary((string[])response["nameByLocale"]);
                    Dictionary <string, string> sourceCode   = DictionaryUtil.FlattenedDictionaryToDictionary((string[])response["sourceCode"]);

                    ExternalAssemblyMetadata md = new ExternalAssemblyMetadata()
                    {
                        ID                 = (string)response["id"],
                        IsUserDefined      = false,
                        InternalLocale     = Locale.Get((string)response["internalLocale"]),
                        SupportedLocales   = new HashSet <Locale>(((string[])response["supportedLocales"]).Select(id => Locale.Get(id))),
                        NameByLocale       = nameByLocale,
                        OnlyImportableFrom = new HashSet <string>((string[])response["onlyImportableFrom"]),
                        SourceCode         = sourceCode,
                    };
                    md.CanonicalKey         = md.InternalLocale.ID + ":" + md.ID;
                    this.assemblyCache[key] = md;
                    foreach (Locale applicableLocale in md.SupportedLocales)
                    {
                        this.assemblyCache[applicableLocale.ID + ":" + nameByLocale[applicableLocale.ID]] = md;
                    }
                }
            }
            return(this.assemblyCache[key]);
        }
Пример #9
0
        public ParserContext(CompileRequest compileRequest, Wax.WaxHub waxHub)
        {
            this.ClassIdAlloc   = 1;
            this.ScopeIdAlloc   = 1;
            this.CompileRequest = compileRequest;
            this.ProjectId      = compileRequest.ProjectId;
            this.DelegateMainTo = compileRequest.DelegateMainTo;
            this.TypeContext    = new TypeContext();
            Locale rootLocale = compileRequest.CompilerLocale;

            ExternalAssemblyMetadata userDefinedAssembly = CreateRootAssembly(compileRequest.CompilerLocale);
            CompilationScope         userDefinedScope    = new CompilationScope(this, userDefinedAssembly, rootLocale, compileRequest.RootProgrammingLanguage);

            this.PushScope(userDefinedScope);
            this.ScopeManager = new ScopeManager(compileRequest, waxHub);
            this.NamespacePrefixLookupForCurrentFile = new List <string>();
            this.ConstantAndEnumResolutionState      = new Dictionary <TopLevelEntity, ConstantResolutionState>();
            this.LiteralLookup = new LiteralLookup();
        }
Пример #10
0
        private async Task <LocalizedAssemblyView> GetOrImportAssemblyImpl(ParserContext parser, Token throwToken, string fullImportNameWithDots)
        {
            // TODO: allow importing from a user-specified locale
            Locale fromLocale = parser.CurrentLocale;
            string name       = fullImportNameWithDots.Contains('.') ? fullImportNameWithDots.Split('.')[0] : fullImportNameWithDots;

            string secondAttemptedKey = name;
            ExternalAssemblyMetadata assemblyMetadata = await this.GetAssemblyMetadataFromAnyPossibleKey(fromLocale.ID, name);

            Locale effectiveLocale = fromLocale;

            if (assemblyMetadata == null)
            {
                assemblyMetadata = await this.GetAssemblyMetadataFromAnyPossibleKey(null, name);

                if (assemblyMetadata != null &&
                    assemblyMetadata.SupportedLocales.Contains(fromLocale) &&
                    assemblyMetadata.InternalLocale != fromLocale)
                {
                    // Coincidental cross-language collision.
                    return(null);
                }

                if (assemblyMetadata == null)
                {
                    // Simply no matches at all.
                    return(null);
                }

                effectiveLocale = assemblyMetadata.InternalLocale;
            }

            // Are there any restrictions on importing that library from this location?
            if (!assemblyMetadata.IsAllowedImport(parser.CurrentLibrary))
            {
                throw new ParserException(throwToken, "This library cannot be imported from here.");
            }

            // Ensure all secondary lookups for each locale is instantiated to make the upcoming code more readable.
            if (!this.importedAssembliesByLocalizedName.ContainsKey(effectiveLocale))
            {
                this.importedAssembliesByLocalizedName[effectiveLocale] = new Dictionary <string, LocalizedAssemblyView>();
            }
            if (!this.importedAssembliesByLocalizedName.ContainsKey(assemblyMetadata.InternalLocale))
            {
                this.importedAssembliesByLocalizedName[assemblyMetadata.InternalLocale] = new Dictionary <string, LocalizedAssemblyView>();
            }

            // Check to see if this library has been imported before.
            if (this.importedAssembliesById.ContainsKey(assemblyMetadata.ID))
            {
                // Is it imported by the same locale?
                if (this.importedAssembliesByLocalizedName[effectiveLocale].ContainsKey(name))
                {
                    // Then just return the previous instance as-is.
                    return(this.importedAssembliesByLocalizedName[effectiveLocale][name]);
                }

                // Wrap the previous instance in the new locale.
                LocalizedAssemblyView output = new LocalizedAssemblyView(effectiveLocale, this.importedAssembliesById[assemblyMetadata.ID]);
                this.importedAssembliesByLocalizedName[effectiveLocale][output.Name] = output;
                return(output);
            }

            Dictionary <string, string> sourceCode = assemblyMetadata.SourceCode;

            string arbitraryFilename = sourceCode.Keys.Where(t => t.Contains('.')).Select(t => t.ToLowerInvariant()).FirstOrDefault();
            ProgrammingLanguage programmingLanguage = arbitraryFilename != null && arbitraryFilename.EndsWith(".acr")
                ? ProgrammingLanguage.ACRYLIC
                : ProgrammingLanguage.CRAYON;

            // If the assembly exists but hasn't been imported before, instantiate it and
            // add it to all the lookups. This needs to happen before parsing the embedded
            // code to prevent infinite recursion.
            CompilationScope compilationScope = new CompilationScope(parser, assemblyMetadata, assemblyMetadata.InternalLocale, programmingLanguage);

            this.assembliesAlreadyImportedIndexByKey[assemblyMetadata.CanonicalKey] = this.ImportedAssemblyScopes.Count;
            this.ImportedAssemblyScopes.Add(compilationScope);
            this.importedAssembliesById[assemblyMetadata.ID] = compilationScope;
            LocalizedAssemblyView localizedView = new LocalizedAssemblyView(effectiveLocale, compilationScope);

            this.importedAssembliesByLocalizedName[effectiveLocale][name] = localizedView;

            // Parse the assembly.
            parser.PushScope(compilationScope);
            foreach (string file in sourceCode.Keys.OrderBy(s => s.ToLowerInvariant()))
            {
                string fakeName = "[" + file + "]";
                string code     = sourceCode[file];
                await parser.ParseFile(fakeName, code);
            }
            parser.PopScope();

            return(localizedView);
        }