示例#1
0
        public string GetSwitchLookupCode()
        {
            List <string> output = new List <string>();

            foreach (string key in this.stringSwitchLookups.Keys)
            {
                string lookupName = key;
                Dictionary <string, int> valuesToInts = this.stringSwitchLookups[key];
                output.Add(lookupName);
                output.Add(" = { ");
                bool first = true;
                foreach (string skey in valuesToInts.Keys)
                {
                    if (!first)
                    {
                        first = false;
                        output.Add(", ");
                    }
                    output.Add(StringTokenUtil.ConvertStringValueToCode(skey));
                    output.Add(": ");
                    output.Add("" + valuesToInts[skey]);
                }
                output.Add(" };\r\n");
            }

            foreach (string lookupName in this.intListLookups.Keys)
            {
                List <int>            actualList = new List <int>();
                Dictionary <int, int> lookup     = this.intListLookups[lookupName];
                int explicitMax   = this.explicitMaxes[lookupName];
                int defaultCaseId = this.defaultCaseIds[lookupName];
                while (actualList.Count <= explicitMax)
                {
                    actualList.Add(defaultCaseId);
                }

                foreach (int ikey in lookup.Keys)
                {
                    while (actualList.Count <= ikey)
                    {
                        actualList.Add(defaultCaseId);
                    }
                    actualList[ikey] = lookup[ikey];
                }

                output.Add(lookupName);
                output.Add(" = [");
                for (int i = 0; i < actualList.Count; ++i)
                {
                    if (i > 0)
                    {
                        output.Add(", ");
                    }
                    output.Add(actualList[i] + "");
                }
                output.Add("];\r\n");
            }

            return(string.Join("", output));
        }
示例#2
0
        public override void ExportProject(
            Dictionary <string, FileOutput> output,
            IList <LibraryForExport> libraries,
            ResourceDatabase resourceDatabase,
            Options options)
        {
            List <string> jsExtraHead = new List <string>()
            {
                options.GetStringOrEmpty(ExportOptionKey.JS_HEAD_EXTRAS)
            };

            if (options.GetBool(ExportOptionKey.JS_FULL_PAGE))
            {
                jsExtraHead.Add(
                    "<script type=\"text/javascript\">"
                    + "C$common$globalOptions['fullscreen'] = true;"
                    + "</script>");
            }
            options.SetOption(ExportOptionKey.JS_HEAD_EXTRAS, string.Join("\n", jsExtraHead));

            Dictionary <string, string> replacements = this.GenerateReplacementDictionary(options, resourceDatabase);

            TemplateReader templateReader = new TemplateReader(new PkgAwareFileUtil(), this);
            TemplateSet    vmTemplates    = templateReader.GetVmTemplates();

            output["vm.js"] = new FileOutput()
            {
                Type        = FileOutputType.Text,
                TextContent = vmTemplates.GetText("vm.js"),
            };

            List <LibraryForExport> librariesWithCode = new List <LibraryForExport>();

            foreach (LibraryForExport library in libraries.Where(lib => lib.HasNativeCode))
            {
                string      libraryName  = library.Name;
                TemplateSet libTemplates = templateReader.GetLibraryTemplates(library);

                List <string> libraryLines = new List <string>();
                libraryLines.Add(libTemplates.GetText("gen/lib_" + libraryName.ToLowerInvariant() + ".js"));
                libraryLines.Add("");
                libraryLines.Add("C$common$scrapeLibFuncNames('" + libraryName.ToLowerInvariant() + "');");
                libraryLines.Add("");

                // add helper functions after the scrape.

                foreach (string jsHelperFile in libTemplates.GetPaths("source/", ".js"))
                {
                    libraryLines.Add(libTemplates.GetText(jsHelperFile));
                    libraryLines.Add("");
                }

                output["libs/lib_" + libraryName.ToLowerInvariant() + ".js"] = new FileOutput()
                {
                    Type        = FileOutputType.Text,
                    TextContent = string.Join(this.NL, libraryLines),
                };
                librariesWithCode.Add(library);
            }

            Dictionary <string, string> htmlReplacements = new Dictionary <string, string>(replacements);

            replacements["JS_LIB_INCLUSIONS"] = GenerateJsLibInclusionHtml(output.Keys);

            this.CopyResourceAsText(output, "index.html", "Resources/HostHtml.txt", replacements);
            this.CopyResourceAsText(output, "test_server.py", "Resources/TestServerPy.txt", replacements);

            this.CopyResourceAsText(output, "common.js", "Resources/Common.txt", replacements);

            System.Text.StringBuilder resourcesJs = new System.Text.StringBuilder();

            foreach (FileOutput textResource in resourceDatabase.TextResources)
            {
                resourcesJs.Append("C$common$addTextRes(");
                resourcesJs.Append(StringTokenUtil.ConvertStringValueToCode(textResource.CanonicalFileName));
                resourcesJs.Append(", ");
                resourcesJs.Append(StringTokenUtil.ConvertStringValueToCode(textResource.TextContent));
                resourcesJs.Append(");\n");
            }

            foreach (FileOutput fontResource in resourceDatabase.FontResources)
            {
                resourcesJs.Append("C$common$addBinaryRes(");
                resourcesJs.Append(StringTokenUtil.ConvertStringValueToCode(fontResource.CanonicalFileName));
                resourcesJs.Append(", '");
                resourcesJs.Append(Base64.ToBase64(fontResource.GetFinalBinaryContent()));
                resourcesJs.Append("');\n");
            }

            FileOutput imageSheetManifest = resourceDatabase.ImageSheetManifestFile;

            resourcesJs.Append("C$common$addTextRes('image_sheets.txt', ");
            resourcesJs.Append(imageSheetManifest == null ? "''" : StringTokenUtil.ConvertStringValueToCode(imageSheetManifest.TextContent));
            resourcesJs.Append(");\n");

            resourcesJs.Append("C$common$resourceManifest = ");
            resourcesJs.Append(StringTokenUtil.ConvertStringValueToCode(resourceDatabase.ResourceManifestFile.TextContent));
            resourcesJs.Append(";\n");

            string filePrefix = options.GetStringOrNull(ExportOptionKey.JS_FILE_PREFIX);

            if (filePrefix != null)
            {
                resourcesJs.Append("C$common$jsFilePrefix = ");
                resourcesJs.Append(StringTokenUtil.ConvertStringValueToCode(filePrefix));
                resourcesJs.Append(";\n");
            }

            output["resources.js"] = new FileOutput()
            {
                Type        = FileOutputType.Text,
                TextContent = resourcesJs.ToString(),
            };

            output["bytecode.js"] = new FileOutput()
            {
                Type        = FileOutputType.Text,
                TextContent = "C$bytecode = " + StringTokenUtil.ConvertStringValueToCode(resourceDatabase.ByteCodeFile.TextContent) + ";",
            };

            foreach (string imageResourceFile in resourceDatabase.ImageSheetFiles.Keys)
            {
                FileOutput file = resourceDatabase.ImageSheetFiles[imageResourceFile];
                output["resources/images/" + imageResourceFile] = file;
            }

            foreach (FileOutput audioResourceFile in resourceDatabase.AudioResources)
            {
                output["resources/audio/" + audioResourceFile.CanonicalFileName] = audioResourceFile;
            }

            // TODO: minify JavaScript across all of output dictionary
        }
示例#3
0
        internal override IList <Executable> Resolve(ParserContext parser)
        {
            TODO.MakeSwitchStatementFallthroughsErrors();
            if (this.explicitMax != null)
            {
                throw new ParserException(this.explicitMaxToken, "Unexpected token: '{'");
            }

            bool useExplicitMax = this.explicitMax != null;
            int  explicitMax    = 0;

            if (useExplicitMax)
            {
                this.explicitMax = this.explicitMax.Resolve(parser);
                if (!(this.explicitMax is IntegerConstant))
                {
                    throw new ParserException(this.explicitMax, "Explicit max must be an integer.");
                }
                explicitMax = ((IntegerConstant)this.explicitMax).Value;
            }

            this.Condition = this.Condition.Resolve(parser);
            int integers    = 0;
            int strings     = 0;
            int largestSpan = 0;

            HashSet <int>    intCases    = new HashSet <int>();
            HashSet <string> stringCases = new HashSet <string>();

            foreach (Chunk chunk in this.chunks)
            {
                if (chunk.Cases.Length > largestSpan)
                {
                    largestSpan = chunk.Cases.Length;
                }

                for (int i = 0; i < chunk.Cases.Length; ++i)
                {
                    if (chunk.Cases[i] != null)
                    {
                        Expression caseExpr = chunk.Cases[i].Resolve(parser);
                        chunk.Cases[i] = caseExpr;

                        if (caseExpr is IntegerConstant)
                        {
                            int intValue = ((IntegerConstant)caseExpr).Value;
                            if (intCases.Contains(intValue))
                            {
                                throw new ParserException(caseExpr, "Duplicate case value in same switch: " + intValue);
                            }
                            intCases.Add(intValue);
                        }
                        else if (caseExpr is StringConstant)
                        {
                            string strValue = ((StringConstant)caseExpr).Value;
                            if (stringCases.Contains(strValue))
                            {
                                throw new ParserException(caseExpr, "Duplicate case value in same switch: " + StringTokenUtil.ConvertStringValueToCode(strValue));
                            }
                            stringCases.Add(strValue);
                        }

                        if (chunk.Cases[i] is IntegerConstant)
                        {
                            integers++;
                        }
                        else if (chunk.Cases[i] is StringConstant)
                        {
                            strings++;
                        }
                        else
                        {
                            if (chunk.Cases[i] is DotField)
                            {
                                // Since most enums are in all caps, offer a more helpful error message when there's a dot followed by all caps.
                                string field = ((DotField)chunk.Cases[i]).FieldToken.Value;
                                if (field.ToUpperInvariant() == field)
                                {
                                    throw new ParserException(chunk.Cases[i],
                                                              "Only strings, integers, and enums can be used in a switch statement. It looks like this is probably supposed to be an enum. Make sure that it is spelled correctly.");
                                }
                            }
                            throw new ParserException(chunk.Cases[i], "Only strings, integers, and enums can be used in a switch statement.");
                        }
                    }
                }

                chunk.Code = Resolve(parser, chunk.Code).ToArray();
            }

            if (integers != 0 && strings != 0)
            {
                throw new ParserException(this, "Cannot mix string and integer cases in a single switch statement.");
            }

            if (integers == 0 && strings == 0)
            {
                if (this.chunks.Length == 0)
                {
                    throw new ParserException(this, "Cannot have a blank switch statement.");
                }
                if (this.chunks.Length > 1)
                {
                    throw new Exception("only had default but had multiple chunks. This should have been prevented at parse-time.");
                }
                return(this.chunks[0].Code);
            }

            Chunk      lastChunk = this.chunks[this.chunks.Length - 1];
            Expression lastCase  = lastChunk.Cases[lastChunk.Cases.Length - 1];

            this.ContainsDefault = lastCase == null;
            this.UsesStrings     = strings != 0;
            this.IsSafe          = !this.ContainsDefault;
            this.IsContinuous    = integers != 0 && largestSpan == 1 && this.IsSafe && this.DetermineContinuousness();

            return(this.CompilationResolution(parser));
        }