From 2b616889a312073f0c4fa403e52cfb31b9d9ee22 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Thu, 27 Aug 2020 18:40:07 +1000 Subject: [PATCH] Tidy up some code --- YarnSpinner.Compiler/CodeGenerationVisitor.cs | 28 +++- YarnSpinner.Compiler/Compiler.cs | 72 +++++--- YarnSpinner.Compiler/ExpressionTypeVisitor.cs | 156 +++++++++++------- .../VariableDeclarationVisitor.cs | 42 +++-- YarnSpinner.Tests/TypeTests.cs | 68 +++++--- 5 files changed, 239 insertions(+), 127 deletions(-) diff --git a/YarnSpinner.Compiler/CodeGenerationVisitor.cs b/YarnSpinner.Compiler/CodeGenerationVisitor.cs index b92fd8581..f8c805068 100644 --- a/YarnSpinner.Compiler/CodeGenerationVisitor.cs +++ b/YarnSpinner.Compiler/CodeGenerationVisitor.cs @@ -88,9 +88,7 @@ public override int VisitLine_statement(YarnSpinnerParser.Line_statementContext // // is identical to // - // <> - // Mae: here's a line - // <> + // <> Mae: here's a line <> // Convert the formatted string into a string with // placeholders, and evaluate the inline expressions and push @@ -161,7 +159,8 @@ public override int VisitSetVariableToValue(YarnSpinnerParser.SetVariableToValue var expressionType = expressionTypeVisitor.Visit(context.expression()); var variableType = expressionTypeVisitor.Visit(context.variable()); - if (expressionType != variableType) { + if (expressionType != variableType) + { throw new TypeException(context, $"{context.variable().GetText()} ({variableType}) cannot be assigned a {expressionType}"); } @@ -280,6 +279,7 @@ public override int VisitIf_statement(YarnSpinnerParser.If_statementContext cont return 0; } + internal void generateClause(string jumpLabel, YarnSpinnerParser.StatementContext[] children, YarnSpinnerParser.ExpressionContext expression) { string endOfClauseLabel = compiler.RegisterLabel("skipclause"); @@ -293,7 +293,7 @@ internal void generateClause(string jumpLabel, YarnSpinnerParser.StatementContex // Code-generate the expression Visit(expression); - + compiler.Emit(OpCode.JumpIfFalse, new Operand(endOfClauseLabel)); } @@ -316,7 +316,6 @@ internal void generateClause(string jumpLabel, YarnSpinnerParser.StatementContex // indent statements dedent)+ public override int VisitShortcut_option_statement(YarnSpinnerParser.Shortcut_option_statementContext context) { - string endOfGroupLabel = compiler.RegisterLabel("group_end"); var labels = new List(); @@ -426,12 +425,15 @@ public override int VisitShortcut_option_statement(YarnSpinnerParser.Shortcut_op // the calls for the various operations and expressions first the // special cases (), unary -, !, and if it is just a value by // itself + #region specialCaseCalls + // (expression) public override int VisitExpParens(YarnSpinnerParser.ExpParensContext context) { return Visit(context.expression()); } + // -expression public override int VisitExpNegative(YarnSpinnerParser.ExpNegativeContext context) { @@ -446,6 +448,7 @@ public override int VisitExpNegative(YarnSpinnerParser.ExpNegativeContext contex return 0; } + // (not NOT !)expression public override int VisitExpNot(YarnSpinnerParser.ExpNotContext context) { @@ -460,6 +463,7 @@ public override int VisitExpNot(YarnSpinnerParser.ExpNotContext context) return 0; } + // variable public override int VisitExpValue(YarnSpinnerParser.ExpValueContext context) { @@ -482,6 +486,7 @@ internal void genericExpVisitor(YarnSpinnerParser.ExpressionContext left, YarnSp compiler.Emit(OpCode.CallFunc, new Operand(tokens[op].ToString())); } + // * / % public override int VisitExpMultDivMod(YarnSpinnerParser.ExpMultDivModContext context) { @@ -489,6 +494,7 @@ public override int VisitExpMultDivMod(YarnSpinnerParser.ExpMultDivModContext co return 0; } + // + - public override int VisitExpAddSub(YarnSpinnerParser.ExpAddSubContext context) { @@ -503,6 +509,7 @@ public override int VisitExpComparison(YarnSpinnerParser.ExpComparisonContext co return 0; } + // == != public override int VisitExpEquality(YarnSpinnerParser.ExpEqualityContext context) { @@ -510,6 +517,7 @@ public override int VisitExpEquality(YarnSpinnerParser.ExpEqualityContext contex return 0; } + // and && or || xor ^ public override int VisitExpAndOrXor(YarnSpinnerParser.ExpAndOrXorContext context) { @@ -532,7 +540,8 @@ internal void opEquals(YarnSpinnerParser.VariableContext variable, YarnSpinnerPa var expressionType = expressionTypeVisitor.Visit(expression); var variableType = expressionTypeVisitor.Visit(variable); - if (expressionType != variableType) { + if (expressionType != variableType) + { throw new TypeException(expression.Parent as ParserRuleContext, $"{variable.GetText()} ({variableType}) cannot be assigned a {expressionType}"); } @@ -584,6 +593,7 @@ public override int VisitValueVar(YarnSpinnerParser.ValueVarContext context) { return Visit(context.variable()); } + public override int VisitValueNumber(YarnSpinnerParser.ValueNumberContext context) { float number = float.Parse(context.NUMBER().GetText(), CultureInfo.InvariantCulture); @@ -591,17 +601,20 @@ public override int VisitValueNumber(YarnSpinnerParser.ValueNumberContext contex return 0; } + public override int VisitValueTrue(YarnSpinnerParser.ValueTrueContext context) { compiler.Emit(OpCode.PushBool, new Operand(true)); return 0; } + public override int VisitValueFalse(YarnSpinnerParser.ValueFalseContext context) { compiler.Emit(OpCode.PushBool, new Operand(false)); return 0; } + public override int VisitVariable(YarnSpinnerParser.VariableContext context) { string variableName = context.VAR_ID().GetText(); @@ -609,6 +622,7 @@ public override int VisitVariable(YarnSpinnerParser.VariableContext context) return 0; } + public override int VisitValueString(YarnSpinnerParser.ValueStringContext context) { // stripping the " off the front and back actually is this what diff --git a/YarnSpinner.Compiler/Compiler.cs b/YarnSpinner.Compiler/Compiler.cs index 67f06ea7b..8eda70cff 100644 --- a/YarnSpinner.Compiler/Compiler.cs +++ b/YarnSpinner.Compiler/Compiler.cs @@ -1,4 +1,4 @@ -namespace Yarn.Compiler +namespace Yarn.Compiler { using System; using System.Collections.Generic; @@ -107,27 +107,34 @@ internal StringInfo(string text, string fileName, string nodeName, int lineNumbe } } - public struct VariableDeclaration { + public struct VariableDeclaration + { public string name; public Value defaultValue; public Value.Type type; public string description; - public override string ToString() { - if (string.IsNullOrEmpty(description)) { + public override string ToString() + { + if (string.IsNullOrEmpty(description)) + { return $"{name} : {type} = {defaultValue}"; - } else { + } + else + { return $"{name} : {type} = {defaultValue} (\"{description}\")"; } } } - public struct CompilationJob { + public struct CompilationJob + { /// /// Represents the contents of a file to compile. /// - public struct File { + public struct File + { public string FileName; public string Source; } @@ -176,18 +183,21 @@ public static CompilationJob CreateFromFiles(IEnumerable paths, Library }; } - public static CompilationJob CreateFromFiles(params string[] paths) { - return CreateFromFiles((IEnumerable) paths); + public static CompilationJob CreateFromFiles(params string[] paths) + { + return CreateFromFiles((IEnumerable)paths); } /// /// Creates a new using the contents /// of a string. /// - /// The name to assign to the compiled file. + /// The name to assign to the compiled + /// file. /// The text to compile. /// A new . - public static CompilationJob CreateFromString(string fileName, string source, Library library = null) { + public static CompilationJob CreateFromString(string fileName, string source, Library library = null) + { return new CompilationJob { Files = new List @@ -221,8 +231,9 @@ internal static CompilationResult CombineCompilationResults(IEnumerable VariableDeclarations = new List(); /// - /// The Library, which contains the function declarations known to the compiler. Supplied as part of a . + /// The Library, which contains the function declarations known to + /// the compiler. Supplied as part of a . /// internal Library Library { get; private set; } @@ -313,19 +327,24 @@ public static CompilationResult Compile(CompilationJob compilationJob) { var results = new List(); - // All variable declarations that we've encountered during this compilation job + // All variable declarations that we've encountered during this + // compilation job var derivedVariableDeclarations = new List(); - // All variable declarations that we've encountered, PLUS the ones we knew about before + // All variable declarations that we've encountered, PLUS the + // ones we knew about before var knownVariableDeclarations = new List(); - if (compilationJob.VariableDeclarations != null) { + if (compilationJob.VariableDeclarations != null) + { knownVariableDeclarations.AddRange(compilationJob.VariableDeclarations); } var compiledTrees = new List<(string name, IParseTree tree)>(); - // First pass: parse all files, generate their syntax trees, and figure out what variables they've delcared - foreach (var file in compilationJob.Files) { + // First pass: parse all files, generate their syntax trees, + // and figure out what variables they've delcared + foreach (var file in compilationJob.Files) + { var tree = ParseSyntaxTree(file); IEnumerable newDeclarations = DeriveVariableDeclarations(tree, knownVariableDeclarations); @@ -335,10 +354,11 @@ public static CompilationResult Compile(CompilationJob compilationJob) compiledTrees.Add((file.FileName, tree)); } - foreach (var parsedFile in compiledTrees) { + foreach (var parsedFile in compiledTrees) + { CompilationResult compilationResult = GenerateCode(parsedFile.name, knownVariableDeclarations, compilationJob, parsedFile.tree); results.Add(compilationResult); - } + } var finalResult = CompilationResult.CombineCompilationResults(results); @@ -347,7 +367,8 @@ public static CompilationResult Compile(CompilationJob compilationJob) // it. (We don't specify an initial value for // externally-declared variables, because we expect their value // to be in the variable storage when the program is run.) - foreach (var declaration in derivedVariableDeclarations) { + foreach (var declaration in derivedVariableDeclarations) + { Operand value; switch (declaration.type) @@ -379,7 +400,8 @@ private static IEnumerable DeriveVariableDeclarations(IPars variableDeclarationVisitor.Visit(tree); - // Upon exit, declarations will now contain every variable declaration we found + // Upon exit, declarations will now contain every variable + // declaration we found return variableDeclarationVisitor.NewVariableDeclarations; } @@ -396,7 +418,7 @@ private static CompilationResult GenerateCode(string fileName, IEnumerable - /// A Visitor that walks an expression parse tree and returns its - /// type. Call the method to begin checking. If - /// a single valid type for the parse tree can't be found, a - /// TypeException is thrown. + /// A Visitor that walks an expression parse tree and returns its type. + /// Call the method to begin checking. If a single + /// valid type for the parse tree can't be found, a TypeException is + /// thrown. /// - internal class ExpressionTypeVisitor : YarnSpinnerParserBaseVisitor { + internal class ExpressionTypeVisitor : YarnSpinnerParserBaseVisitor + { // The variable declarations we know about protected IEnumerable VariableDeclarations; - // If true, this expression may not involve any variables or function calls + // If true, this expression may not involve any variables or + // function calls protected bool RequireConstantExpression; // The function declarations we know about @@ -29,49 +31,59 @@ public ExpressionTypeVisitor(IEnumerable variableDeclaratio } protected override Value.Type DefaultResult => Value.Type.Undefined; - - public override Value.Type VisitValueString(YarnSpinnerParser.ValueStringContext context) { + + public override Value.Type VisitValueString(YarnSpinnerParser.ValueStringContext context) + { return Value.Type.String; } - public override Value.Type VisitValueTrue(YarnSpinnerParser.ValueTrueContext context) { + public override Value.Type VisitValueTrue(YarnSpinnerParser.ValueTrueContext context) + { return Value.Type.Bool; } - public override Value.Type VisitValueFalse(YarnSpinnerParser.ValueFalseContext context) { + public override Value.Type VisitValueFalse(YarnSpinnerParser.ValueFalseContext context) + { return Value.Type.Bool; } - public override Value.Type VisitValueNumber(YarnSpinnerParser.ValueNumberContext context) { + public override Value.Type VisitValueNumber(YarnSpinnerParser.ValueNumberContext context) + { return Value.Type.Number; } - public override Value.Type VisitValueVar(YarnSpinnerParser.ValueVarContext context) { + public override Value.Type VisitValueVar(YarnSpinnerParser.ValueVarContext context) + { return VisitVariable(context.variable()); } - public override Value.Type VisitVariable(YarnSpinnerParser.VariableContext context) { - if (RequireConstantExpression) { + public override Value.Type VisitVariable(YarnSpinnerParser.VariableContext context) + { + if (RequireConstantExpression) + { throw new TypeException(context, $"Can't use a variable here: expression must be constant"); } - // The type of the value depends on the declared type of - // the variable + // The type of the value depends on the declared type of the + // variable var name = context.VAR_ID().GetText(); - foreach (var declaration in VariableDeclarations) { - if (declaration.name == name) { + foreach (var declaration in VariableDeclarations) + { + if (declaration.name == name) + { return declaration.type; } } - + throw new TypeException(context, $"Undeclared variable {name}"); } - public override Value.Type VisitValueNull(YarnSpinnerParser.ValueNullContext context) { + public override Value.Type VisitValueNull(YarnSpinnerParser.ValueNullContext context) + { throw new TypeException("Null is not a permitted type in Yarn Spinner 2.0 and later"); } @@ -153,9 +165,12 @@ public override Value.Type VisitValueFunc(YarnSpinnerParser.ValueFuncContext con { if (mapping.NativeType.IsAssignableFrom(expectedType)) { - if (suppliedType != mapping.YarnType) { + if (suppliedType != mapping.YarnType) + { throw new TypeException($"{functionName} parameter {i + 1} expects a {mapping.YarnType}, not a {suppliedType}"); - } else { + } + else + { // This parameter's expected type is valid, and // the supplied type can be used with it. expectedTypeIsValid = true; @@ -164,8 +179,9 @@ public override Value.Type VisitValueFunc(YarnSpinnerParser.ValueFuncContext con } } - if (expectedTypeIsValid == false) { - throw new TypeException($"{functionName} cannot be called: parameter {i+1}'s type ({expectedType}) cannot be used in Yarn functions"); + if (expectedTypeIsValid == false) + { + throw new TypeException($"{functionName} cannot be called: parameter {i + 1}'s type ({expectedType}) cannot be used in Yarn functions"); } } @@ -187,78 +203,92 @@ public override Value.Type VisitValueFunc(YarnSpinnerParser.ValueFuncContext con throw new TypeException($"Function {functionName} can't be called, because it returns an invalid type ({returnType})"); } - public override Value.Type VisitExpValue(YarnSpinnerParser.ExpValueContext context) { + public override Value.Type VisitExpValue(YarnSpinnerParser.ExpValueContext context) + { // Value expressions have the type of their inner value return Visit(context.value()); } - public override Value.Type VisitExpParens(YarnSpinnerParser.ExpParensContext context) { + public override Value.Type VisitExpParens(YarnSpinnerParser.ExpParensContext context) + { // Parens expressions have the type of their inner expression return Visit(context.expression()); } - public override Value.Type VisitExpAndOrXor(YarnSpinnerParser.ExpAndOrXorContext context) { - // And/Or/Xor expressions require both child expressions to be Bool, and have a type of Bool + public override Value.Type VisitExpAndOrXor(YarnSpinnerParser.ExpAndOrXorContext context) + { + // And/Or/Xor expressions require both child expressions to be + // Bool, and have a type of Bool var expressions = context.expression(); Value.Type left = Visit(expressions[0]); Value.Type right = Visit(expressions[1]); - if (left != Value.Type.Bool || right != Value.Type.Bool) { + if (left != Value.Type.Bool || right != Value.Type.Bool) + { throw new TypeException(context, $"Both sides of {context.op.Text} must be bool, not {left} + {right}"); } return Value.Type.Bool; } - private Value.Type CheckOperation(ParserRuleContext context, ParserRuleContext[] terms, string operationType, params Value.Type[] permittedTypes ) { + private Value.Type CheckOperation(ParserRuleContext context, ParserRuleContext[] terms, string operationType, params Value.Type[] permittedTypes) + { var types = new List(); var expressionType = Value.Type.Undefined; - foreach (var expression in terms) { + foreach (var expression in terms) + { Value.Type type = Visit(expression); types.Add(type); - if (expressionType == Value.Type.Undefined) { + if (expressionType == Value.Type.Undefined) + { // This is the first concrete type we've seen. This // will be our expression type. expressionType = type; - } + } } // The expression type that we've seen must not be Any or // Undefined - it needs to be a concrete type. - if (expressionType == Value.Type.Undefined) { + if (expressionType == Value.Type.Undefined) + { throw new TypeException(context, $"Can't determine a type for operands"); } string typeList; // All types must be same as the expression type - for (int i = 1; i < types.Count; i++) { - if (types[i] != expressionType) { + for (int i = 1; i < types.Count; i++) + { + if (types[i] != expressionType) + { typeList = string.Join(", ", types); throw new TypeException(context, $"All terms of {operationType} must be the same, not {typeList}"); } } - + // Types must match one of the permitted types - foreach (var type in permittedTypes) { - if (expressionType == type) { + foreach (var type in permittedTypes) + { + if (expressionType == type) + { // This is one of the permitted types, so this // expression is valid return expressionType; } } - - var permittedTypesList = string.Join(" or ", permittedTypes); + + var permittedTypesList = string.Join(" or ", permittedTypes); typeList = string.Join(", ", types); throw new TypeException(context, $"Terms of {operationType} must be {permittedTypesList}, not {typeList}"); } - - public override Value.Type VisitExpAddSub(YarnSpinnerParser.ExpAddSubContext context) { + + public override Value.Type VisitExpAddSub(YarnSpinnerParser.ExpAddSubContext context) + { var expressions = context.expression(); @@ -272,20 +302,23 @@ public override Value.Type VisitExpAddSub(YarnSpinnerParser.ExpAddSubContext con return CheckOperation(context, expressions, context.op.Text, Value.Type.Number); default: throw new InvalidOperationException($"Internal error: {nameof(VisitExpAddSub)} got unexpected op {context.op.Text}"); - } + } } - public override Value.Type VisitExpMultDivMod(YarnSpinnerParser.ExpMultDivModContext context) { + public override Value.Type VisitExpMultDivMod(YarnSpinnerParser.ExpMultDivModContext context) + { var expressions = context.expression(); // *, /, % all support numbers only return CheckOperation(context, expressions, context.op.Text, Value.Type.Number); } - public override Value.Type VisitExpPlusMinusEquals(YarnSpinnerParser.ExpPlusMinusEqualsContext context) { + public override Value.Type VisitExpPlusMinusEquals(YarnSpinnerParser.ExpPlusMinusEqualsContext context) + { ParserRuleContext[] terms = { context.variable(), context.expression() }; - switch (context.op.Text) { + switch (context.op.Text) + { case "+=": // + supports strings and numbers return CheckOperation(context, terms, context.op.Text, Value.Type.String, Value.Type.Number); @@ -297,14 +330,16 @@ public override Value.Type VisitExpPlusMinusEquals(YarnSpinnerParser.ExpPlusMinu } } - public override Value.Type VisitExpMultDivModEquals(YarnSpinnerParser.ExpMultDivModEqualsContext context) { + public override Value.Type VisitExpMultDivModEquals(YarnSpinnerParser.ExpMultDivModEqualsContext context) + { ParserRuleContext[] terms = { context.variable(), context.expression() }; // *, /, % all support numbers only - return CheckOperation(context, terms, context.op.Text, Value.Type.Number); + return CheckOperation(context, terms, context.op.Text, Value.Type.Number); } - public override Value.Type VisitExpComparison(YarnSpinnerParser.ExpComparisonContext context) { + public override Value.Type VisitExpComparison(YarnSpinnerParser.ExpComparisonContext context) + { ParserRuleContext[] terms = context.expression(); // <, <=, >, >= all support numbers only @@ -314,32 +349,35 @@ public override Value.Type VisitExpComparison(YarnSpinnerParser.ExpComparisonCon return Value.Type.Bool; } - public override Value.Type VisitExpEquality(YarnSpinnerParser.ExpEqualityContext context) { + public override Value.Type VisitExpEquality(YarnSpinnerParser.ExpEqualityContext context) + { ParserRuleContext[] terms = context.expression(); - // == and != support any defined type, as long as terms are - // the same type + // == and != support any defined type, as long as terms are the + // same type CheckOperation(context, terms, context.op.Text, Value.Type.Number, Value.Type.String, Value.Type.Bool); // Equality checks always return bool return Value.Type.Bool; } - public override Value.Type VisitExpNegative(YarnSpinnerParser.ExpNegativeContext context) { - ParserRuleContext[] terms = new[] {context.expression()}; + public override Value.Type VisitExpNegative(YarnSpinnerParser.ExpNegativeContext context) + { + ParserRuleContext[] terms = new[] { context.expression() }; // - supports only number types return CheckOperation(context, terms, "-", Value.Type.Number); } - public override Value.Type VisitExpNot(YarnSpinnerParser.ExpNotContext context) { - ParserRuleContext[] terms = new[] {context.expression()}; + public override Value.Type VisitExpNot(YarnSpinnerParser.ExpNotContext context) + { + ParserRuleContext[] terms = new[] { context.expression() }; // ! supports only bool types return CheckOperation(context, terms, "!", Value.Type.Bool); } - - } + + } } diff --git a/YarnSpinner.Compiler/VariableDeclarationVisitor.cs b/YarnSpinner.Compiler/VariableDeclarationVisitor.cs index e96103ae3..1ebee657c 100644 --- a/YarnSpinner.Compiler/VariableDeclarationVisitor.cs +++ b/YarnSpinner.Compiler/VariableDeclarationVisitor.cs @@ -4,9 +4,18 @@ namespace Yarn.Compiler using System.Collections.Generic; using Antlr4.Runtime; - internal class VariableDeclarationVisitor : YarnSpinnerParserBaseVisitor { + internal class VariableDeclarationVisitor : YarnSpinnerParserBaseVisitor + { + // The collection of variable declarations we know about before + // starting our work private IEnumerable ExistingVariableDeclarations; + + /// + /// The collection of new variable declarations that were found as + /// a result of using this + /// to visit a . + /// public ICollection NewVariableDeclarations { get; private set; } private IEnumerable AllDeclarations @@ -30,13 +39,17 @@ public VariableDeclarationVisitor(IEnumerable existingDecla this.NewVariableDeclarations = new List(); } - public override int VisitDeclare_statement(YarnSpinnerParser.Declare_statementContext context) { + public override int VisitDeclare_statement(YarnSpinnerParser.Declare_statementContext context) + { + // Get the name of the variable we're declaring string variableName = context.variable().GetText(); - + // Does this variable name already exist in our declarations? - foreach (var decl in AllDeclarations) { - if (decl.name == variableName) { + foreach (var decl in AllDeclarations) + { + if (decl.name == variableName) + { throw new TypeException($"{decl.name} has already been declared"); } } @@ -44,16 +57,19 @@ public override int VisitDeclare_statement(YarnSpinnerParser.Declare_statementCo // Figure out the type of the value var expressionVisitor = new ExpressionTypeVisitor(null, null, true); var type = expressionVisitor.Visit(context.value()); - + // Figure out the value itself var constantValueVisitor = new ConstantValueVisitor(); var value = constantValueVisitor.Visit(context.value()); // Do we have an explicit type declaration? - if (context.type() != null) { + if (context.type() != null) + { Value.Type explicitType; + // Get its type - switch (context.type().typename.Type) { + switch (context.type().typename.Type) + { case YarnSpinnerLexer.TYPE_STRING: explicitType = Value.Type.String; break; @@ -67,17 +83,23 @@ public override int VisitDeclare_statement(YarnSpinnerParser.Declare_statementCo throw new ParseException(context, $"Unknown type {context.type().GetText()}"); } - if (explicitType != type) { + // Check that it matches - if it doesn't, that's a type + // error + if (explicitType != type) + { throw new TypeException(context, $"Type {context.type().GetText()} does not match value {context.value().GetText()} ({type})"); } } + // Get the variable declaration, if we have one string description = null; - if (context.Description != null) { + if (context.Description != null) + { description = context.Description.Text.Trim('"'); } + // We're done creating the declaration! var declaration = new VariableDeclaration { name = variableName, diff --git a/YarnSpinner.Tests/TypeTests.cs b/YarnSpinner.Tests/TypeTests.cs index eb345d4fa..aab2f468b 100644 --- a/YarnSpinner.Tests/TypeTests.cs +++ b/YarnSpinner.Tests/TypeTests.cs @@ -13,13 +13,15 @@ namespace YarnSpinner.Tests { - public class TypeTests : TestBase + public class TypeTests : TestBase { - public TypeTests() : base() { + public TypeTests() : base() + { } [Fact] - void TestVariableDeclarationsParsed() { + void TestVariableDeclarationsParsed() + { var source = CreateTestNode(@" <> <> @@ -53,12 +55,12 @@ void TestVariableDeclarationsParsed() { name = "$bool", type = Value.Type.Bool, defaultValue = new Value(true) - }, + }, }; Assert.Equal(expectedDeclarations, result.Declarations); - + } [Fact] @@ -76,11 +78,12 @@ public void TestDeclarationsCanAppearInOtherFiles() <> ", "NodeB"); - var compilationJob = new CompilationJob { + var compilationJob = new CompilationJob + { Files = new[] { new CompilationJob.File { FileName = "sourceA", Source = sourceA }, new CompilationJob.File { FileName = "sourceB", Source = sourceB }, - }, + }, }; Compiler.Compile(compilationJob); @@ -114,13 +117,15 @@ public void TestImportingVariableDeclarations() } [Fact] - void TestVariableDeclarationsDisallowDuplicates() { + void TestVariableDeclarationsDisallowDuplicates() + { var source = CreateTestNode(@" <> <> // redeclaration "); - var ex = Assert.Throws(() => { + var ex = Assert.Throws(() => + { Compiler.Compile(CompilationJob.CreateFromString("input", source)); }); @@ -128,7 +133,8 @@ void TestVariableDeclarationsDisallowDuplicates() { } [Fact] - public void TestExpressionsDisallowMismatchedTypes() { + public void TestExpressionsDisallowMismatchedTypes() + { var source = CreateTestNode(@" <> <> // error, can't assign string to a variable declared int @@ -140,13 +146,14 @@ public void TestExpressionsDisallowMismatchedTypes() { }); Assert.Contains("$int (Number) cannot be assigned a String", ex.Message); - + } [Theory] [InlineData(@"<>")] // in commands [InlineData(@"{$str}")] // in inline expressions - public void TestExpressionsDisallowUsingUndeclaredVariables(string testSource) { + public void TestExpressionsDisallowUsingUndeclaredVariables(string testSource) + { var source = CreateTestNode($@" {testSource} // error, undeclared "); @@ -160,7 +167,8 @@ public void TestExpressionsDisallowUsingUndeclaredVariables(string testSource) { } [Fact] - public void TestExpressionsRequireCompatibleTypes() { + public void TestExpressionsRequireCompatibleTypes() + { var source = CreateTestNode(@" <> <> @@ -208,7 +216,8 @@ public void TestNullNotAllowed() <> // error, null not allowed "); - var ex = Assert.Throws( () => { + var ex = Assert.Throws(() => + { Compiler.Compile(CompilationJob.CreateFromString("input", source)); }); @@ -248,20 +257,25 @@ public void TestOperatorsAreTypeChecked([CombinatorialValues( "-= 1", "/= 1", "*= 1" - )] string operation, bool declared ) { + )] string operation, bool declared) + { string source = CreateTestNode($@" {(declared ? "<>" : "")} <> "); - if (!declared) { - var ex = Assert.Throws(() => { + if (!declared) + { + var ex = Assert.Throws(() => + { Compiler.Compile(CompilationJob.CreateFromString("input", source, dialogue.library)); }); Assert.Contains("Undeclared variable $var", ex.Message); - } else { + } + else + { Compiler.Compile(CompilationJob.CreateFromString("input", source, dialogue.library)); } } @@ -280,7 +294,7 @@ public void TestFailingFunctionSignatures(string source, string expectedExceptio dialogue.library.RegisterFunction("func_int_bool", (int i) => true); dialogue.library.RegisterFunction("func_int_int_bool", (int i, int j) => true); dialogue.library.RegisterFunction("func_string_string_bool", (string i, string j) => true); - dialogue.library.RegisterFunction("func_invalid_return", () => new List{1,2,3}); + dialogue.library.RegisterFunction("func_invalid_return", () => new List { 1, 2, 3 }); dialogue.library.RegisterFunction("func_invalid_param", (List i) => true); var failingSource = CreateTestNode($@" @@ -289,11 +303,12 @@ public void TestFailingFunctionSignatures(string source, string expectedExceptio {source} "); - var ex = Assert.Throws(() => { + var ex = Assert.Throws(() => + { Compiler.Compile(CompilationJob.CreateFromString("input", failingSource, dialogue.library)); }); - Assert.Matches(expectedExceptionMessage, ex.Message); + Assert.Matches(expectedExceptionMessage, ex.Message); } [Fact] @@ -354,7 +369,7 @@ public void TestInitialValues() stringTable = result.StringTable; RunStandardTestcase(); - + } [Fact] @@ -366,7 +381,7 @@ public void TestExplicitTypes() <> "); - Compiler.Compile(CompilationJob.CreateFromString("input", source, dialogue.library)); + Compiler.Compile(CompilationJob.CreateFromString("input", source, dialogue.library)); } [Theory] @@ -377,8 +392,9 @@ public void TestExplicitTypesMustMatchValue(string test) { var source = CreateTestNode(test); - Assert.Throws(() => { - var result = Compiler.Compile(CompilationJob.CreateFromString("input", source, dialogue.library)); + Assert.Throws(() => + { + var result = Compiler.Compile(CompilationJob.CreateFromString("input", source, dialogue.library)); }); } @@ -412,7 +428,7 @@ public void TestVariableDeclarationAnnotations() defaultValue = new Value(true), description = "a bool", - }, + }, }; Assert.Equal(expectedDeclarations, result.Declarations);