public VariableTypeBindingVisitor( [NotNull] OrderedSet <TypeBinding> potentialTypeBindings, [NotNull] OrderedSet <string> allSeenVariables, ICollection <TextReplacement> replacements = null) { this.potentialTypeBindings = potentialTypeBindings; this.allSeenVariables = allSeenVariables; this.replacements = replacements; }
public UpgradeResult Upgrade(UpgradeJob upgradeJob) { var potentialTypeBindings = new OrderedSet <TypeBinding>(); var allSeenVariables = new OrderedSet <string>(); foreach (var file in upgradeJob.Files) { ICharStream input = CharStreams.fromstring(file.Source); YarnSpinnerV1Lexer lexer = new YarnSpinnerV1Lexer(input); CommonTokenStream tokens = new CommonTokenStream(lexer); YarnSpinnerV1Parser parser = new YarnSpinnerV1Parser(tokens); YarnSpinnerV1Parser.DialogueContext tree = parser.dialogue(); var declarationVisitor = new VariableTypeBindingVisitor(potentialTypeBindings, allSeenVariables); declarationVisitor.Visit(tree); } // We now have information on which variables exist, and // potentially what type they are. We can now do a pass, // rewriting certain expressions. var outputFiles = new List <UpgradeResult.OutputFile>(); foreach (var file in upgradeJob.Files) { ICharStream input = CharStreams.fromstring(file.Source); YarnSpinnerV1Lexer lexer = new YarnSpinnerV1Lexer(input); CommonTokenStream tokens = new CommonTokenStream(lexer); YarnSpinnerV1Parser parser = new YarnSpinnerV1Parser(tokens); YarnSpinnerV1Parser.DialogueContext tree = parser.dialogue(); var replacements = new List <TextReplacement>(); var declarationVisitorWithReplacements = new VariableTypeBindingVisitor(potentialTypeBindings, allSeenVariables, replacements); declarationVisitorWithReplacements.Visit(tree); outputFiles.Add(new UpgradeResult.OutputFile(file.FileName, replacements, file.Source)); } List <TypeBinding> unifiedVariableBindings = TypeBinding.UnifyBindings(potentialTypeBindings); // We finally have our bindings. Generate declarations for them. var allBindings = unifiedVariableBindings.ToDictionary(b => b.VariableName, b => b.Type); if (allSeenVariables.Count() > 0) { // If we're here, we've got variables, and we need to // generate declarations for them. We'll do this by // generating a node in a new file that contains them. var declarationsNodeStringBuilder = new System.Text.StringBuilder(); // declarationsNodeStringBuilder.AppendLine var preambleLines = new[] { "title: _AutoGeneratedVariableDeclarations", "tags: generated ys-upgrade-v1-to-v2", "---", "// NOTE: These variable declarations were automatically generated as part", "// of the upgrade process. Please check these before using them in your", "// game.", }; foreach (var line in preambleLines) { declarationsNodeStringBuilder.AppendLine(line); } declarationsNodeStringBuilder.AppendLine(); // Create a dictionary that maps a type to a string that // will be used in declarations. This string contains the // name of the type as defined in Yarn, as well as a // default value. var typesToStrings = new Dictionary <Type, string> { { Type.Bool, "false as bool" }, { Type.Number, "0 as number" }, { Type.String, @""""" as string" }, { Type.Undefined, "undefined" }, }; foreach (var variableName in allSeenVariables) { Type type; if (allBindings.ContainsKey(variableName)) { type = allBindings[variableName]; } else { type = Type.Undefined; } declarationsNodeStringBuilder.Append("<<declare "); declarationsNodeStringBuilder.Append(variableName); declarationsNodeStringBuilder.Append(" = "); declarationsNodeStringBuilder.Append(typesToStrings[type]); declarationsNodeStringBuilder.Append(">>"); declarationsNodeStringBuilder.AppendLine(); } declarationsNodeStringBuilder.AppendLine("==="); var outputDirectory = System.IO.Path.GetDirectoryName(upgradeJob.Files.First().FileName); var outputFileName = System.IO.Path.Combine(outputDirectory, "Program.yarnproject"); var declarationsOutputFile = new UpgradeResult.OutputFile(outputFileName, declarationsNodeStringBuilder.ToString()); outputFiles.Add(declarationsOutputFile); } return(new UpgradeResult { Files = outputFiles, }); }