From d02eca487fb32d157267b2dfda7520e958856a1e Mon Sep 17 00:00:00 2001 From: Jesse McGrew Date: Sun, 11 Oct 2020 05:03:40 -0700 Subject: [PATCH] Update to .NET Core 3.0 and add nullability annotations. --- .../ErrorExceptionUsageTests.cs | 2 +- .../Helpers/CodeFixVerifier.Helper.cs | 8 +- .../Helpers/DiagnosticResult.cs | 2 +- .../Helpers/DiagnosticVerifier.Helper.cs | 16 +- .../ZilfAnalyzers.Test/Helpers/DiffHelper.cs | 2 +- .../MessageConstantTests.cs | 2 +- .../Verifiers/CodeFixVerifier.cs | 6 +- .../Verifiers/DiagnosticVerifier.cs | 18 +- .../ZilfAnalyzers.Test/ZilObjectTests.cs | 2 +- .../ZilfAnalyzers.Test.csproj | 8 +- src/Analyzers/ZilfAnalyzers/.editorconfig | 7 + .../ErrorExceptionUsageAnalyzer.cs | 2 + .../ZilfAnalyzers/MessageConstantAnalyzer.cs | 2 + .../ZilfAnalyzers/ZilObjectAnalyzer.cs | 5 +- .../ZilfAnalyzers/ZilfAnalyzers.csproj | 2 +- src/Dezapf/Dezapf.csproj | 4 +- src/Zapf.Parsing/.editorconfig | 7 + .../Diagnostics/AssemblerError.cs | 7 +- src/Zapf.Parsing/Diagnostics/Errors.cs | 45 +- src/Zapf.Parsing/Diagnostics/FatalError.cs | 2 +- src/Zapf.Parsing/Diagnostics/ISourceLine.cs | 3 +- src/Zapf.Parsing/Diagnostics/SeriousError.cs | 2 +- src/Zapf.Parsing/Diagnostics/Warning.cs | 2 +- src/Zapf.Parsing/Directives/AlignDirective.cs | 3 +- src/Zapf.Parsing/Directives/AsmLine.cs | 2 +- src/Zapf.Parsing/Directives/BareSymbolLine.cs | 3 +- .../Directives/ChrsetDirective.cs | 4 +- src/Zapf.Parsing/Directives/DataDirective.cs | 1 - .../Directives/DebugActionDirective.cs | 2 +- .../Directives/DebugArrayDirective.cs | 2 +- .../Directives/DebugAttrDirective.cs | 2 +- .../Directives/DebugClassDirective.cs | 14 +- .../Directives/DebugFakeActionDirective.cs | 5 +- .../Directives/DebugFileDirective.cs | 5 +- .../Directives/DebugGlobalDirective.cs | 2 +- .../Directives/DebugLineDirective.cs | 2 +- .../Directives/DebugMapDirective.cs | 6 +- .../Directives/DebugObjectDirective.cs | 14 +- .../Directives/DebugPropDirective.cs | 2 +- .../Directives/DebugRoutineDirective.cs | 7 +- .../Directives/DebugRoutineEndDirective.cs | 2 +- .../Directives/EqualsDirective.cs | 4 +- src/Zapf.Parsing/Directives/FstrDirective.cs | 2 +- src/Zapf.Parsing/Directives/FunctDirective.cs | 3 +- src/Zapf.Parsing/Directives/FunctLocal.cs | 6 +- src/Zapf.Parsing/Directives/GstrDirective.cs | 2 +- src/Zapf.Parsing/Directives/GvarDirective.cs | 5 +- .../Directives/InsertDirective.cs | 3 +- src/Zapf.Parsing/Directives/LangDirective.cs | 4 +- src/Zapf.Parsing/Directives/LenDirective.cs | 2 +- .../Directives/LineDebugDirective.cs | 5 +- .../Directives/NameAndTextDirective.cs | 4 +- src/Zapf.Parsing/Directives/NamedDirective.cs | 3 +- src/Zapf.Parsing/Directives/NewDirective.cs | 5 +- .../Directives/NumberAndNameDebugDirective.cs | 7 +- .../Directives/ObjectDirective.cs | 17 +- src/Zapf.Parsing/Directives/PropDirective.cs | 4 +- src/Zapf.Parsing/Directives/StrDirective.cs | 2 +- src/Zapf.Parsing/Directives/StrlDirective.cs | 2 +- src/Zapf.Parsing/Directives/TableDirective.cs | 5 +- src/Zapf.Parsing/Directives/TextDirective.cs | 3 +- .../Directives/VocbegDirective.cs | 4 +- src/Zapf.Parsing/Directives/ZwordDirective.cs | 2 +- src/Zapf.Parsing/Expressions/AdditionExpr.cs | 4 +- src/Zapf.Parsing/Expressions/AsmExpr.cs | 2 +- .../Expressions/NumericLiteral.cs | 2 +- src/Zapf.Parsing/Expressions/QuoteExpr.cs | 3 +- src/Zapf.Parsing/Expressions/StringLiteral.cs | 2 +- src/Zapf.Parsing/Expressions/SymbolExpr.cs | 2 +- src/Zapf.Parsing/Expressions/TextAsmExpr.cs | 3 +- src/Zapf.Parsing/GlobalLabel.cs | 3 +- src/Zapf.Parsing/Instructions/Instruction.cs | 31 +- src/Zapf.Parsing/Instructions/LocalLabel.cs | 3 +- src/Zapf.Parsing/Instructions/ZOpAttribute.cs | 7 +- src/Zapf.Parsing/ParseResult.cs | 2 - src/Zapf.Parsing/Token.cs | 2 +- src/Zapf.Parsing/Tokenizer.cs | 21 +- src/Zapf.Parsing/ZapParser.cs | 272 +++++---- src/Zapf.Parsing/Zapf.Parsing.csproj | 3 +- src/Zapf/.editorconfig | 4 + src/Zapf/AbbrevFinder.cs | 6 +- src/Zapf/BinaryDebugFileWriter.cs | 26 +- src/Zapf/Context.cs | 115 ++-- src/Zapf/IDebugFileWriter.cs | 25 +- src/Zapf/Program.cs | 134 +++-- src/Zapf/XmlDebugFileWriter.cs | 10 +- src/Zapf/Zapf.csproj | 4 +- src/Zapf/ZapfAssembler.cs | 31 +- src/Zilf.Common/StringEncoding/Horspool.cs | 2 +- src/Zilf.Common/UnhandledCaseException.cs | 15 +- src/Zilf.Common/UnreachableCodeException.cs | 15 +- src/Zilf.Common/Zilf.Common.csproj | 3 +- src/Zilf.Emit/.editorconfig | 4 + src/Zilf.Emit/IConstantOperand.cs | 2 +- src/Zilf.Emit/IDebugFileBuilder.cs | 8 +- src/Zilf.Emit/IGameBuilder.cs | 42 +- src/Zilf.Emit/IGlobalBuilder.cs | 3 +- src/Zilf.Emit/IIndirectOperand.cs | 1 - src/Zilf.Emit/ILocalBuilder.cs | 5 +- src/Zilf.Emit/IObjectBuilder.cs | 18 +- src/Zilf.Emit/IPropertyBuilder.cs | 3 +- src/Zilf.Emit/IRoutineBuilder.cs | 94 ++- src/Zilf.Emit/ITableBuilder.cs | 6 +- src/Zilf.Emit/IVariable.cs | 1 - src/Zilf.Emit/Peephole.cs | 93 ++- src/Zilf.Emit/Zap/DebugFileBuilder.cs | 2 +- src/Zilf.Emit/Zap/GameBuilder.cs | 59 +- src/Zilf.Emit/Zap/GameOptions.cs | 8 +- src/Zilf.Emit/Zap/GlobalBuilder.cs | 5 +- src/Zilf.Emit/Zap/IZapStreamFactory.cs | 16 +- src/Zilf.Emit/Zap/IndirectOperand.cs | 2 +- src/Zilf.Emit/Zap/LocalBuilder.cs | 17 +- src/Zilf.Emit/Zap/NumericConstantOperand.cs | 3 +- src/Zilf.Emit/Zap/ObjectBuilder.cs | 12 +- src/Zilf.Emit/Zap/OperandExtensions.cs | 14 +- src/Zilf.Emit/Zap/PropertyBuilder.cs | 5 +- src/Zilf.Emit/Zap/RoutineBuilder.cs | 490 ++++++---------- src/Zilf.Emit/Zap/SumOperand.cs | 4 +- src/Zilf.Emit/Zap/TableBuilder.cs | 5 +- src/Zilf.Emit/Zap/WordBuilder.cs | 3 +- src/Zilf.Emit/Zap/ZapCode.cs | 7 +- src/Zilf.Emit/Zilf.Emit.csproj | 7 +- src/Zilf/.editorconfig | 16 + src/Zilf/Compiler/Action.cs | 10 +- src/Zilf/Compiler/Block.cs | 8 +- src/Zilf/Compiler/Builtins/BuiltinArg.cs | 4 +- .../Compiler/Builtins/BuiltinAttribute.cs | 6 +- src/Zilf/Compiler/Builtins/BuiltinSpec.cs | 22 +- .../Compiler/Builtins/ParameterTypeHandler.cs | 46 +- src/Zilf/Compiler/Builtins/PredCall.cs | 6 +- src/Zilf/Compiler/Builtins/ValueCall.cs | 7 +- src/Zilf/Compiler/Builtins/ValuePredCall.cs | 14 +- .../Compiler/Builtins/VariableAttribute.cs | 2 +- .../{QuirksMode.cs => VariableScopeQuirks.cs} | 4 +- src/Zilf/Compiler/Builtins/VoidCall.cs | 5 +- src/Zilf/Compiler/Builtins/ZBuiltins.cs | 522 ++++++++--------- src/Zilf/Compiler/Compilation.Compile.cs | 106 ++-- src/Zilf/Compiler/Compilation.Conditions.cs | 67 ++- src/Zilf/Compiler/Compilation.Expressions.cs | 44 +- src/Zilf/Compiler/Compilation.Globals.cs | 121 ++-- src/Zilf/Compiler/Compilation.Loops.cs | 235 ++++---- src/Zilf/Compiler/Compilation.Objects.cs | 61 +- src/Zilf/Compiler/Compilation.Operands.cs | 12 +- src/Zilf/Compiler/Compilation.Routines.cs | 36 +- src/Zilf/Compiler/Compilation.Strings.cs | 37 +- src/Zilf/Compiler/Compilation.Syntax.cs | 48 +- src/Zilf/Compiler/Compilation.Tables.cs | 35 +- src/Zilf/Compiler/Compilation.cs | 24 +- src/Zilf/Compiler/CompilationExtensions.cs | 24 +- src/Zilf/Compiler/FrontEnd.cs | 46 +- src/Zilf/Compiler/LocalBindingRecord.cs | 10 +- src/Zilf/Compiler/VariableRef.cs | 10 +- src/Zilf/Completer.cs | 41 +- src/Zilf/Diagnostics/ArgCountHelpers.cs | 14 +- .../Diagnostics/DefaultDiagnosticFormatter.cs | 1 + src/Zilf/Diagnostics/Diagnostic.cs | 68 +-- src/Zilf/Diagnostics/DiagnosticContext.cs | 25 +- src/Zilf/Diagnostics/DiagnosticManager.cs | 18 +- src/Zilf/Diagnostics/IDiagnosticFormatter.cs | 3 +- src/Zilf/Diagnostics/InterpreterMessages.cs | 1 + src/Zilf/Interpreter/ApplicableExtensions.cs | 47 +- src/Zilf/Interpreter/ArgDecoder.cs | 371 +++++++----- src/Zilf/Interpreter/ArgItem.cs | 4 +- src/Zilf/Interpreter/ArgSpec.cs | 216 ++++--- src/Zilf/Interpreter/AssociationTable.cs | 5 +- src/Zilf/Interpreter/Binding.cs | 6 +- src/Zilf/Interpreter/CallFrame.cs | 7 +- src/Zilf/Interpreter/Context.cs | 546 +++++++----------- src/Zilf/Interpreter/FileContext.cs | 4 +- src/Zilf/Interpreter/Frame.cs | 9 +- src/Zilf/Interpreter/IApplicable.cs | 4 +- src/Zilf/Interpreter/IMayExpand.cs | 5 +- src/Zilf/Interpreter/IStructure.cs | 23 +- src/Zilf/Interpreter/LocalEnvironment.cs | 24 +- src/Zilf/Interpreter/NativeFrame.cs | 4 +- src/Zilf/Interpreter/ObList.cs | 46 +- src/Zilf/Interpreter/Recursion.cs | 4 +- src/Zilf/Interpreter/StructureExtensions.cs | 110 +--- src/Zilf/Interpreter/Subrs.Atoms.cs | 193 +++---- src/Zilf/Interpreter/Subrs.Conditionals.cs | 26 +- src/Zilf/Interpreter/Subrs.DefStruct.cs | 220 +++---- src/Zilf/Interpreter/Subrs.Functions.cs | 46 +- src/Zilf/Interpreter/Subrs.Loops.cs | 48 +- src/Zilf/Interpreter/Subrs.Map.cs | 39 +- src/Zilf/Interpreter/Subrs.Math.cs | 83 +-- src/Zilf/Interpreter/Subrs.Meta.cs | 64 +- src/Zilf/Interpreter/Subrs.Output.cs | 66 +-- src/Zilf/Interpreter/Subrs.Packages.cs | 41 +- src/Zilf/Interpreter/Subrs.Structures.cs | 170 +++--- src/Zilf/Interpreter/Subrs.Types.cs | 88 +-- src/Zilf/Interpreter/Subrs.ZModel.cs | 268 ++++----- src/Zilf/Interpreter/Subrs.cs | 16 +- .../Interpreter/Values/Tied/TiedLayout.cs | 10 +- .../Values/Tied/ZilTiedListBase.cs | 45 +- src/Zilf/Interpreter/Values/ZilActivation.cs | 6 +- src/Zilf/Interpreter/Values/ZilAdecl.cs | 96 +-- src/Zilf/Interpreter/Values/ZilAsoc.cs | 11 +- src/Zilf/Interpreter/Values/ZilAtom.cs | 22 +- src/Zilf/Interpreter/Values/ZilChannel.cs | 109 ++-- src/Zilf/Interpreter/Values/ZilChar.cs | 10 +- src/Zilf/Interpreter/Values/ZilDecl.cs | 10 +- src/Zilf/Interpreter/Values/ZilEnvironment.cs | 11 +- src/Zilf/Interpreter/Values/ZilEvalMacro.cs | 21 +- src/Zilf/Interpreter/Values/ZilFSubr.cs | 9 +- src/Zilf/Interpreter/Values/ZilFalse.cs | 2 +- src/Zilf/Interpreter/Values/ZilFix.cs | 12 +- src/Zilf/Interpreter/Values/ZilForm.cs | 64 +- src/Zilf/Interpreter/Values/ZilFunction.cs | 66 +-- src/Zilf/Interpreter/Values/ZilHashBase.cs | 16 +- src/Zilf/Interpreter/Values/ZilLink.cs | 9 +- src/Zilf/Interpreter/Values/ZilList.cs | 11 +- src/Zilf/Interpreter/Values/ZilListBase.cs | 117 ++-- src/Zilf/Interpreter/Values/ZilListoidBase.cs | 36 +- src/Zilf/Interpreter/Values/ZilMacroResult.cs | 27 +- src/Zilf/Interpreter/Values/ZilObject.cs | 60 +- src/Zilf/Interpreter/Values/ZilOffset.cs | 94 ++- src/Zilf/Interpreter/Values/ZilSegment.cs | 23 +- src/Zilf/Interpreter/Values/ZilSplice.cs | 2 +- src/Zilf/Interpreter/Values/ZilString.cs | 68 +-- .../Interpreter/Values/ZilStructuredHash.cs | 10 +- src/Zilf/Interpreter/Values/ZilSubr.cs | 14 +- src/Zilf/Interpreter/Values/ZilVector.cs | 63 +- src/Zilf/Interpreter/WeakCountingSet.cs | 36 +- src/Zilf/Interpreter/ZilResult.cs | 83 +-- src/Zilf/Language/AtomAttribute.cs | 3 +- src/Zilf/Language/CompilerError.cs | 39 +- src/Zilf/Language/CompilerFatal.cs | 26 +- src/Zilf/Language/Decl.cs | 131 +++-- src/Zilf/Language/FileSourceLine.cs | 3 +- src/Zilf/Language/IProvideSourceLine.cs | 2 +- src/Zilf/Language/InterpreterError.cs | 48 +- src/Zilf/Language/Parser.cs | 103 ++-- src/Zilf/Language/Signatures/AdeclPart.cs | 4 +- .../Language/Signatures/AlternativesPart.cs | 7 +- src/Zilf/Language/Signatures/AnyPart.cs | 2 +- .../Language/Signatures/ConstrainedPart.cs | 6 +- src/Zilf/Language/Signatures/Constraint.cs | 44 +- src/Zilf/Language/Signatures/FormPart.cs | 5 +- .../Language/Signatures/ISignaturePart.cs | 8 +- .../Language/Signatures/ISignatureVisitor.cs | 22 +- src/Zilf/Language/Signatures/JsonDescriber.cs | 59 +- src/Zilf/Language/Signatures/ListPart.cs | 5 +- src/Zilf/Language/Signatures/LiteralPart.cs | 6 +- src/Zilf/Language/Signatures/OptionalPart.cs | 6 +- .../Language/Signatures/PlainDescriber.cs | 16 +- src/Zilf/Language/Signatures/QuotedPart.cs | 6 +- src/Zilf/Language/Signatures/SequencePart.cs | 7 +- .../Language/Signatures/SignatureBuilder.cs | 54 +- src/Zilf/Language/Signatures/SignaturePart.cs | 9 +- src/Zilf/Language/Signatures/StructurePart.cs | 4 +- .../Signatures/SubrSignature.Builder.cs | 90 ++- src/Zilf/Language/Signatures/SubrSignature.cs | 4 +- src/Zilf/Language/Signatures/VarArgsPart.cs | 8 +- .../Language/Signatures/ZBuiltinSignature.cs | 11 +- src/Zilf/Language/SourceLines.cs | 4 - src/Zilf/Language/SyntaxError.cs | 39 -- src/Zilf/Language/ZilError.cs | 89 ++- src/Zilf/Program.cs | 83 ++- src/Zilf/ZModel/AtomNameEqualityComparer.cs | 2 +- src/Zilf/ZModel/Language.cs | 8 +- src/Zilf/ZModel/LowCoreField.cs | 3 +- src/Zilf/ZModel/Syntax.cs | 66 +-- src/Zilf/ZModel/TellTokens.cs | 44 +- src/Zilf/ZModel/Values/ComplexPropDef.cs | 194 ++++--- src/Zilf/ZModel/Values/ZilConstant.cs | 9 +- src/Zilf/ZModel/Values/ZilGlobal.cs | 11 +- src/Zilf/ZModel/Values/ZilModelObject.cs | 11 +- src/Zilf/ZModel/Values/ZilRoutine.cs | 23 +- src/Zilf/ZModel/Values/ZilTable.cs | 190 +++--- src/Zilf/ZModel/Values/ZilWord.cs | 5 +- src/Zilf/ZModel/Vocab/AdjSynonym.cs | 2 +- src/Zilf/ZModel/Vocab/DirSynonym.cs | 2 +- src/Zilf/ZModel/Vocab/IVocabFormat.cs | 114 ++-- src/Zilf/ZModel/Vocab/IWord.cs | 1 - .../Vocab/NewParser/NewParserVocabFormat.cs | 65 ++- .../ZModel/Vocab/NewParser/NewParserWord.cs | 7 +- .../Vocab/OldParser/OldParserVocabFormat.cs | 20 +- .../ZModel/Vocab/OldParser/OldParserWord.cs | 33 +- src/Zilf/ZModel/Vocab/PrepSynonym.cs | 2 +- src/Zilf/ZModel/Vocab/ScopeFlags.cs | 8 +- src/Zilf/ZModel/Vocab/Synonym.cs | 6 +- src/Zilf/ZModel/Vocab/VerbSynonym.cs | 2 +- src/Zilf/ZModel/ZEnvironment.cs | 260 ++++----- src/Zilf/Zilf.csproj | 10 +- test/Dezapf.Tests/Dezapf.Tests.csproj | 10 +- test/Zapf.Tests/HeaderTests.cs | 2 +- test/Zapf.Tests/LabelConvergenceTests.cs | 6 +- test/Zapf.Tests/TestHelper.cs | 14 +- test/Zapf.Tests/VocabTests.cs | 4 +- test/Zapf.Tests/Zapf.Tests.csproj | 8 +- test/Zilf.Emit.Tests/Zilf.Emit.Tests.csproj | 10 +- .../Zilf.Tests.Integration/AssertionHelper.cs | 108 ++-- .../FullProjectTests.cs | 16 +- .../IntegrationTestClass.cs | 24 +- test/Zilf.Tests.Integration/OpcodeTests.cs | 24 +- test/Zilf.Tests.Integration/TestCaseIO.cs | 12 +- test/Zilf.Tests.Integration/VocabTests.cs | 4 +- .../Zilf.Tests.Integration.csproj | 8 +- test/Zilf.Tests.Integration/ZlrHelper.cs | 26 +- test/Zilf.Tests/.editorconfig | 7 + test/Zilf.Tests/Compiler/PathTests.cs | 8 +- .../Zilf.Tests/Interpreter/ArgDecoderTests.cs | 6 +- .../Interpreter/OldParserWordTests.cs | 4 +- test/Zilf.Tests/Interpreter/OutputTests.cs | 4 +- test/Zilf.Tests/Interpreter/ParserTests.cs | 4 +- test/Zilf.Tests/Interpreter/SyntaxTests.cs | 4 +- test/Zilf.Tests/Interpreter/TestHelpers.cs | 20 +- test/Zilf.Tests/Interpreter/TypeTests.cs | 2 +- test/Zilf.Tests/Zilf.Tests.csproj | 9 +- 309 files changed, 4552 insertions(+), 5597 deletions(-) create mode 100644 src/Analyzers/ZilfAnalyzers/.editorconfig create mode 100644 src/Zapf.Parsing/.editorconfig create mode 100644 src/Zapf/.editorconfig create mode 100644 src/Zilf.Emit/.editorconfig create mode 100644 src/Zilf/.editorconfig rename src/Zilf/Compiler/Builtins/{QuirksMode.cs => VariableScopeQuirks.cs} (89%) delete mode 100644 src/Zilf/Language/SyntaxError.cs create mode 100644 test/Zilf.Tests/.editorconfig diff --git a/src/Analyzers/ZilfAnalyzers.Test/ErrorExceptionUsageTests.cs b/src/Analyzers/ZilfAnalyzers.Test/ErrorExceptionUsageTests.cs index b42cca6..cb19edc 100644 --- a/src/Analyzers/ZilfAnalyzers.Test/ErrorExceptionUsageTests.cs +++ b/src/Analyzers/ZilfAnalyzers.Test/ErrorExceptionUsageTests.cs @@ -183,7 +183,7 @@ class Program { throw new System.NotImplementedException(); } - [NotNull] + [JetBrains.Annotations.NotNull] protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer() { return new ErrorExceptionUsageAnalyzer(); diff --git a/src/Analyzers/ZilfAnalyzers.Test/Helpers/CodeFixVerifier.Helper.cs b/src/Analyzers/ZilfAnalyzers.Test/Helpers/CodeFixVerifier.Helper.cs index f1ceb52..1433cf0 100644 --- a/src/Analyzers/ZilfAnalyzers.Test/Helpers/CodeFixVerifier.Helper.cs +++ b/src/Analyzers/ZilfAnalyzers.Test/Helpers/CodeFixVerifier.Helper.cs @@ -24,7 +24,7 @@ namespace ZilfAnalyzers.Test.Helpers /// The Document to apply the fix on /// A CodeAction that will be applied to the Document. /// A Document with the changes from the CodeAction - static Document ApplyFix([NotNull] Document document, [NotNull] CodeAction codeAction) + static Document ApplyFix([JetBrains.Annotations.NotNull] Document document, [JetBrains.Annotations.NotNull] CodeAction codeAction) { var operations = codeAction.GetOperationsAsync(CancellationToken.None).Result; var solution = operations.OfType().Single().ChangedSolution; @@ -39,7 +39,7 @@ namespace ZilfAnalyzers.Test.Helpers /// The Diagnostics that existed in the code before the CodeFix was applied /// The Diagnostics that exist in the code after the CodeFix was applied /// A list of Diagnostics that only surfaced in the code after the CodeFix was applied - static IEnumerable GetNewDiagnostics([NotNull] [InstantHandle] IEnumerable diagnostics, [NotNull] [InstantHandle] IEnumerable newDiagnostics) + static IEnumerable GetNewDiagnostics([JetBrains.Annotations.NotNull] [InstantHandle] IEnumerable diagnostics, [JetBrains.Annotations.NotNull] [InstantHandle] IEnumerable newDiagnostics) { var oldArray = diagnostics.OrderBy(d => d.Location.SourceSpan.Start).ToArray(); var newArray = newDiagnostics.OrderBy(d => d.Location.SourceSpan.Start).ToArray(); @@ -66,7 +66,7 @@ namespace ZilfAnalyzers.Test.Helpers /// /// The Document to run the compiler diagnostic analyzers on /// The compiler diagnostics that were found in the code - static ImmutableArray GetCompilerDiagnostics([NotNull] Document document) + static ImmutableArray GetCompilerDiagnostics([JetBrains.Annotations.NotNull] Document document) { return document.GetSemanticModelAsync().Result.GetDiagnostics(); } @@ -76,7 +76,7 @@ namespace ZilfAnalyzers.Test.Helpers /// /// The Document to be converted to a string /// A string containing the syntax of the Document after formatting - [NotNull] + [JetBrains.Annotations.NotNull] static string GetStringFromDocument(Document document) { var simplifiedDoc = Simplifier.ReduceAsync(document, Simplifier.Annotation).Result; diff --git a/src/Analyzers/ZilfAnalyzers.Test/Helpers/DiagnosticResult.cs b/src/Analyzers/ZilfAnalyzers.Test/Helpers/DiagnosticResult.cs index f90a8f0..4bcae54 100644 --- a/src/Analyzers/ZilfAnalyzers.Test/Helpers/DiagnosticResult.cs +++ b/src/Analyzers/ZilfAnalyzers.Test/Helpers/DiagnosticResult.cs @@ -40,7 +40,7 @@ namespace ZilfAnalyzers.Test.Helpers { DiagnosticResultLocation[] locations; - [NotNull] + [JetBrains.Annotations.NotNull] public DiagnosticResultLocation[] Locations { get => locations ?? (locations = new DiagnosticResultLocation[] { }); diff --git a/src/Analyzers/ZilfAnalyzers.Test/Helpers/DiagnosticVerifier.Helper.cs b/src/Analyzers/ZilfAnalyzers.Test/Helpers/DiagnosticVerifier.Helper.cs index d140640..a2f50cb 100644 --- a/src/Analyzers/ZilfAnalyzers.Test/Helpers/DiagnosticVerifier.Helper.cs +++ b/src/Analyzers/ZilfAnalyzers.Test/Helpers/DiagnosticVerifier.Helper.cs @@ -24,7 +24,7 @@ namespace ZilfAnalyzers.Test.Helpers static readonly IReadOnlyCollection ProjectMetadataReferences = GetProjectMetadataReferences(); - [NotNull, ItemNotNull] + [JetBrains.Annotations.NotNull, ItemNotNull] private static IReadOnlyCollection GetProjectMetadataReferences() { var result = new List @@ -72,7 +72,7 @@ namespace ZilfAnalyzers.Test.Helpers /// The analyzer to be run on the sources /// An IEnumerable of Diagnostics that surfaced in the source code, sorted by Location [ItemNotNull] - private static async Task GetSortedDiagnosticsAsync([NotNull] string[] sources, [NotNull] string language, DiagnosticAnalyzer analyzer) + private static async Task GetSortedDiagnosticsAsync([JetBrains.Annotations.NotNull] string[] sources, [JetBrains.Annotations.NotNull] string language, DiagnosticAnalyzer analyzer) { return await GetSortedDiagnosticsFromDocumentsAsync(analyzer, GetDocuments(sources, language)).ConfigureAwait(false); } @@ -85,7 +85,7 @@ namespace ZilfAnalyzers.Test.Helpers /// The Documents that the analyzer will be run on /// An IEnumerable of Diagnostics that surfaced in the source code, sorted by Location [ItemNotNull] - protected static async Task GetSortedDiagnosticsFromDocumentsAsync(DiagnosticAnalyzer analyzer, [NotNull] Document[] documents) + protected static async Task GetSortedDiagnosticsFromDocumentsAsync(DiagnosticAnalyzer analyzer, [JetBrains.Annotations.NotNull] Document[] documents) { var projects = new HashSet(); foreach (var document in documents) @@ -137,8 +137,8 @@ namespace ZilfAnalyzers.Test.Helpers /// /// The list of Diagnostics to be sorted /// An IEnumerable containing the Diagnostics in order of Location - [NotNull] - static Diagnostic[] SortDiagnostics([NotNull] IEnumerable diagnostics) + [JetBrains.Annotations.NotNull] + static Diagnostic[] SortDiagnostics([JetBrains.Annotations.NotNull] IEnumerable diagnostics) { return diagnostics.OrderBy(d => d.Location.SourceSpan.Start).ToArray(); } @@ -152,8 +152,8 @@ namespace ZilfAnalyzers.Test.Helpers /// Classes in the form of strings /// The language the source code is in /// A Tuple containing the Documents produced from the sources and their TextSpans if relevant - [NotNull] - static Document[] GetDocuments([NotNull] string[] sources, [NotNull] string language) + [JetBrains.Annotations.NotNull] + static Document[] GetDocuments([JetBrains.Annotations.NotNull] string[] sources, [JetBrains.Annotations.NotNull] string language) { if (language != LanguageNames.CSharp && language != LanguageNames.VisualBasic) { @@ -188,7 +188,7 @@ namespace ZilfAnalyzers.Test.Helpers /// Classes in the form of strings /// The language the source code is in /// A Project created out of the Documents created from the source strings - static Project CreateProject([NotNull] string[] sources, string language = LanguageNames.CSharp) + static Project CreateProject([JetBrains.Annotations.NotNull] string[] sources, string language = LanguageNames.CSharp) { string fileNamePrefix = DefaultFilePathPrefix; string fileExt = language == LanguageNames.CSharp ? CSharpDefaultFileExt : VisualBasicDefaultExt; diff --git a/src/Analyzers/ZilfAnalyzers.Test/Helpers/DiffHelper.cs b/src/Analyzers/ZilfAnalyzers.Test/Helpers/DiffHelper.cs index e4abb3d..1a06009 100644 --- a/src/Analyzers/ZilfAnalyzers.Test/Helpers/DiffHelper.cs +++ b/src/Analyzers/ZilfAnalyzers.Test/Helpers/DiffHelper.cs @@ -53,7 +53,7 @@ namespace ZilfAnalyzers.Test.Helpers Assert.AreEqual(expectedValue, actualValue); } - [NotNull] + [JetBrains.Annotations.NotNull] static string ToSafeString(this char c) { switch (c) diff --git a/src/Analyzers/ZilfAnalyzers.Test/MessageConstantTests.cs b/src/Analyzers/ZilfAnalyzers.Test/MessageConstantTests.cs index 0d1ebfb..fe7584a 100644 --- a/src/Analyzers/ZilfAnalyzers.Test/MessageConstantTests.cs +++ b/src/Analyzers/ZilfAnalyzers.Test/MessageConstantTests.cs @@ -155,7 +155,7 @@ namespace Zilf.Diagnostics { await VerifyCSharpFixAsync(test, fixtest); } - [NotNull] + [JetBrains.Annotations.NotNull] protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer() { return new MessageConstantAnalyzer(); diff --git a/src/Analyzers/ZilfAnalyzers.Test/Verifiers/CodeFixVerifier.cs b/src/Analyzers/ZilfAnalyzers.Test/Verifiers/CodeFixVerifier.cs index 03ddfb7..8641113 100644 --- a/src/Analyzers/ZilfAnalyzers.Test/Verifiers/CodeFixVerifier.cs +++ b/src/Analyzers/ZilfAnalyzers.Test/Verifiers/CodeFixVerifier.cs @@ -23,14 +23,14 @@ namespace ZilfAnalyzers.Test.Helpers /// Returns the codefix being tested (C#) - to be implemented in non-abstract class /// /// The CodeFixProvider to be used for CSharp code - [NotNull] + [JetBrains.Annotations.NotNull] protected abstract CodeFixProvider GetCSharpCodeFixProvider(); /// /// Returns the codefix being tested (VB) - to be implemented in non-abstract class /// /// The CodeFixProvider to be used for VisualBasic code - [NotNull] + [JetBrains.Annotations.NotNull] protected abstract CodeFixProvider GetBasicCodeFixProvider(); /// @@ -70,7 +70,7 @@ namespace ZilfAnalyzers.Test.Helpers /// A class in the form of a string after the CodeFix was applied to it /// Index determining which codefix to apply if there are multiple /// A bool controlling whether or not the test will fail if the CodeFix introduces other warnings after being applied - static async Task VerifyFixAsync(string language, DiagnosticAnalyzer analyzer, [NotNull] CodeFixProvider codeFixProvider, string oldSource, string newSource, int? codeFixIndex, bool allowNewCompilerDiagnostics) + static async Task VerifyFixAsync(string language, DiagnosticAnalyzer analyzer, [JetBrains.Annotations.NotNull] CodeFixProvider codeFixProvider, string oldSource, string newSource, int? codeFixIndex, bool allowNewCompilerDiagnostics) { var document = CreateDocument(oldSource, language); var analyzerDiagnostics = await GetSortedDiagnosticsFromDocumentsAsync(analyzer, new[] { document }).ConfigureAwait(false); diff --git a/src/Analyzers/ZilfAnalyzers.Test/Verifiers/DiagnosticVerifier.cs b/src/Analyzers/ZilfAnalyzers.Test/Verifiers/DiagnosticVerifier.cs index d914f34..71653ad 100644 --- a/src/Analyzers/ZilfAnalyzers.Test/Verifiers/DiagnosticVerifier.cs +++ b/src/Analyzers/ZilfAnalyzers.Test/Verifiers/DiagnosticVerifier.cs @@ -38,7 +38,7 @@ namespace ZilfAnalyzers.Test.Helpers /// /// A class in the form of a string to run the analyzer on /// DiagnosticResults that should appear after the analyzer is run on the source - protected async Task VerifyCSharpDiagnosticAsync(string source, [NotNull] params DiagnosticResult[] expected) + protected async Task VerifyCSharpDiagnosticAsync(string source, [JetBrains.Annotations.NotNull] params DiagnosticResult[] expected) { await VerifyDiagnosticsAsync(new[] { source }, LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), expected); } @@ -49,7 +49,7 @@ namespace ZilfAnalyzers.Test.Helpers /// /// A class in the form of a string to run the analyzer on /// DiagnosticResults that should appear after the analyzer is run on the source - protected async Task VerifyBasicDiagnosticAsync(string source, [NotNull] params DiagnosticResult[] expected) + protected async Task VerifyBasicDiagnosticAsync(string source, [JetBrains.Annotations.NotNull] params DiagnosticResult[] expected) { await VerifyDiagnosticsAsync(new[] { source }, LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), expected); } @@ -60,7 +60,7 @@ namespace ZilfAnalyzers.Test.Helpers /// /// An array of strings to create source documents from to run the analyzers on /// DiagnosticResults that should appear after the analyzer is run on the sources - protected async Task VerifyCSharpDiagnosticAsync([NotNull] string[] sources, [NotNull] params DiagnosticResult[] expected) + protected async Task VerifyCSharpDiagnosticAsync([JetBrains.Annotations.NotNull] string[] sources, [JetBrains.Annotations.NotNull] params DiagnosticResult[] expected) { await VerifyDiagnosticsAsync(sources, LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), expected); } @@ -71,7 +71,7 @@ namespace ZilfAnalyzers.Test.Helpers /// /// An array of strings to create source documents from to run the analyzers on /// DiagnosticResults that should appear after the analyzer is run on the sources - protected async Task VerifyBasicDiagnosticAsync([NotNull] string[] sources, [NotNull] params DiagnosticResult[] expected) + protected async Task VerifyBasicDiagnosticAsync([JetBrains.Annotations.NotNull] string[] sources, [JetBrains.Annotations.NotNull] params DiagnosticResult[] expected) { await VerifyDiagnosticsAsync(sources, LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), expected); } @@ -84,7 +84,7 @@ namespace ZilfAnalyzers.Test.Helpers /// The language of the classes represented by the source strings /// The analyzer to be run on the source code /// DiagnosticResults that should appear after the analyzer is run on the sources - static async Task VerifyDiagnosticsAsync([NotNull] string[] sources, [NotNull] string language, DiagnosticAnalyzer analyzer, [NotNull] params DiagnosticResult[] expected) + static async Task VerifyDiagnosticsAsync([JetBrains.Annotations.NotNull] string[] sources, [JetBrains.Annotations.NotNull] string language, DiagnosticAnalyzer analyzer, [JetBrains.Annotations.NotNull] params DiagnosticResult[] expected) { var diagnostics = await GetSortedDiagnosticsAsync(sources, language, analyzer).ConfigureAwait(false); VerifyDiagnosticResults(diagnostics, analyzer, expected); @@ -100,7 +100,7 @@ namespace ZilfAnalyzers.Test.Helpers /// The Diagnostics found by the compiler after running the analyzer on the source code /// The analyzer that was being run on the sources /// Diagnostic Results that should have appeared in the code - static void VerifyDiagnosticResults([NotNull] IEnumerable actualResults, DiagnosticAnalyzer analyzer, [NotNull] params DiagnosticResult[] expectedResults) + static void VerifyDiagnosticResults([JetBrains.Annotations.NotNull] IEnumerable actualResults, DiagnosticAnalyzer analyzer, [JetBrains.Annotations.NotNull] params DiagnosticResult[] expectedResults) { var expectedCount = expectedResults.Length; var actualResultsArray = actualResults as Diagnostic[] ?? actualResults.ToArray(); @@ -172,7 +172,7 @@ namespace ZilfAnalyzers.Test.Helpers /// The diagnostic that was found in the code /// The Location of the Diagnostic found in the code /// The DiagnosticResultLocation that should have been found - static void VerifyDiagnosticLocation(DiagnosticAnalyzer analyzer, Diagnostic diagnostic, [NotNull] Location actual, DiagnosticResultLocation expected) + static void VerifyDiagnosticLocation(DiagnosticAnalyzer analyzer, Diagnostic diagnostic, [JetBrains.Annotations.NotNull] Location actual, DiagnosticResultLocation expected) { var actualSpan = actual.GetLineSpan(); @@ -213,8 +213,8 @@ namespace ZilfAnalyzers.Test.Helpers /// The analyzer that this verifier tests /// The Diagnostics to be formatted /// The Diagnostics formatted as a string - [NotNull] - static string FormatDiagnostics(DiagnosticAnalyzer analyzer, [NotNull] params Diagnostic[] diagnostics) + [JetBrains.Annotations.NotNull] + static string FormatDiagnostics(DiagnosticAnalyzer analyzer, [JetBrains.Annotations.NotNull] params Diagnostic[] diagnostics) { var builder = new StringBuilder(); for (int i = 0; i < diagnostics.Length; ++i) diff --git a/src/Analyzers/ZilfAnalyzers.Test/ZilObjectTests.cs b/src/Analyzers/ZilfAnalyzers.Test/ZilObjectTests.cs index e245e1f..1fb8275 100644 --- a/src/Analyzers/ZilfAnalyzers.Test/ZilObjectTests.cs +++ b/src/Analyzers/ZilfAnalyzers.Test/ZilObjectTests.cs @@ -208,7 +208,7 @@ namespace Zilf.Diagnostics { #endif } - [NotNull] + [JetBrains.Annotations.NotNull] protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer() { return new ZilObjectAnalyzer(); diff --git a/src/Analyzers/ZilfAnalyzers.Test/ZilfAnalyzers.Test.csproj b/src/Analyzers/ZilfAnalyzers.Test/ZilfAnalyzers.Test.csproj index 4b698c9..e51f90e 100644 --- a/src/Analyzers/ZilfAnalyzers.Test/ZilfAnalyzers.Test.csproj +++ b/src/Analyzers/ZilfAnalyzers.Test/ZilfAnalyzers.Test.csproj @@ -6,14 +6,14 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/src/Analyzers/ZilfAnalyzers/.editorconfig b/src/Analyzers/ZilfAnalyzers/.editorconfig new file mode 100644 index 0000000..875a567 --- /dev/null +++ b/src/Analyzers/ZilfAnalyzers/.editorconfig @@ -0,0 +1,7 @@ +[*.cs] + +# RNUL: Parameter is missing nullability annotation. +dotnet_diagnostic.RNUL.severity = silent + +# RINUL: Parameter is missing item nullability annotation. +dotnet_diagnostic.RINUL.severity = silent diff --git a/src/Analyzers/ZilfAnalyzers/ErrorExceptionUsageAnalyzer.cs b/src/Analyzers/ZilfAnalyzers/ErrorExceptionUsageAnalyzer.cs index 2e22da7..9f4f21b 100644 --- a/src/Analyzers/ZilfAnalyzers/ErrorExceptionUsageAnalyzer.cs +++ b/src/Analyzers/ZilfAnalyzers/ErrorExceptionUsageAnalyzer.cs @@ -27,6 +27,8 @@ namespace ZilfAnalyzers public override void Initialize([NotNull] AnalysisContext context) { + context.EnableConcurrentExecution(); + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.ObjectCreationExpression); } diff --git a/src/Analyzers/ZilfAnalyzers/MessageConstantAnalyzer.cs b/src/Analyzers/ZilfAnalyzers/MessageConstantAnalyzer.cs index 668a11d..863ff41 100644 --- a/src/Analyzers/ZilfAnalyzers/MessageConstantAnalyzer.cs +++ b/src/Analyzers/ZilfAnalyzers/MessageConstantAnalyzer.cs @@ -51,6 +51,8 @@ namespace ZilfAnalyzers public override void Initialize([NotNull] AnalysisContext context) { + context.EnableConcurrentExecution(); + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.ClassDeclaration); } diff --git a/src/Analyzers/ZilfAnalyzers/ZilObjectAnalyzer.cs b/src/Analyzers/ZilfAnalyzers/ZilObjectAnalyzer.cs index aa4b414..7747201 100644 --- a/src/Analyzers/ZilfAnalyzers/ZilObjectAnalyzer.cs +++ b/src/Analyzers/ZilfAnalyzers/ZilObjectAnalyzer.cs @@ -28,7 +28,6 @@ namespace ZilfAnalyzers DiagnosticSeverity.Warning, isEnabledByDefault: true); - public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create( Rule_ComparingZilObjectsWithEquals, @@ -36,6 +35,8 @@ namespace ZilfAnalyzers public override void Initialize([NotNull] AnalysisContext context) { + context.EnableConcurrentExecution(); + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.RegisterSyntaxNodeAction(AnalyzeMemberAccessishNode, SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.ConditionalAccessExpression); context.RegisterSyntaxNodeAction(AnalyzeInvocationNode, SyntaxKind.InvocationExpression); context.RegisterSymbolAction(AnalyzeClassSymbol, SymbolKind.NamedType); @@ -63,7 +64,7 @@ namespace ZilfAnalyzers { var diagnostic = Diagnostic.Create( Rule_PartiallyOverriddenZilObjectComparison, - overridingMethod.Locations.First(), + overridingMethod.Locations[0], type.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat), baseEqualsMethod.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat), baseExactlyEqualsMethod?.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat)); diff --git a/src/Analyzers/ZilfAnalyzers/ZilfAnalyzers.csproj b/src/Analyzers/ZilfAnalyzers/ZilfAnalyzers.csproj index 9952936..095931d 100644 --- a/src/Analyzers/ZilfAnalyzers/ZilfAnalyzers.csproj +++ b/src/Analyzers/ZilfAnalyzers/ZilfAnalyzers.csproj @@ -24,7 +24,7 @@ - + diff --git a/src/Dezapf/Dezapf.csproj b/src/Dezapf/Dezapf.csproj index d59262f..906c7af 100644 --- a/src/Dezapf/Dezapf.csproj +++ b/src/Dezapf/Dezapf.csproj @@ -1,6 +1,6 @@  - netcoreapp2.2 + netcoreapp3.0 Exe ZILF 0.8 @@ -13,7 +13,7 @@ - + all runtime compile; build; native; contentfiles; analyzers diff --git a/src/Zapf.Parsing/.editorconfig b/src/Zapf.Parsing/.editorconfig new file mode 100644 index 0000000..21c8129 --- /dev/null +++ b/src/Zapf.Parsing/.editorconfig @@ -0,0 +1,7 @@ +[*.cs] + +# RCS1194: Implement exception constructors. +dotnet_diagnostic.RCS1194.severity = suggestion + +# RCS1139: Add summary element to documentation comment. +dotnet_diagnostic.RCS1139.severity = silent diff --git a/src/Zapf.Parsing/Diagnostics/AssemblerError.cs b/src/Zapf.Parsing/Diagnostics/AssemblerError.cs index 34f0391..c461568 100644 --- a/src/Zapf.Parsing/Diagnostics/AssemblerError.cs +++ b/src/Zapf.Parsing/Diagnostics/AssemblerError.cs @@ -18,26 +18,25 @@ using System; using System.Runtime.Serialization; -using JetBrains.Annotations; namespace Zapf.Parsing.Diagnostics { [Serializable] public abstract class AssemblerError : Exception { - protected AssemblerError(ISourceLine node, string message) + protected AssemblerError(ISourceLine? node, string message) : base(message) { Node = node; } - protected AssemblerError([NotNull] SerializationInfo info, StreamingContext context) + protected AssemblerError(SerializationInfo info, StreamingContext context) : base(info, context) { Node = (ISourceLine)info.GetValue("node", typeof(ISourceLine)); } - public ISourceLine Node { get; } + public ISourceLine? Node { get; } public override void GetObjectData(SerializationInfo info, StreamingContext context) { diff --git a/src/Zapf.Parsing/Diagnostics/Errors.cs b/src/Zapf.Parsing/Diagnostics/Errors.cs index c6f568d..f556a9e 100644 --- a/src/Zapf.Parsing/Diagnostics/Errors.cs +++ b/src/Zapf.Parsing/Diagnostics/Errors.cs @@ -16,62 +16,62 @@ * along with ZILF. If not, see . */ +using System.Diagnostics.CodeAnalysis; using JetBrains.Annotations; namespace Zapf.Parsing.Diagnostics { public static class Errors { - public static void Warn([NotNull] IErrorSink sink, [CanBeNull] ISourceLine node, [NotNull] string message) + public static void Warn(IErrorSink sink, ISourceLine? node, string message) { sink.HandleWarning(new Warning(node, message)); } [StringFormatMethod("format")] - public static void Warn([NotNull] IErrorSink sink, [CanBeNull] ISourceLine node, [NotNull] string format, [NotNull] params object[] args) + public static void Warn(IErrorSink sink, ISourceLine? node, string format, params object[] args) { Warn(sink, node, string.Format(format, args)); } - public static void Serious([NotNull] IErrorSink sink, [NotNull] string message) + public static void Serious(IErrorSink sink, string message) { Serious(sink, null, message); } [StringFormatMethod("format")] - public static void Serious([NotNull] IErrorSink sink, [NotNull] string format, [NotNull] params object[] args) + public static void Serious(IErrorSink sink, string format, params object[] args) { Serious(sink, string.Format(format, args)); } - public static void Serious([NotNull] IErrorSink sink, ISourceLine node, [NotNull] string message) + public static void Serious(IErrorSink sink, ISourceLine? node, string message) { sink.HandleSeriousError(new SeriousError(node, message)); } [StringFormatMethod("format")] - public static void Serious([NotNull] IErrorSink sink, ISourceLine node, [NotNull] string format, - [NotNull] params object[] args) + public static void Serious(IErrorSink sink, ISourceLine? node, string format, + params object[] args) { Serious(sink, node, string.Format(format, args)); } - [NotNull] - public static SeriousError MakeSerious(ISourceLine node, [NotNull] string message) + public static SeriousError MakeSerious(ISourceLine? node, string message) { return new SeriousError(node, message); } - [NotNull] [StringFormatMethod("format")] - public static SeriousError MakeSerious(ISourceLine node, [NotNull] string format, [NotNull] params object[] args) + public static SeriousError MakeSerious(ISourceLine? node, string format, params object[] args) { return MakeSerious(node, string.Format(format, args)); } /// Always thrown. [ContractAnnotation("=> halt")] - public static void ThrowSerious([NotNull] string message) + [DoesNotReturn] + public static void ThrowSerious(string message) { ThrowSerious(null, message); } @@ -79,14 +79,16 @@ namespace Zapf.Parsing.Diagnostics /// Always thrown. [ContractAnnotation("=> halt")] [StringFormatMethod("format")] - public static void ThrowSerious([NotNull] string format, [NotNull] params object[] args) + [DoesNotReturn] + public static void ThrowSerious(string format, params object[] args) { ThrowSerious(null, format, args); } /// Always thrown. [ContractAnnotation("=> halt")] - public static void ThrowSerious(ISourceLine node, [NotNull] string message) + [DoesNotReturn] + public static void ThrowSerious(ISourceLine? node, string message) { throw MakeSerious(node, message); } @@ -94,14 +96,16 @@ namespace Zapf.Parsing.Diagnostics /// Always thrown. [ContractAnnotation("=> halt")] [StringFormatMethod("format")] - public static void ThrowSerious(ISourceLine node, [NotNull] string format, [NotNull] params object[] args) + [DoesNotReturn] + public static void ThrowSerious(ISourceLine? node, string format, params object[] args) { throw MakeSerious(node, format, args); } /// Always thrown. [ContractAnnotation("=> halt")] - public static void ThrowFatal([NotNull] string message) + [DoesNotReturn] + public static void ThrowFatal(string message) { ThrowFatal(null, message); } @@ -109,14 +113,16 @@ namespace Zapf.Parsing.Diagnostics /// Always thrown. [ContractAnnotation("=> halt")] [StringFormatMethod("format")] - public static void ThrowFatal([NotNull] string format, [NotNull] params object[] args) + [DoesNotReturn] + public static void ThrowFatal(string format, params object[] args) { ThrowFatal(null, format, args); } /// Always thrown. [ContractAnnotation("=> halt")] - public static void ThrowFatal(ISourceLine node, [NotNull] string message) + [DoesNotReturn] + public static void ThrowFatal(ISourceLine? node, string message) { throw new FatalError(node, message); } @@ -124,7 +130,8 @@ namespace Zapf.Parsing.Diagnostics /// Always thrown. [ContractAnnotation("=> halt")] [StringFormatMethod("format")] - public static void ThrowFatal(ISourceLine node, [NotNull] string format, [NotNull] params object[] args) + [DoesNotReturn] + public static void ThrowFatal(ISourceLine? node, string format, params object[] args) { ThrowFatal(node, string.Format(format, args)); } diff --git a/src/Zapf.Parsing/Diagnostics/FatalError.cs b/src/Zapf.Parsing/Diagnostics/FatalError.cs index 5ea9de4..df97d50 100644 --- a/src/Zapf.Parsing/Diagnostics/FatalError.cs +++ b/src/Zapf.Parsing/Diagnostics/FatalError.cs @@ -26,7 +26,7 @@ namespace Zapf.Parsing.Diagnostics [Serializable] public class FatalError : AssemblerError { - public FatalError(ISourceLine node, string message) + public FatalError(ISourceLine? node, string message) : base(node, message) { } diff --git a/src/Zapf.Parsing/Diagnostics/ISourceLine.cs b/src/Zapf.Parsing/Diagnostics/ISourceLine.cs index cc31f7b..5087e87 100644 --- a/src/Zapf.Parsing/Diagnostics/ISourceLine.cs +++ b/src/Zapf.Parsing/Diagnostics/ISourceLine.cs @@ -25,8 +25,7 @@ namespace Zapf.Parsing.Diagnostics [SuppressMessage("ReSharper", "UnusedMemberInSuper.Global")] public interface ISourceLine { - [CanBeNull] - string SourceFile { get; } + string? SourceFile { get; } int LineNum { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Diagnostics/SeriousError.cs b/src/Zapf.Parsing/Diagnostics/SeriousError.cs index 5c3a890..59c14cf 100644 --- a/src/Zapf.Parsing/Diagnostics/SeriousError.cs +++ b/src/Zapf.Parsing/Diagnostics/SeriousError.cs @@ -26,7 +26,7 @@ namespace Zapf.Parsing.Diagnostics [Serializable] public class SeriousError : AssemblerError { - public SeriousError(ISourceLine node, string message) + public SeriousError(ISourceLine? node, string message) : base(node, message) { } diff --git a/src/Zapf.Parsing/Diagnostics/Warning.cs b/src/Zapf.Parsing/Diagnostics/Warning.cs index f99b306..5f497d6 100644 --- a/src/Zapf.Parsing/Diagnostics/Warning.cs +++ b/src/Zapf.Parsing/Diagnostics/Warning.cs @@ -26,7 +26,7 @@ namespace Zapf.Parsing.Diagnostics [Serializable] public class Warning : AssemblerError { - public Warning(ISourceLine node, string message) + public Warning(ISourceLine? node, string message) : base(node, message) { } diff --git a/src/Zapf.Parsing/Directives/AlignDirective.cs b/src/Zapf.Parsing/Directives/AlignDirective.cs index 3daa6f7..ba1bb1d 100644 --- a/src/Zapf.Parsing/Directives/AlignDirective.cs +++ b/src/Zapf.Parsing/Directives/AlignDirective.cs @@ -23,12 +23,11 @@ namespace Zapf.Parsing.Directives { public sealed class AlignDirective : Directive { - public AlignDirective([NotNull] AsmExpr divisor) + public AlignDirective(AsmExpr divisor) { Divisor = divisor; } - [NotNull] public AsmExpr Divisor { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/AsmLine.cs b/src/Zapf.Parsing/Directives/AsmLine.cs index 1aeb01b..03f1914 100644 --- a/src/Zapf.Parsing/Directives/AsmLine.cs +++ b/src/Zapf.Parsing/Directives/AsmLine.cs @@ -22,7 +22,7 @@ namespace Zapf.Parsing.Directives { public abstract class AsmLine : ISourceLine { - public string SourceFile { get; set; } + public string? SourceFile { get; set; } public int LineNum { get; set; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/BareSymbolLine.cs b/src/Zapf.Parsing/Directives/BareSymbolLine.cs index c6efed9..a14c0ba 100644 --- a/src/Zapf.Parsing/Directives/BareSymbolLine.cs +++ b/src/Zapf.Parsing/Directives/BareSymbolLine.cs @@ -22,12 +22,11 @@ namespace Zapf.Parsing.Directives { public sealed class BareSymbolLine : AsmLine { - public BareSymbolLine([NotNull] string text) + public BareSymbolLine(string text) { Text = text; } - [NotNull] public string Text { get; } public int OperandCount { get; set; } diff --git a/src/Zapf.Parsing/Directives/ChrsetDirective.cs b/src/Zapf.Parsing/Directives/ChrsetDirective.cs index 267a688..b0c5b41 100644 --- a/src/Zapf.Parsing/Directives/ChrsetDirective.cs +++ b/src/Zapf.Parsing/Directives/ChrsetDirective.cs @@ -24,15 +24,13 @@ namespace Zapf.Parsing.Directives { public sealed class ChrsetDirective : Directive { - public ChrsetDirective([NotNull] AsmExpr alphabetNum, [NotNull] IEnumerable characters) + public ChrsetDirective(AsmExpr alphabetNum, IEnumerable characters) { CharsetNum = alphabetNum; Characters = new List(characters); } - [NotNull] public AsmExpr CharsetNum { get; } - [NotNull] public IList Characters { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/DataDirective.cs b/src/Zapf.Parsing/Directives/DataDirective.cs index 48c8352..0d3fa99 100644 --- a/src/Zapf.Parsing/Directives/DataDirective.cs +++ b/src/Zapf.Parsing/Directives/DataDirective.cs @@ -24,7 +24,6 @@ namespace Zapf.Parsing.Directives { public abstract class DataDirective : Directive { - [NotNull] public IList Elements { get; } = new List(); } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/DebugActionDirective.cs b/src/Zapf.Parsing/Directives/DebugActionDirective.cs index e4804c0..cfc490c 100644 --- a/src/Zapf.Parsing/Directives/DebugActionDirective.cs +++ b/src/Zapf.Parsing/Directives/DebugActionDirective.cs @@ -23,7 +23,7 @@ namespace Zapf.Parsing.Directives { public sealed class DebugActionDirective : NumberAndNameDebugDirective { - public DebugActionDirective([NotNull] AsmExpr number, [NotNull] string name) + public DebugActionDirective(AsmExpr number, string name) : base(number, name) { } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/DebugArrayDirective.cs b/src/Zapf.Parsing/Directives/DebugArrayDirective.cs index 4086648..ed47773 100644 --- a/src/Zapf.Parsing/Directives/DebugArrayDirective.cs +++ b/src/Zapf.Parsing/Directives/DebugArrayDirective.cs @@ -23,7 +23,7 @@ namespace Zapf.Parsing.Directives { public sealed class DebugArrayDirective : NumberAndNameDebugDirective { - public DebugArrayDirective([NotNull] AsmExpr number, [NotNull] string name) + public DebugArrayDirective(AsmExpr number, string name) : base(number, name) { } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/DebugAttrDirective.cs b/src/Zapf.Parsing/Directives/DebugAttrDirective.cs index 211b79b..9f87204 100644 --- a/src/Zapf.Parsing/Directives/DebugAttrDirective.cs +++ b/src/Zapf.Parsing/Directives/DebugAttrDirective.cs @@ -23,7 +23,7 @@ namespace Zapf.Parsing.Directives { public sealed class DebugAttrDirective : NumberAndNameDebugDirective { - public DebugAttrDirective([NotNull] AsmExpr number, [NotNull] string name) + public DebugAttrDirective(AsmExpr number, string name) : base(number, name) { } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/DebugClassDirective.cs b/src/Zapf.Parsing/Directives/DebugClassDirective.cs index c6c781b..7a6be1e 100644 --- a/src/Zapf.Parsing/Directives/DebugClassDirective.cs +++ b/src/Zapf.Parsing/Directives/DebugClassDirective.cs @@ -17,7 +17,6 @@ */ using System.Diagnostics.CodeAnalysis; -using JetBrains.Annotations; using Zapf.Parsing.Expressions; namespace Zapf.Parsing.Directives @@ -25,9 +24,9 @@ namespace Zapf.Parsing.Directives [SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")] public sealed class DebugClassDirective : DebugDirective { - public DebugClassDirective([NotNull] string name, - [NotNull] AsmExpr startFile, [NotNull] AsmExpr startLine, [NotNull] AsmExpr startColumn, - [NotNull] AsmExpr endFile, [NotNull] AsmExpr endLine, [NotNull] AsmExpr endColumn) + public DebugClassDirective(string name, + AsmExpr startFile, AsmExpr startLine, AsmExpr startColumn, + AsmExpr endFile, AsmExpr endLine, AsmExpr endColumn) { Name = name; StartFile = startFile; @@ -38,19 +37,12 @@ namespace Zapf.Parsing.Directives EndColumn = endColumn; } - [NotNull] public string Name { get; } - [NotNull] public AsmExpr StartFile { get; } - [NotNull] public AsmExpr StartLine { get; } - [NotNull] public AsmExpr StartColumn { get; } - [NotNull] public AsmExpr EndFile { get; } - [NotNull] public AsmExpr EndLine { get; } - [NotNull] public AsmExpr EndColumn { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/DebugFakeActionDirective.cs b/src/Zapf.Parsing/Directives/DebugFakeActionDirective.cs index 5140a70..15efcc1 100644 --- a/src/Zapf.Parsing/Directives/DebugFakeActionDirective.cs +++ b/src/Zapf.Parsing/Directives/DebugFakeActionDirective.cs @@ -17,15 +17,16 @@ */ using System.Diagnostics.CodeAnalysis; -using JetBrains.Annotations; using Zapf.Parsing.Expressions; namespace Zapf.Parsing.Directives { +#nullable enable [SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")] public sealed class DebugFakeActionDirective : NumberAndNameDebugDirective { - public DebugFakeActionDirective([NotNull] AsmExpr number, [NotNull] string name) + public DebugFakeActionDirective(AsmExpr number, string name) : base(number, name) { } } +#nullable restore } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/DebugFileDirective.cs b/src/Zapf.Parsing/Directives/DebugFileDirective.cs index 9a4fb62..be5f6a3 100644 --- a/src/Zapf.Parsing/Directives/DebugFileDirective.cs +++ b/src/Zapf.Parsing/Directives/DebugFileDirective.cs @@ -23,18 +23,15 @@ namespace Zapf.Parsing.Directives { public sealed class DebugFileDirective : DebugDirective { - public DebugFileDirective([NotNull] AsmExpr number, [NotNull] string includeName, [NotNull] string actualName) + public DebugFileDirective(AsmExpr number, string includeName, string actualName) { Number = number; IncludeName = includeName; ActualName = actualName; } - [NotNull] public AsmExpr Number { get; } - [NotNull] public string IncludeName { get; } - [NotNull] public string ActualName { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/DebugGlobalDirective.cs b/src/Zapf.Parsing/Directives/DebugGlobalDirective.cs index 3d0e351..a4a18bd 100644 --- a/src/Zapf.Parsing/Directives/DebugGlobalDirective.cs +++ b/src/Zapf.Parsing/Directives/DebugGlobalDirective.cs @@ -23,7 +23,7 @@ namespace Zapf.Parsing.Directives { public sealed class DebugGlobalDirective : NumberAndNameDebugDirective { - public DebugGlobalDirective([NotNull] AsmExpr number, [NotNull] string name) + public DebugGlobalDirective(AsmExpr number, string name) : base(number, name) { } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/DebugLineDirective.cs b/src/Zapf.Parsing/Directives/DebugLineDirective.cs index 4021334..e0744ad 100644 --- a/src/Zapf.Parsing/Directives/DebugLineDirective.cs +++ b/src/Zapf.Parsing/Directives/DebugLineDirective.cs @@ -23,7 +23,7 @@ namespace Zapf.Parsing.Directives { public sealed class DebugLineDirective : LineDebugDirective { - public DebugLineDirective([NotNull] AsmExpr file, [NotNull] AsmExpr line, [NotNull] AsmExpr column) + public DebugLineDirective(AsmExpr file, AsmExpr line, AsmExpr column) : base(file, line, column) { } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/DebugMapDirective.cs b/src/Zapf.Parsing/Directives/DebugMapDirective.cs index 51d3f07..3e16296 100644 --- a/src/Zapf.Parsing/Directives/DebugMapDirective.cs +++ b/src/Zapf.Parsing/Directives/DebugMapDirective.cs @@ -23,15 +23,13 @@ namespace Zapf.Parsing.Directives { public sealed class DebugMapDirective : DebugDirective { - public DebugMapDirective([NotNull] string key, [CanBeNull] AsmExpr value) + public DebugMapDirective(string key, AsmExpr? value) { Key = key; Value = value; } - [NotNull] public string Key { get; } - [CanBeNull] - public AsmExpr Value { get; } + public AsmExpr? Value { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/DebugObjectDirective.cs b/src/Zapf.Parsing/Directives/DebugObjectDirective.cs index a59d33a..c573aca 100644 --- a/src/Zapf.Parsing/Directives/DebugObjectDirective.cs +++ b/src/Zapf.Parsing/Directives/DebugObjectDirective.cs @@ -23,9 +23,9 @@ namespace Zapf.Parsing.Directives { public sealed class DebugObjectDirective : DebugDirective { - public DebugObjectDirective([NotNull] AsmExpr number, [NotNull] string name, - [NotNull] AsmExpr startFile, [NotNull] AsmExpr startLine, [NotNull] AsmExpr startColumn, - [NotNull] AsmExpr endFile, [NotNull] AsmExpr endLine, [NotNull] AsmExpr endColumn) + public DebugObjectDirective(AsmExpr number, string name, + AsmExpr startFile, AsmExpr startLine, AsmExpr startColumn, + AsmExpr endFile, AsmExpr endLine, AsmExpr endColumn) { Number = number; Name = name; @@ -37,21 +37,13 @@ namespace Zapf.Parsing.Directives EndColumn = endColumn; } - [NotNull] public AsmExpr Number { get; } - [NotNull] public string Name { get; } - [NotNull] public AsmExpr StartFile { get; } - [NotNull] public AsmExpr StartLine { get; } - [NotNull] public AsmExpr StartColumn { get; } - [NotNull] public AsmExpr EndFile { get; } - [NotNull] public AsmExpr EndLine { get; } - [NotNull] public AsmExpr EndColumn { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/DebugPropDirective.cs b/src/Zapf.Parsing/Directives/DebugPropDirective.cs index 5cd8803..9c92e9f 100644 --- a/src/Zapf.Parsing/Directives/DebugPropDirective.cs +++ b/src/Zapf.Parsing/Directives/DebugPropDirective.cs @@ -23,7 +23,7 @@ namespace Zapf.Parsing.Directives { public sealed class DebugPropDirective : NumberAndNameDebugDirective { - public DebugPropDirective([NotNull] AsmExpr number, [NotNull] string name) + public DebugPropDirective(AsmExpr number, string name) : base(number, name) { } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/DebugRoutineDirective.cs b/src/Zapf.Parsing/Directives/DebugRoutineDirective.cs index f078563..d4b42d6 100644 --- a/src/Zapf.Parsing/Directives/DebugRoutineDirective.cs +++ b/src/Zapf.Parsing/Directives/DebugRoutineDirective.cs @@ -24,18 +24,15 @@ namespace Zapf.Parsing.Directives { public sealed class DebugRoutineDirective : LineDebugDirective { - public DebugRoutineDirective([NotNull] AsmExpr file, [NotNull] AsmExpr line, [NotNull] AsmExpr column, - [NotNull] string name, [ItemNotNull] [NotNull] IEnumerable locals) + public DebugRoutineDirective(AsmExpr file, AsmExpr line, AsmExpr column, + string name, IEnumerable locals) : base(file, line, column) { Name = name; Locals = new List(locals); } - [NotNull] public string Name { get; } - [ItemNotNull] - [NotNull] public IList Locals { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/DebugRoutineEndDirective.cs b/src/Zapf.Parsing/Directives/DebugRoutineEndDirective.cs index 5f3063e..9274b01 100644 --- a/src/Zapf.Parsing/Directives/DebugRoutineEndDirective.cs +++ b/src/Zapf.Parsing/Directives/DebugRoutineEndDirective.cs @@ -23,7 +23,7 @@ namespace Zapf.Parsing.Directives { public sealed class DebugRoutineEndDirective : LineDebugDirective { - public DebugRoutineEndDirective([NotNull] AsmExpr file, [NotNull] AsmExpr line, [NotNull] AsmExpr column) + public DebugRoutineEndDirective(AsmExpr file, AsmExpr line, AsmExpr column) : base(file, line, column) { } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/EqualsDirective.cs b/src/Zapf.Parsing/Directives/EqualsDirective.cs index 16ef138..13231dd 100644 --- a/src/Zapf.Parsing/Directives/EqualsDirective.cs +++ b/src/Zapf.Parsing/Directives/EqualsDirective.cs @@ -23,15 +23,13 @@ namespace Zapf.Parsing.Directives { public sealed class EqualsDirective : Directive { - public EqualsDirective([NotNull] string left, [NotNull] AsmExpr right) + public EqualsDirective(string left, AsmExpr right) { Left = left; Right = right; } - [NotNull] public string Left { get; } - [NotNull] public AsmExpr Right { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/FstrDirective.cs b/src/Zapf.Parsing/Directives/FstrDirective.cs index 76cb479..36be0d8 100644 --- a/src/Zapf.Parsing/Directives/FstrDirective.cs +++ b/src/Zapf.Parsing/Directives/FstrDirective.cs @@ -22,7 +22,7 @@ namespace Zapf.Parsing.Directives { public sealed class FstrDirective : NameAndTextDirective { - public FstrDirective([NotNull] string name, [NotNull] string text) + public FstrDirective(string name, string text) : base(name, text) { } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/FunctDirective.cs b/src/Zapf.Parsing/Directives/FunctDirective.cs index f31dc41..5115888 100644 --- a/src/Zapf.Parsing/Directives/FunctDirective.cs +++ b/src/Zapf.Parsing/Directives/FunctDirective.cs @@ -23,13 +23,12 @@ namespace Zapf.Parsing.Directives { public sealed class FunctDirective : NamedDirective { - public FunctDirective([NotNull] string name) + public FunctDirective(string name) : base(name) { Locals = new List(); } - [NotNull] public IList Locals { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/FunctLocal.cs b/src/Zapf.Parsing/Directives/FunctLocal.cs index 57e6642..2159573 100644 --- a/src/Zapf.Parsing/Directives/FunctLocal.cs +++ b/src/Zapf.Parsing/Directives/FunctLocal.cs @@ -23,15 +23,13 @@ namespace Zapf.Parsing.Directives { public struct FunctLocal { - public FunctLocal([NotNull] string name, [CanBeNull] AsmExpr defaultValue) + public FunctLocal(string name, AsmExpr? defaultValue) { Name = name; DefaultValue = defaultValue; } - [NotNull] public readonly string Name; - [CanBeNull] - public readonly AsmExpr DefaultValue; + public readonly AsmExpr? DefaultValue; } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/GstrDirective.cs b/src/Zapf.Parsing/Directives/GstrDirective.cs index f954745..cfa8d36 100644 --- a/src/Zapf.Parsing/Directives/GstrDirective.cs +++ b/src/Zapf.Parsing/Directives/GstrDirective.cs @@ -22,7 +22,7 @@ namespace Zapf.Parsing.Directives { public sealed class GstrDirective : NameAndTextDirective { - public GstrDirective([NotNull] string name, [NotNull] string text) + public GstrDirective(string name, string text) : base(name, text) { } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/GvarDirective.cs b/src/Zapf.Parsing/Directives/GvarDirective.cs index 31372c4..d4ee398 100644 --- a/src/Zapf.Parsing/Directives/GvarDirective.cs +++ b/src/Zapf.Parsing/Directives/GvarDirective.cs @@ -23,13 +23,12 @@ namespace Zapf.Parsing.Directives { public sealed class GvarDirective : NamedDirective { - public GvarDirective([NotNull] string name, [CanBeNull] AsmExpr initialValue) + public GvarDirective(string name, AsmExpr? initialValue) : base(name) { InitialValue = initialValue; } - [CanBeNull] - public AsmExpr InitialValue { get; } + public AsmExpr? InitialValue { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/InsertDirective.cs b/src/Zapf.Parsing/Directives/InsertDirective.cs index 594dfe6..3d101d6 100644 --- a/src/Zapf.Parsing/Directives/InsertDirective.cs +++ b/src/Zapf.Parsing/Directives/InsertDirective.cs @@ -22,12 +22,11 @@ namespace Zapf.Parsing.Directives { public sealed class InsertDirective : Directive { - public InsertDirective([NotNull] string filename) + public InsertDirective(string filename) { InsertFileName = filename; } - [NotNull] public string InsertFileName { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/LangDirective.cs b/src/Zapf.Parsing/Directives/LangDirective.cs index f3c2116..f6028db 100644 --- a/src/Zapf.Parsing/Directives/LangDirective.cs +++ b/src/Zapf.Parsing/Directives/LangDirective.cs @@ -23,15 +23,13 @@ namespace Zapf.Parsing.Directives { public sealed class LangDirective : Directive { - public LangDirective([NotNull] AsmExpr langId, [NotNull] AsmExpr escapeChar) + public LangDirective(AsmExpr langId, AsmExpr escapeChar) { LanguageId = langId; EscapeChar = escapeChar; } - [NotNull] public AsmExpr LanguageId { get; } - [NotNull] public AsmExpr EscapeChar { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/LenDirective.cs b/src/Zapf.Parsing/Directives/LenDirective.cs index 274ab13..0ceb02a 100644 --- a/src/Zapf.Parsing/Directives/LenDirective.cs +++ b/src/Zapf.Parsing/Directives/LenDirective.cs @@ -22,7 +22,7 @@ namespace Zapf.Parsing.Directives { public sealed class LenDirective : TextDirective { - public LenDirective([NotNull] string text) + public LenDirective(string text) : base(text) { } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/LineDebugDirective.cs b/src/Zapf.Parsing/Directives/LineDebugDirective.cs index c6c400d..99c716b 100644 --- a/src/Zapf.Parsing/Directives/LineDebugDirective.cs +++ b/src/Zapf.Parsing/Directives/LineDebugDirective.cs @@ -23,18 +23,15 @@ namespace Zapf.Parsing.Directives { public abstract class LineDebugDirective : DebugDirective { - protected LineDebugDirective([NotNull] AsmExpr file, [NotNull] AsmExpr line, [NotNull] AsmExpr column) + protected LineDebugDirective(AsmExpr file, AsmExpr line, AsmExpr column) { TheFile = file; TheLine = line; TheColumn = column; } - [NotNull] public AsmExpr TheFile { get; } - [NotNull] public AsmExpr TheLine { get; } - [NotNull] public AsmExpr TheColumn { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/NameAndTextDirective.cs b/src/Zapf.Parsing/Directives/NameAndTextDirective.cs index 04a514c..59862ca 100644 --- a/src/Zapf.Parsing/Directives/NameAndTextDirective.cs +++ b/src/Zapf.Parsing/Directives/NameAndTextDirective.cs @@ -22,15 +22,13 @@ namespace Zapf.Parsing.Directives { public abstract class NameAndTextDirective : Directive { - protected NameAndTextDirective([NotNull] string name, [NotNull] string text) + protected NameAndTextDirective(string name, string text) { Name = name; Text = text; } - [NotNull] public string Name { get; } - [NotNull] public string Text { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/NamedDirective.cs b/src/Zapf.Parsing/Directives/NamedDirective.cs index 51ac516..ab8739e 100644 --- a/src/Zapf.Parsing/Directives/NamedDirective.cs +++ b/src/Zapf.Parsing/Directives/NamedDirective.cs @@ -22,12 +22,11 @@ namespace Zapf.Parsing.Directives { public abstract class NamedDirective : Directive { - protected NamedDirective([NotNull] string name) + protected NamedDirective(string name) { Name = name; } - [NotNull] public string Name { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/NewDirective.cs b/src/Zapf.Parsing/Directives/NewDirective.cs index 76495c0..97cd806 100644 --- a/src/Zapf.Parsing/Directives/NewDirective.cs +++ b/src/Zapf.Parsing/Directives/NewDirective.cs @@ -23,12 +23,11 @@ namespace Zapf.Parsing.Directives { public sealed class NewDirective : Directive { - public NewDirective([CanBeNull] AsmExpr version) + public NewDirective(AsmExpr? version) { Version = version; } - [CanBeNull] - public AsmExpr Version { get; } + public AsmExpr? Version { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/NumberAndNameDebugDirective.cs b/src/Zapf.Parsing/Directives/NumberAndNameDebugDirective.cs index a11a098..f344a7e 100644 --- a/src/Zapf.Parsing/Directives/NumberAndNameDebugDirective.cs +++ b/src/Zapf.Parsing/Directives/NumberAndNameDebugDirective.cs @@ -16,22 +16,21 @@ * along with ZILF. If not, see . */ -using JetBrains.Annotations; using Zapf.Parsing.Expressions; namespace Zapf.Parsing.Directives { +#nullable enable public abstract class NumberAndNameDebugDirective : DebugDirective { - protected NumberAndNameDebugDirective([NotNull] AsmExpr number, [NotNull] string name) + protected NumberAndNameDebugDirective(AsmExpr number, string name) { Number = number; Name = name; } - [NotNull] public AsmExpr Number { get; } - [NotNull] public string Name { get; } } +#nullable restore } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/ObjectDirective.cs b/src/Zapf.Parsing/Directives/ObjectDirective.cs index 0792513..e3a6124 100644 --- a/src/Zapf.Parsing/Directives/ObjectDirective.cs +++ b/src/Zapf.Parsing/Directives/ObjectDirective.cs @@ -23,10 +23,10 @@ namespace Zapf.Parsing.Directives { public sealed class ObjectDirective : NamedDirective { - public ObjectDirective([NotNull] string name, - [NotNull] AsmExpr flags1, [NotNull] AsmExpr flags2, [CanBeNull] AsmExpr flags3, - [NotNull] AsmExpr parent, [NotNull] AsmExpr sibling, [NotNull] AsmExpr child, - [NotNull] AsmExpr propTable) + public ObjectDirective(string name, + AsmExpr flags1, AsmExpr flags2, AsmExpr? flags3, + AsmExpr parent, AsmExpr sibling, AsmExpr child, + AsmExpr propTable) : base(name) { Flags1 = flags1; @@ -38,19 +38,12 @@ namespace Zapf.Parsing.Directives PropTable = propTable; } - [NotNull] public AsmExpr Flags1 { get; } - [NotNull] public AsmExpr Flags2 { get; } - [CanBeNull] - public AsmExpr Flags3 { get; } - [NotNull] + public AsmExpr? Flags3 { get; } public AsmExpr Parent { get; } - [NotNull] public AsmExpr Sibling { get; } - [NotNull] public AsmExpr Child { get; } - [NotNull] public AsmExpr PropTable { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/PropDirective.cs b/src/Zapf.Parsing/Directives/PropDirective.cs index f222e35..b71e461 100644 --- a/src/Zapf.Parsing/Directives/PropDirective.cs +++ b/src/Zapf.Parsing/Directives/PropDirective.cs @@ -23,15 +23,13 @@ namespace Zapf.Parsing.Directives { public sealed class PropDirective : Directive { - public PropDirective([NotNull] AsmExpr size, [NotNull] AsmExpr prop) + public PropDirective(AsmExpr size, AsmExpr prop) { Size = size; Prop = prop; } - [NotNull] public AsmExpr Size { get; } - [NotNull] public AsmExpr Prop { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/StrDirective.cs b/src/Zapf.Parsing/Directives/StrDirective.cs index c9dd87f..728ed61 100644 --- a/src/Zapf.Parsing/Directives/StrDirective.cs +++ b/src/Zapf.Parsing/Directives/StrDirective.cs @@ -22,7 +22,7 @@ namespace Zapf.Parsing.Directives { public sealed class StrDirective : TextDirective { - public StrDirective([NotNull] string text) + public StrDirective(string text) : base(text) { } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/StrlDirective.cs b/src/Zapf.Parsing/Directives/StrlDirective.cs index dd53204..65fb6ea 100644 --- a/src/Zapf.Parsing/Directives/StrlDirective.cs +++ b/src/Zapf.Parsing/Directives/StrlDirective.cs @@ -22,7 +22,7 @@ namespace Zapf.Parsing.Directives { public sealed class StrlDirective : TextDirective { - public StrlDirective([NotNull] string text) + public StrlDirective(string text) : base(text) { } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/TableDirective.cs b/src/Zapf.Parsing/Directives/TableDirective.cs index f913503..768ead5 100644 --- a/src/Zapf.Parsing/Directives/TableDirective.cs +++ b/src/Zapf.Parsing/Directives/TableDirective.cs @@ -23,12 +23,11 @@ namespace Zapf.Parsing.Directives { public sealed class TableDirective : Directive { - public TableDirective([CanBeNull] AsmExpr size) + public TableDirective(AsmExpr? size) { Size = size; } - [CanBeNull] - public AsmExpr Size { get; } + public AsmExpr? Size { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/TextDirective.cs b/src/Zapf.Parsing/Directives/TextDirective.cs index 216274f..14fd437 100644 --- a/src/Zapf.Parsing/Directives/TextDirective.cs +++ b/src/Zapf.Parsing/Directives/TextDirective.cs @@ -22,12 +22,11 @@ namespace Zapf.Parsing.Directives { public abstract class TextDirective : Directive { - protected TextDirective([NotNull] string text) + protected TextDirective(string text) { Text = text; } - [NotNull] public string Text { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/VocbegDirective.cs b/src/Zapf.Parsing/Directives/VocbegDirective.cs index e2abf84..2c74ca3 100644 --- a/src/Zapf.Parsing/Directives/VocbegDirective.cs +++ b/src/Zapf.Parsing/Directives/VocbegDirective.cs @@ -23,15 +23,13 @@ namespace Zapf.Parsing.Directives { public sealed class VocbegDirective : Directive { - public VocbegDirective([NotNull] AsmExpr recordSize, [NotNull] AsmExpr keySize) + public VocbegDirective(AsmExpr recordSize, AsmExpr keySize) { RecordSize = recordSize; KeySize = keySize; } - [NotNull] public AsmExpr RecordSize { get; } - [NotNull] public AsmExpr KeySize { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Directives/ZwordDirective.cs b/src/Zapf.Parsing/Directives/ZwordDirective.cs index 31a5cc4..80ad222 100644 --- a/src/Zapf.Parsing/Directives/ZwordDirective.cs +++ b/src/Zapf.Parsing/Directives/ZwordDirective.cs @@ -22,7 +22,7 @@ namespace Zapf.Parsing.Directives { public sealed class ZwordDirective : TextDirective { - public ZwordDirective([NotNull] string text) + public ZwordDirective(string text) : base(text) { } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Expressions/AdditionExpr.cs b/src/Zapf.Parsing/Expressions/AdditionExpr.cs index 25e4283..506ac1b 100644 --- a/src/Zapf.Parsing/Expressions/AdditionExpr.cs +++ b/src/Zapf.Parsing/Expressions/AdditionExpr.cs @@ -22,15 +22,13 @@ namespace Zapf.Parsing.Expressions { public sealed class AdditionExpr : AsmExpr { - public AdditionExpr([NotNull] AsmExpr left, [NotNull] AsmExpr right) + public AdditionExpr(AsmExpr left, AsmExpr right) { Left = left; Right = right; } - [NotNull] public AsmExpr Left { get; } - [NotNull] public AsmExpr Right { get; } public override string ToString() diff --git a/src/Zapf.Parsing/Expressions/AsmExpr.cs b/src/Zapf.Parsing/Expressions/AsmExpr.cs index d2111bb..35b329b 100644 --- a/src/Zapf.Parsing/Expressions/AsmExpr.cs +++ b/src/Zapf.Parsing/Expressions/AsmExpr.cs @@ -22,7 +22,7 @@ namespace Zapf.Parsing.Expressions { public abstract class AsmExpr : ISourceLine { - public string SourceFile => null; + public string? SourceFile => null; public int LineNum => 0; public abstract override string ToString(); diff --git a/src/Zapf.Parsing/Expressions/NumericLiteral.cs b/src/Zapf.Parsing/Expressions/NumericLiteral.cs index 545ea4f..fec0891 100644 --- a/src/Zapf.Parsing/Expressions/NumericLiteral.cs +++ b/src/Zapf.Parsing/Expressions/NumericLiteral.cs @@ -22,7 +22,7 @@ namespace Zapf.Parsing.Expressions { public sealed class NumericLiteral : TextAsmExpr { - public NumericLiteral([NotNull] string text) + public NumericLiteral(string text) : base(text) { Value = int.Parse(text); diff --git a/src/Zapf.Parsing/Expressions/QuoteExpr.cs b/src/Zapf.Parsing/Expressions/QuoteExpr.cs index a5ed7c2..6c07ef1 100644 --- a/src/Zapf.Parsing/Expressions/QuoteExpr.cs +++ b/src/Zapf.Parsing/Expressions/QuoteExpr.cs @@ -22,12 +22,11 @@ namespace Zapf.Parsing.Expressions { public sealed class QuoteExpr : AsmExpr { - public QuoteExpr([NotNull] AsmExpr inner) + public QuoteExpr(AsmExpr inner) { Inner = inner; } - [NotNull] public AsmExpr Inner { get; } public override string ToString() diff --git a/src/Zapf.Parsing/Expressions/StringLiteral.cs b/src/Zapf.Parsing/Expressions/StringLiteral.cs index b25fbf9..df88378 100644 --- a/src/Zapf.Parsing/Expressions/StringLiteral.cs +++ b/src/Zapf.Parsing/Expressions/StringLiteral.cs @@ -23,7 +23,7 @@ namespace Zapf.Parsing.Expressions { public sealed class StringLiteral : TextAsmExpr { - public StringLiteral([NotNull] string text) + public StringLiteral(string text) : base(text) { } public override string ToString() diff --git a/src/Zapf.Parsing/Expressions/SymbolExpr.cs b/src/Zapf.Parsing/Expressions/SymbolExpr.cs index 1baf031..f71295e 100644 --- a/src/Zapf.Parsing/Expressions/SymbolExpr.cs +++ b/src/Zapf.Parsing/Expressions/SymbolExpr.cs @@ -22,7 +22,7 @@ namespace Zapf.Parsing.Expressions { public sealed class SymbolExpr : TextAsmExpr { - public SymbolExpr([NotNull] string name) + public SymbolExpr(string name) : base(name) { } public override string ToString() diff --git a/src/Zapf.Parsing/Expressions/TextAsmExpr.cs b/src/Zapf.Parsing/Expressions/TextAsmExpr.cs index f605201..89e198b 100644 --- a/src/Zapf.Parsing/Expressions/TextAsmExpr.cs +++ b/src/Zapf.Parsing/Expressions/TextAsmExpr.cs @@ -22,12 +22,11 @@ namespace Zapf.Parsing.Expressions { public abstract class TextAsmExpr : AsmExpr { - protected TextAsmExpr([NotNull] string text) + protected TextAsmExpr(string text) { Text = text; } - [NotNull] public string Text { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/GlobalLabel.cs b/src/Zapf.Parsing/GlobalLabel.cs index aa0c187..fe66df5 100644 --- a/src/Zapf.Parsing/GlobalLabel.cs +++ b/src/Zapf.Parsing/GlobalLabel.cs @@ -23,12 +23,11 @@ namespace Zapf.Parsing { public sealed class GlobalLabel : AsmLine { - public GlobalLabel([NotNull] string name) + public GlobalLabel(string name) { Name = name; } - [NotNull] public string Name { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Instructions/Instruction.cs b/src/Zapf.Parsing/Instructions/Instruction.cs index 1a86d32..306ce98 100644 --- a/src/Zapf.Parsing/Instructions/Instruction.cs +++ b/src/Zapf.Parsing/Instructions/Instruction.cs @@ -20,10 +20,11 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; -using JetBrains.Annotations; using Zapf.Parsing.Directives; using Zapf.Parsing.Expressions; +#nullable enable + namespace Zapf.Parsing.Instructions { public sealed class Instruction : AsmLine @@ -31,56 +32,51 @@ namespace Zapf.Parsing.Instructions public const string BranchTrue = "TRUE"; public const string BranchFalse = "FALSE"; - public Instruction([NotNull] string name) + public Instruction(string name) { Name = name; } - public Instruction([NotNull] string name, [NotNull] IEnumerable operands) + public Instruction(string name, IEnumerable operands) : this(name) { ((List)Operands).AddRange(operands); } - public Instruction([NotNull] string name, [NotNull] AsmExpr operand1) + public Instruction(string name, AsmExpr operand1) : this(name) { Operands.Add(operand1); } - public Instruction([NotNull] string name, [NotNull] AsmExpr operand1, [NotNull] AsmExpr operand2) + public Instruction(string name, AsmExpr operand1, AsmExpr operand2) : this(name, operand1) { Operands.Add(operand2); } - public Instruction([NotNull] string name, [NotNull] AsmExpr operand1, [NotNull] AsmExpr operand2, [NotNull] AsmExpr operand3) + public Instruction(string name, AsmExpr operand1, AsmExpr operand2, AsmExpr operand3) : this(name, operand1, operand2) { Operands.Add(operand3); } - public Instruction([NotNull] string name, [NotNull] AsmExpr operand1, [NotNull] AsmExpr operand2, [NotNull] AsmExpr operand3, [NotNull] AsmExpr operand4) + public Instruction(string name, AsmExpr operand1, AsmExpr operand2, AsmExpr operand3, AsmExpr operand4) : this(name, operand1, operand2, operand3) { Operands.Add(operand4); } - [NotNull] public string Name { get; } - [NotNull] public IList Operands { get; } = new List(); - [CanBeNull] - public string StoreTarget { get; set; } + public string? StoreTarget { get; set; } public bool? BranchPolarity { get; set; } - [CanBeNull] - public string BranchTarget { get; set; } + public string? BranchTarget { get; set; } - [NotNull] - public Instruction WithStoreTarget([CanBeNull] string newStoreTarget) + public Instruction WithStoreTarget(string? newStoreTarget) { var result = new Instruction(Name); ((List)result.Operands).AddRange(Operands); @@ -88,8 +84,7 @@ namespace Zapf.Parsing.Instructions return result; } - [NotNull] - public Instruction WithName([NotNull] string newName) + public Instruction WithName(string newName) { var result = new Instruction(newName) { StoreTarget = StoreTarget }; ((List)result.Operands).AddRange(Operands); @@ -120,7 +115,7 @@ namespace Zapf.Parsing.Instructions return sb.ToString(); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is Instruction other && other.Name == Name && diff --git a/src/Zapf.Parsing/Instructions/LocalLabel.cs b/src/Zapf.Parsing/Instructions/LocalLabel.cs index eb00641..b5fba2c 100644 --- a/src/Zapf.Parsing/Instructions/LocalLabel.cs +++ b/src/Zapf.Parsing/Instructions/LocalLabel.cs @@ -23,12 +23,11 @@ namespace Zapf.Parsing.Instructions { public sealed class LocalLabel : AsmLine { - public LocalLabel([NotNull] string name) + public LocalLabel(string name) { Name = name; } - [NotNull] public string Name { get; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/Instructions/ZOpAttribute.cs b/src/Zapf.Parsing/Instructions/ZOpAttribute.cs index 83b27f5..9e488f4 100644 --- a/src/Zapf.Parsing/Instructions/ZOpAttribute.cs +++ b/src/Zapf.Parsing/Instructions/ZOpAttribute.cs @@ -25,7 +25,7 @@ namespace Zapf.Parsing.Instructions [MeansImplicitUse] public class ZOpAttribute : Attribute { - public ZOpAttribute([NotNull] string classicName, [NotNull] string informName, int minVer, int maxVer, ZOpFlags flags) + public ZOpAttribute(string classicName, string informName, int minVer, int maxVer, ZOpFlags flags) { ClassicName = classicName; InformName = informName; @@ -34,10 +34,8 @@ namespace Zapf.Parsing.Instructions Flags = flags; } - [NotNull] public string ClassicName { get; } - [NotNull] public string InformName { get; } public int MinVer { get; } @@ -46,7 +44,6 @@ namespace Zapf.Parsing.Instructions public ZOpFlags Flags { get; } - [CanBeNull] - public string WhenExtra { get; set; } + public string? WhenExtra { get; set; } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/ParseResult.cs b/src/Zapf.Parsing/ParseResult.cs index 3b5b1b6..1dcd060 100644 --- a/src/Zapf.Parsing/ParseResult.cs +++ b/src/Zapf.Parsing/ParseResult.cs @@ -24,8 +24,6 @@ namespace Zapf.Parsing { public struct ParseResult { - [ItemNotNull] - [NotNull] public IEnumerable Lines; public int NumberOfSyntaxErrors; } diff --git a/src/Zapf.Parsing/Token.cs b/src/Zapf.Parsing/Token.cs index 587057b..aa68111 100644 --- a/src/Zapf.Parsing/Token.cs +++ b/src/Zapf.Parsing/Token.cs @@ -28,7 +28,7 @@ namespace Zapf.Parsing public int Line; public string Filename; - string ISourceLine.SourceFile => Filename; + string? ISourceLine.SourceFile => Filename; int ISourceLine.LineNum => Line; public override string ToString() diff --git a/src/Zapf.Parsing/Tokenizer.cs b/src/Zapf.Parsing/Tokenizer.cs index ccd2c85..1530dc6 100644 --- a/src/Zapf.Parsing/Tokenizer.cs +++ b/src/Zapf.Parsing/Tokenizer.cs @@ -21,7 +21,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; -using JetBrains.Annotations; using Zapf.Parsing.Diagnostics; namespace Zapf.Parsing @@ -39,7 +38,7 @@ namespace Zapf.Parsing { '\'', TokenType.Apostrophe }, }; - StreamReader rdr; + readonly StreamReader rdr; readonly string filename; int line = 1; Token? heldToken; @@ -54,13 +53,12 @@ namespace Zapf.Parsing } public int LineNum { get; } - public string SourceFile { get; } + public string? SourceFile { get; } } - [NotNull] ISourceLine CurrentSourceLine => new BasicSourceLine(line, filename); - public Tokenizer([NotNull] Stream stream, [NotNull] string filename) + public Tokenizer(Stream stream, string filename) { rdr = new StreamReader(stream); this.filename = filename; @@ -68,7 +66,7 @@ namespace Zapf.Parsing char? PeekChar() { - return heldChar ?? (heldChar = NextChar()); + return heldChar ??= NextChar(); } char? NextChar() @@ -149,7 +147,7 @@ namespace Zapf.Parsing break; case ';': - // disard comment + // discard comment do { c = NextChar(); @@ -287,14 +285,7 @@ namespace Zapf.Parsing public void Dispose() { - try - { - rdr?.Dispose(); - } - finally - { - rdr = null; - } + rdr.Dispose(); } } } \ No newline at end of file diff --git a/src/Zapf.Parsing/ZapParser.cs b/src/Zapf.Parsing/ZapParser.cs index 49a61f0..fc05a8c 100644 --- a/src/Zapf.Parsing/ZapParser.cs +++ b/src/Zapf.Parsing/ZapParser.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using JetBrains.Annotations; using Zapf.Parsing.Diagnostics; @@ -31,10 +32,10 @@ namespace Zapf.Parsing { readonly IErrorSink sink; readonly IDictionary> opcodeDict; - Tokenizer toks; + Tokenizer? toks; int errorCount; - public ZapParser(IErrorSink sink, [NotNull] IDictionary> opcodeDict) + public ZapParser(IErrorSink sink, IDictionary> opcodeDict) { this.sink = sink; this.opcodeDict = opcodeDict; @@ -102,7 +103,7 @@ namespace Zapf.Parsing } /// Syntax error. - public ParseResult Parse([NotNull] Stream stream, [NotNull] string filename) + public ParseResult Parse(Stream stream, string filename) { toks = new Tokenizer(stream, filename); var output = new List(); @@ -165,37 +166,37 @@ namespace Zapf.Parsing }; } - void ReportError(ISourceLine node, [NotNull] string message) + void ReportError(ISourceLine node, string message) { errorCount++; Errors.Serious(sink, node, message); } - void ReportError(ISourceLine node, [NotNull] string format, [NotNull] params object[] args) + void ReportError(ISourceLine node, string format, params object[] args) { errorCount++; Errors.Serious(sink, node, format, args); } - void ReportErrorAndSkipLine(ISourceLine node, [NotNull] string message) + void ReportErrorAndSkipLine(ISourceLine node, string message) { ReportError(node, message); SkipLine(); } - void ReportErrorAndSkipLine(ISourceLine node, [NotNull] string format, [NotNull] params object[] args) + void ReportErrorAndSkipLine(ISourceLine node, string format, params object[] args) { ReportError(node, format, args); SkipLine(); } - void ReportErrorAndSkipExpr(ISourceLine node, [NotNull] string message) + void ReportErrorAndSkipExpr(ISourceLine node, string message) { ReportError(node, message); SkipExpr(); } - void ReportErrorAndSkipExpr(ISourceLine node, [NotNull] string format, [NotNull] params object[] args) + void ReportErrorAndSkipExpr(ISourceLine node, string format, params object[] args) { ReportError(node, format, args); SkipExpr(); @@ -203,6 +204,7 @@ namespace Zapf.Parsing void SkipLine() { + Debug.Assert(toks != null); while (true) { switch (toks.PeekToken().Type) @@ -223,6 +225,8 @@ namespace Zapf.Parsing void SkipExpr() { + Debug.Assert(toks != null); + while (true) { switch (toks.PeekToken().Type) @@ -245,106 +249,106 @@ namespace Zapf.Parsing } } - [CanBeNull] - AsmLine TryParseInstruction(Token head) + AsmLine? TryParseInstruction(Token head) { - if (head.Type == TokenType.Symbol && opcodeDict.ContainsKey(head.Text)) + Debug.Assert(toks != null); + + if (head.Type != TokenType.Symbol || !opcodeDict.ContainsKey(head.Text)) + return null; + + var result = new Instruction(head.Text); + + // parse operands + while (true) { - var result = new Instruction(head.Text); + Token t; + var type = toks.PeekToken().Type; - // parse operands - while (true) + switch (type) { - Token t; - var type = toks.PeekToken().Type; + case TokenType.EndOfLine: + toks.NextToken(); + return result; - switch (type) - { - case TokenType.EndOfLine: - toks.NextToken(); - return result; + case TokenType.EndOfFile: + return result; - case TokenType.EndOfFile: - return result; - - case TokenType.Slash: - case TokenType.Backslash: - // branch target - var polarity = toks.NextToken().Type == TokenType.Slash; - t = toks.NextToken(); - if (t.Type != TokenType.Symbol) - { - ReportErrorAndSkipLine( - t, - "expected label or 'TRUE' or 'FALSE' after '{0}'", - polarity ? '/' : '\\'); - } - else if (result.BranchPolarity != null) - { - ReportErrorAndSkipLine(t, "multiple branch targets"); - } - else - { - result.BranchPolarity = polarity; - result.BranchTarget = t.Text; - } - break; + case TokenType.Slash: + case TokenType.Backslash: + // branch target + var polarity = toks.NextToken().Type == TokenType.Slash; + t = toks.NextToken(); + if (t.Type != TokenType.Symbol) + { + ReportErrorAndSkipLine( + t, + "expected label or 'TRUE' or 'FALSE' after '{0}'", + polarity ? '/' : '\\'); + } + else if (result.BranchPolarity != null) + { + ReportErrorAndSkipLine(t, "multiple branch targets"); + } + else + { + result.BranchPolarity = polarity; + result.BranchTarget = t.Text; + } + break; - case TokenType.RAngle: - // store target - toks.NextToken(); - t = toks.NextToken(); - if (t.Type != TokenType.Symbol) - { - ReportErrorAndSkipLine(t, "expected variable or 'STACK' after '>'"); - } - else if (result.StoreTarget != null) - { - ReportErrorAndSkipLine(t, "multiple store targets"); - } - else - { - result.StoreTarget = t.Text; - } - break; + case TokenType.RAngle: + // store target + toks.NextToken(); + t = toks.NextToken(); + if (t.Type != TokenType.Symbol) + { + ReportErrorAndSkipLine(t, "expected variable or 'STACK' after '>'"); + } + else if (result.StoreTarget != null) + { + ReportErrorAndSkipLine(t, "multiple store targets"); + } + else + { + result.StoreTarget = t.Text; + } + break; - default: - if (CanStartExpr(type)) + default: + if (CanStartExpr(type)) + { + // regular operand + result.Operands.Add(ParseExpr()); + switch (toks.PeekToken().Type) { - // regular operand - result.Operands.Add(ParseExpr()); - switch (toks.PeekToken().Type) - { - case TokenType.Comma: - toks.NextToken(); - break; - - case TokenType.Slash: - case TokenType.Backslash: - case TokenType.RAngle: - case TokenType.EndOfLine: - case TokenType.EndOfFile: - break; - - default: - ReportErrorAndSkipLine(toks.PeekToken(), "expected ',' or target or EOL after operand"); - break; - } - break; + case TokenType.Comma: + toks.NextToken(); + break; + + case TokenType.Slash: + case TokenType.Backslash: + case TokenType.RAngle: + case TokenType.EndOfLine: + case TokenType.EndOfFile: + break; + + default: + ReportErrorAndSkipLine(toks.PeekToken(), "expected ',' or target or EOL after operand"); + break; } - - ReportErrorAndSkipLine(toks.PeekToken(), "unexpected token: {0}", toks.PeekToken()); break; - } + } + + ReportErrorAndSkipLine(toks.PeekToken(), "unexpected token: {0}", toks.PeekToken()); + break; } } - - return null; } - [CanBeNull] - AsmLine TryParseLabel(Token head) + AsmLine? TryParseLabel(Token head) { + Debug.Assert(toks != null); + if (head.Type == TokenType.Symbol) { switch (toks.PeekToken().Type) @@ -362,13 +366,13 @@ namespace Zapf.Parsing return null; } - [NotNull] AsmExpr ParseExprOne() { + Debug.Assert(toks != null); + return ParseExprOne(toks.NextToken()); } - [NotNull] AsmExpr ParseExprOne(Token head) { switch (head.Type) @@ -406,15 +410,17 @@ namespace Zapf.Parsing } } - [NotNull] AsmExpr ParseExpr() { + Debug.Assert(toks != null); + return ParseExpr(toks.NextToken()); } - [NotNull] AsmExpr ParseExpr(Token head) { + Debug.Assert(toks != null); + var result = ParseExprOne(head); while (toks.PeekToken().Type == TokenType.Plus) @@ -428,9 +434,10 @@ namespace Zapf.Parsing return result; } - [CanBeNull] - AsmExpr TryParseExpr() + AsmExpr? TryParseExpr() { + Debug.Assert(toks != null); + return CanStartExpr(toks.PeekToken().Type) ? ParseExpr() : null; } @@ -442,8 +449,10 @@ namespace Zapf.Parsing } } - AsmLine TryParseDirective(Token head) + AsmLine? TryParseDirective(Token head) { + Debug.Assert(toks != null); + if (head.Type == TokenType.Symbol) { if (toks.PeekToken().Type == TokenType.Equals) @@ -489,9 +498,10 @@ namespace Zapf.Parsing return null; } - [NotNull] AsmLine ParseUnrecognizedInstruction(Token head) { + Debug.Assert(toks != null); + var result = new BareSymbolLine(head.Text); bool betweenOperands = true; @@ -535,12 +545,14 @@ namespace Zapf.Parsing #region Directive Handlers - [NotNull] delegate AsmLine DirectiveParseHandler(Token head); + delegate AsmLine DirectiveParseHandler(Token head); readonly IReadOnlyDictionary directiveDict; void MatchEndOfDirective() { + Debug.Assert(toks != null); + switch (toks.PeekToken().Type) { case TokenType.EndOfLine: @@ -558,6 +570,8 @@ namespace Zapf.Parsing bool TryMatchComma() { + Debug.Assert(toks != null); + if (toks.PeekToken().Type == TokenType.Comma) { toks.NextToken(); @@ -569,6 +583,8 @@ namespace Zapf.Parsing void MatchComma() { + Debug.Assert(toks != null); + if (!TryMatchComma()) { ReportErrorAndSkipExpr(toks.PeekToken(), "expected ','"); @@ -577,6 +593,8 @@ namespace Zapf.Parsing bool TryMatchColon() { + Debug.Assert(toks != null); + if (toks.PeekToken().Type == TokenType.Colon) { toks.NextToken(); @@ -588,6 +606,8 @@ namespace Zapf.Parsing void MatchColon() { + Debug.Assert(toks != null); + if (!TryMatchColon()) { ReportErrorAndSkipExpr(toks.PeekToken(), "expected ':'"); @@ -596,6 +616,8 @@ namespace Zapf.Parsing bool TryMatchEquals() { + Debug.Assert(toks != null); + if (toks.PeekToken().Type == TokenType.Equals) { toks.NextToken(); @@ -607,6 +629,8 @@ namespace Zapf.Parsing string MatchSymbol() { + Debug.Assert(toks != null); + if (toks.PeekToken().Type == TokenType.Symbol) return toks.NextToken().Text; @@ -616,6 +640,8 @@ namespace Zapf.Parsing string MatchString() { + Debug.Assert(toks != null); + if (toks.PeekToken().Type == TokenType.String) return toks.NextToken().Text; @@ -623,14 +649,12 @@ namespace Zapf.Parsing return "???"; } - [NotNull] AsmLine IgnoreDirective(Token head) { SkipLine(); return new NullDirective(); } - [NotNull] AsmLine ParseAlignDirective(Token head) { var divisor = ParseExpr(); @@ -638,7 +662,6 @@ namespace Zapf.Parsing return new AlignDirective(divisor); } - [NotNull] AsmLine ParseByteDirective(Token head) { var result = new ByteDirective(); @@ -650,7 +673,6 @@ namespace Zapf.Parsing return result; } - [NotNull] AsmLine ParseChrsetDirective(Token head) { var alphabetNum = ParseExpr(); @@ -663,28 +685,24 @@ namespace Zapf.Parsing return new ChrsetDirective(alphabetNum, characters); } - [NotNull] AsmLine ParseEndDirective(Token head) { MatchEndOfDirective(); return new EndDirective(); } - [NotNull] AsmLine ParseEndiDirective(Token head) { MatchEndOfDirective(); return new EndiDirective(); } - [NotNull] AsmLine ParseEndtDirective(Token head) { MatchEndOfDirective(); return new EndtDirective(); } - [NotNull] AsmLine ParseFstrDirective(Token head) { var name = MatchSymbol(); @@ -694,7 +712,6 @@ namespace Zapf.Parsing return new FstrDirective(name, text); } - [NotNull] AsmLine ParseFunctDirective(Token head) { var result = new FunctDirective(MatchSymbol()); @@ -716,7 +733,6 @@ namespace Zapf.Parsing return result; } - [NotNull] AsmLine ParseGstrDirective(Token head) { var name = MatchSymbol(); @@ -726,11 +742,10 @@ namespace Zapf.Parsing return new GstrDirective(name, text); } - [NotNull] AsmLine ParseGvarDirective(Token head) { var name = MatchSymbol(); - AsmExpr initialValue; + AsmExpr? initialValue; if (TryMatchEquals()) { initialValue = ParseExpr(); @@ -746,7 +761,6 @@ namespace Zapf.Parsing return new GvarDirective(name, initialValue); } - [NotNull] AsmLine ParseInsertDirective(Token head) { var filename = MatchString(); @@ -754,7 +768,6 @@ namespace Zapf.Parsing return new InsertDirective(filename); } - [NotNull] AsmLine ParseLangDirective(Token head) { var langId = ParseExpr(); @@ -764,7 +777,6 @@ namespace Zapf.Parsing return new LangDirective(langId, escapeChar); } - [NotNull] AsmLine ParseLenDirective(Token head) { var text = MatchString(); @@ -772,7 +784,6 @@ namespace Zapf.Parsing return new LenDirective(text); } - [NotNull] AsmLine ParseNewDirective(Token head) { var version = TryParseExpr(); @@ -780,7 +791,6 @@ namespace Zapf.Parsing return new NewDirective(version); } - [NotNull] AsmLine ParseObjectDirective(Token head) { var name = MatchSymbol(); @@ -798,7 +808,8 @@ namespace Zapf.Parsing MatchComma(); var propTableOrChild = ParseExpr(); // proptable or child - AsmExpr flags3, parent, sibling, child, propTable; + AsmExpr? flags3; + AsmExpr parent, sibling, child, propTable; if (TryMatchComma()) { // flags3 provided @@ -821,7 +832,6 @@ namespace Zapf.Parsing return new ObjectDirective(name, flags1, flags2, flags3, parent, sibling, child, propTable); } - [NotNull] AsmLine ParsePropDirective(Token head) { var size = ParseExpr(); @@ -831,14 +841,12 @@ namespace Zapf.Parsing return new PropDirective(size, prop); } - [NotNull] AsmLine ParseSoundDirective(Token head) { MatchEndOfDirective(); return new SoundDirective(); } - [NotNull] AsmLine ParseStrDirective(Token head) { var text = MatchString(); @@ -846,7 +854,6 @@ namespace Zapf.Parsing return new StrDirective(text); } - [NotNull] AsmLine ParseStrlDirective(Token head) { var text = MatchString(); @@ -854,7 +861,6 @@ namespace Zapf.Parsing return new StrlDirective(text); } - [NotNull] AsmLine ParseTableDirective(Token head) { var size = TryParseExpr(); @@ -862,14 +868,12 @@ namespace Zapf.Parsing return new TableDirective(size); } - [NotNull] AsmLine ParseTimeDirective(Token head) { MatchEndOfDirective(); return new TimeDirective(); } - [NotNull] AsmLine ParseVocbegDirective(Token head) { var recordSize = ParseExpr(); @@ -879,14 +883,12 @@ namespace Zapf.Parsing return new VocbegDirective(recordSize, keySize); } - [NotNull] AsmLine ParseVocendDirective(Token head) { MatchEndOfDirective(); return new VocendDirective(); } - [NotNull] AsmLine ParseWordDirective(Token head) { var result = new WordDirective(); @@ -898,7 +900,6 @@ namespace Zapf.Parsing return result; } - [NotNull] AsmLine ParseZwordDirective(Token head) { var text = MatchString(); @@ -906,7 +907,6 @@ namespace Zapf.Parsing return new ZwordDirective(text); } - [NotNull] AsmLine ParseDebugActionDirective(Token head) { var number = ParseExpr(); @@ -916,7 +916,6 @@ namespace Zapf.Parsing return new DebugActionDirective(number, name); } - [NotNull] AsmLine ParseDebugArrayDirective(Token head) { var number = ParseExpr(); @@ -926,7 +925,6 @@ namespace Zapf.Parsing return new DebugArrayDirective(number, name); } - [NotNull] AsmLine ParseDebugAttrDirective(Token head) { var number = ParseExpr(); @@ -936,7 +934,6 @@ namespace Zapf.Parsing return new DebugAttrDirective(number, name); } - [NotNull] AsmLine ParseDebugFileDirective(Token head) { var number = ParseExpr(); @@ -948,7 +945,6 @@ namespace Zapf.Parsing return new DebugFileDirective(number, includeName, actualName); } - [NotNull] AsmLine ParseDebugGlobalDirective(Token head) { var number = ParseExpr(); @@ -958,7 +954,6 @@ namespace Zapf.Parsing return new DebugGlobalDirective(number, name); } - [NotNull] AsmLine ParseDebugLineDirective(Token head) { var file = ParseExpr(); @@ -970,7 +965,6 @@ namespace Zapf.Parsing return new DebugLineDirective(file, line, column); } - [NotNull] AsmLine ParseDebugMapDirective(Token head) { var key = MatchString(); @@ -979,7 +973,6 @@ namespace Zapf.Parsing return new DebugMapDirective(key, value); } - [NotNull] AsmLine ParseDebugObjectDirective(Token head) { var number = ParseExpr(); @@ -1004,7 +997,6 @@ namespace Zapf.Parsing endFile, endLine, endColumn); } - [NotNull] AsmLine ParseDebugPropDirective(Token head) { var number = ParseExpr(); @@ -1014,7 +1006,6 @@ namespace Zapf.Parsing return new DebugPropDirective(number, name); } - [NotNull] AsmLine ParseDebugRoutineDirective(Token head) { var file = ParseExpr(); @@ -1033,7 +1024,6 @@ namespace Zapf.Parsing return new DebugRoutineDirective(file, line, column, name, locals); } - [NotNull] AsmLine ParseDebugRoutineEndDirective(Token head) { var file = ParseExpr(); diff --git a/src/Zapf.Parsing/Zapf.Parsing.csproj b/src/Zapf.Parsing/Zapf.Parsing.csproj index 23008e6..ce54c0b 100644 --- a/src/Zapf.Parsing/Zapf.Parsing.csproj +++ b/src/Zapf.Parsing/Zapf.Parsing.csproj @@ -1,8 +1,9 @@  - netstandard2.0 + netstandard2.1 Provides an assembly language parser for ZAPF. + enable diff --git a/src/Zapf/.editorconfig b/src/Zapf/.editorconfig new file mode 100644 index 0000000..e8d8986 --- /dev/null +++ b/src/Zapf/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# RCS1139: Add summary element to documentation comment. +dotnet_diagnostic.RCS1139.severity = silent diff --git a/src/Zapf/AbbrevFinder.cs b/src/Zapf/AbbrevFinder.cs index c169234..6a13ed0 100644 --- a/src/Zapf/AbbrevFinder.cs +++ b/src/Zapf/AbbrevFinder.cs @@ -57,7 +57,7 @@ namespace Zapf /// Adds some text to the accumulator. /// /// The text to add. - public void AddText([NotNull] string text) + public void AddText(string text) { allText.Append(text); allText.Append('\0'); @@ -92,7 +92,7 @@ namespace Zapf static readonly char[] wordDelimiters = { ' ', '.', ',', ':', ';', '!', '?', '(', ')', '/' }; - static IEnumerable FindWords([NotNull] string text) + static IEnumerable FindWords(string text) { int wordStart = -1; bool inWord = false; @@ -144,7 +144,7 @@ namespace Zapf return zchars - 2; } - int CountAppearances([NotNull] Horspool pattern) + int CountAppearances(Horspool pattern) { #if DEBUG_ABBREV var stopw = new Stopwatch(); diff --git a/src/Zapf/BinaryDebugFileWriter.cs b/src/Zapf/BinaryDebugFileWriter.cs index 5a3ea0e..0e330f7 100644 --- a/src/Zapf/BinaryDebugFileWriter.cs +++ b/src/Zapf/BinaryDebugFileWriter.cs @@ -49,7 +49,7 @@ namespace Zapf stream.Close(); } - public void WriteMap([NotNull] IEnumerable> map) + public void WriteMap(IEnumerable> map) { WriteDebugByte(DEBF.MAP_DBR); foreach (var pair in map) @@ -60,34 +60,34 @@ namespace Zapf WriteDebugByte(0); } - public void WriteHeader([NotNull] byte[] header) + public void WriteHeader(byte[] header) { WriteDebugByte(DEBF.HEADER_DBR); stream.Write(header, 0, 64); } - public void WriteAction(ushort value, [NotNull] string name) + public void WriteAction(ushort value, string name) { WriteDebugByte(DEBF.ACTION_DBR); WriteDebugWord(value); WriteDebugString(name); } - public void WriteArray(ushort offsetFromGlobal, [NotNull] string name) + public void WriteArray(ushort offsetFromGlobal, string name) { WriteDebugByte(DEBF.ARRAY_DBR); WriteDebugWord(offsetFromGlobal); WriteDebugString(name); } - public void WriteAttr(ushort value, [NotNull] string name) + public void WriteAttr(ushort value, string name) { WriteDebugByte(DEBF.ATTR_DBR); WriteDebugWord(value); WriteDebugString(name); } - public void WriteClass([NotNull] string name, LineRef start, LineRef end) + public void WriteClass(string name, LineRef start, LineRef end) { WriteDebugByte(DEBF.CLASS_DBR); WriteDebugString(name); @@ -95,14 +95,14 @@ namespace Zapf WriteDebugLineRef(end); } - public void WriteFakeAction(ushort value, [NotNull] string name) + public void WriteFakeAction(ushort value, string name) { WriteDebugByte(DEBF.FAKE_ACTION_DBR); WriteDebugWord(value); WriteDebugString(name); } - public void WriteFile(byte number, [NotNull] string includeName, [NotNull] string actualName) + public void WriteFile(byte number, string includeName, string actualName) { WriteDebugByte(DEBF.FILE_DBR); WriteDebugByte(number); @@ -110,7 +110,7 @@ namespace Zapf WriteDebugString(actualName); } - public void WriteGlobal(byte number, [NotNull] string name) + public void WriteGlobal(byte number, string name) { WriteDebugByte(DEBF.GLOBAL_DBR); WriteDebugByte(number); @@ -128,7 +128,7 @@ namespace Zapf routinePoints++; } - public void WriteObject(ushort number, [NotNull] string name, LineRef start, LineRef end) + public void WriteObject(ushort number, string name, LineRef start, LineRef end) { WriteDebugByte(DEBF.OBJECT_DBR); WriteDebugWord(number); @@ -137,14 +137,14 @@ namespace Zapf WriteDebugLineRef(end); } - public void WriteProp(ushort number, [NotNull] string name) + public void WriteProp(ushort number, string name) { WriteDebugByte(DEBF.PROP_DBR); WriteDebugWord(number); WriteDebugString(name); } - public void StartRoutine(LineRef start, int address, [NotNull] string name, [NotNull] IEnumerable locals) + public void StartRoutine(LineRef start, int address, string name, IEnumerable locals) { WriteDebugByte(DEBF.ROUTINE_DBR); WriteDebugWord(nextRoutineNumber); @@ -218,7 +218,7 @@ namespace Zapf stream.WriteByte(lineRef.Col); } - void WriteDebugString([NotNull] string s) + void WriteDebugString(string s) { var bytes = Encoding.ASCII.GetBytes(s); stream.Write(bytes, 0, bytes.Length); diff --git a/src/Zapf/Context.cs b/src/Zapf/Context.cs index 6246a8a..faa47d4 100644 --- a/src/Zapf/Context.cs +++ b/src/Zapf/Context.cs @@ -18,10 +18,10 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Text; -using JetBrains.Annotations; using Zilf.Common.StringEncoding; using Zapf.Parsing.Diagnostics; using Zapf.Parsing.Instructions; @@ -35,8 +35,9 @@ namespace Zapf class Context : IErrorSink, IDisposable { public bool Quiet, InformMode, ListAddresses, AbbreviateMode, XmlDebugMode; - public string InFile, OutFile, DebugFile; - public string Creator = "ZAPF", Serial; + public string? InFile, OutFile, DebugFile; + public string? Creator = "ZAPF"; + public string? Serial; public byte ZVersion, ZFlags; public ushort ZFlags2; public short? Release; @@ -45,28 +46,20 @@ namespace Zapf public int ErrorCount, WarningCount; - [CanBeNull] - public Dictionary> OpcodeDict; + public Dictionary>? OpcodeDict; - [NotNull] public StringEncoder StringEncoder; - [NotNull] public readonly AbbrevFinder AbbrevFinder; - [NotNull] public readonly Dictionary LocalSymbols; - [NotNull] public readonly Dictionary GlobalSymbols; - [NotNull] public readonly List Fixups; - [CanBeNull] - public IDebugFileWriter DebugWriter; + public IDebugFileWriter? DebugWriter; - [NotNull] public readonly Dictionary DebugFileMap; /// @@ -83,24 +76,22 @@ namespace Zapf public int? TableStart, TableSize; public bool InVocab; - public OpenFileDelegate InterceptOpenFile; - public FileExistsDelegate InterceptFileExists; + public OpenFileDelegate? InterceptOpenFile; + public FileExistsDelegate? InterceptFileExists; #pragma warning disable CS0649 - public GetDebugWriterDelegate InterceptGetDebugWriter; + public GetDebugWriterDelegate? InterceptGetDebugWriter; #pragma warning restore CS0649 char? LanguageEscapeChar { get; set; } - [NotNull] IDictionary LanguageSpecialChars { get; } - Stream stream; - Stream prevStream; + Stream? stream; + Stream? prevStream; int position; int globalVarCount, objectCount; - [NotNull] readonly Stack fileStack; int vocabStart, vocabRecSize, vocabKeySize; @@ -121,7 +112,7 @@ namespace Zapf /// /// The symbol of the function that owns the reassembly scope. /// - Symbol reassemblySymbol; + Symbol? reassemblySymbol; /// /// The local labels that have been encountered in the current reassembly scope @@ -131,7 +122,6 @@ namespace Zapf /// When one of these labels is defined, we rewind to the beginning of the /// reassembly scope and start again using the new value. /// - [NotNull] readonly Dictionary reassemblyLabels; // TODO: convert to HashSet /// @@ -142,7 +132,6 @@ namespace Zapf /// /// These are checked at the end of the reassembly scope. /// - [NotNull] readonly Dictionary deferredGlobalLabelChecks; public Context() @@ -191,7 +180,7 @@ namespace Zapf } /// is undefined. - public void WriteByte([NotNull] Symbol sym) + public void WriteByte(Symbol sym) { switch (sym.Type) { @@ -221,7 +210,7 @@ namespace Zapf } /// is undefined. - public void WriteWord([NotNull] Symbol sym) + public void WriteWord(Symbol sym) { switch (sym.Type) { @@ -250,7 +239,7 @@ namespace Zapf return (byte)stream.ReadByte(); } - public void WriteZString([NotNull] string str, bool withLength, StringEncoderMode mode = StringEncoderMode.Normal) + public void WriteZString(string str, bool withLength, StringEncoderMode mode = StringEncoderMode.Normal) { MaybeProcessEscapeChars(ref str); @@ -265,7 +254,7 @@ namespace Zapf stream?.Write(zstr, 0, zstr.Length); } - void MaybeProcessEscapeChars([NotNull] ref string str) + void MaybeProcessEscapeChars(ref string str) { // ReSharper disable once ConditionIsAlwaysTrueOrFalse // false alarm! if (!(LanguageEscapeChar is char escape) || str.IndexOf((char)LanguageEscapeChar) < 0) @@ -309,7 +298,7 @@ namespace Zapf public void WriteZWord(string str) { MaybeProcessEscapeChars(ref str); - + var zstr = StringEncoder.Encode(str, ZWordChars, StringEncoderMode.NoAbbreviations); position += zstr.Length; @@ -338,7 +327,7 @@ namespace Zapf if (InVocab) { // restore stream - var buffer = ((MemoryStream)stream).GetBuffer(); + var buffer = ((MemoryStream?)stream)!.GetBuffer(); var bufLen = (int)stream.Length; stream = prevStream; @@ -390,7 +379,11 @@ namespace Zapf { if (VocabCompare(buffer, i - 1, i) == 0) { - Errors.Warn(this, src, "vocab collision between {0} and {1}", VocabLabel(i - 1), VocabLabel(i)); + Errors.Warn(this, + src, + "vocab collision between {0} and {1}", + VocabLabel(i - 1) ?? "", + VocabLabel(i) ?? ""); } } } @@ -426,7 +419,7 @@ namespace Zapf vocabKeySize = 0; } - int MapVocabAddress(int oldAddress, [NotNull] int[] newIndexes) + int MapVocabAddress(int oldAddress, int[] newIndexes) { var oldOffsetFromVocab = oldAddress - vocabStart; var oldIndex = oldOffsetFromVocab / vocabRecSize; @@ -468,8 +461,7 @@ namespace Zapf return 0; } - [CanBeNull] - string VocabLabel(int index) + string? VocabLabel(int index) { foreach (var sym in GlobalSymbols.Values) { @@ -499,6 +491,8 @@ namespace Zapf public void OpenOutput() { + Debug.Assert(OutFile != null); + if (Path.GetExtension(OutFile) == ".z#") OutFile = Path.ChangeExtension(OutFile, ".z" + ZVersion); @@ -514,6 +508,8 @@ namespace Zapf public void OpenDebugFile() { + Debug.Assert(DebugFile != null); + var debugStream = OpenFile(DebugFile, true); if (InterceptGetDebugWriter != null) @@ -635,19 +631,19 @@ namespace Zapf reassemblySymbol = symbol; } - public bool CausesReassembly([NotNull] string label) + public bool CausesReassembly(string label) { return reassemblyLabels.ContainsKey(label); } public bool InReassemblyScope => reassemblyPosition != -1; - public void MarkUnknownBranch([NotNull] string label) + public void MarkUnknownBranch(string label) { reassemblyLabels[label] = true; } - public void DeferGlobalLabelStabilityCheck([NotNull] Symbol sym, [NotNull] Action checkMismatch) + public void DeferGlobalLabelStabilityCheck(Symbol sym, Action checkMismatch) { if (!deferredGlobalLabelChecks.ContainsKey(sym)) { @@ -655,7 +651,7 @@ namespace Zapf } } - public int Reassemble([NotNull] string curLabel) + public int Reassemble(string curLabel) { if (LocalSymbols.TryGetValue(curLabel, out var sym)) sym.Value = position; @@ -668,16 +664,21 @@ namespace Zapf foreach (var i in LocalSymbols.Values) { if (i.Type == SymbolType.Label) + { i.Phantom = true; + } else + { + Debug.Assert(i.Name != null); goners.Enqueue(i.Name); + } } while (goners.Count > 0) LocalSymbols.Remove(goners.Dequeue()); // make function symbol into a phantom - reassemblySymbol.Phantom = true; + reassemblySymbol!.Phantom = true; // clean up reassembly state and rewind to the beginning of the scope reassemblyLabels.Clear(); @@ -712,7 +713,7 @@ namespace Zapf } /// The global variable moved unexpectedly between passes. - public void AddGlobalVar([NotNull] string name) + public void AddGlobalVar(string name) { int num = 16 + globalVarCount++; @@ -721,7 +722,7 @@ namespace Zapf sym = new Symbol(name, SymbolType.Variable, num); GlobalSymbols.Add(name, sym); } - else if (sym.Phantom && sym.Type == SymbolType.Variable) + else if (sym!.Phantom && sym.Type == SymbolType.Variable) { if (sym.Value != num) { @@ -744,7 +745,7 @@ namespace Zapf /// The object moved unexpectedly between passes. /// The object was redefined. - public void AddObject([NotNull] string name) + public void AddObject(string name) { int num = 1 + objectCount++; @@ -753,7 +754,7 @@ namespace Zapf sym = new Symbol(name, SymbolType.Object, num); GlobalSymbols.Add(name, sym); } - else if (sym.Phantom && sym.Type == SymbolType.Object) + else if (sym!.Phantom && sym.Type == SymbolType.Object) { if (sym.Value != num) { @@ -837,7 +838,7 @@ namespace Zapf StringsOffset = 0; } - public void HandleWarning([NotNull] Warning warning) + public void HandleWarning(Warning warning) { WarningCount++; @@ -847,7 +848,7 @@ namespace Zapf Console.Error.WriteLine("warning: {0}", warning.Message); } - public void HandleSeriousError([NotNull] SeriousError ser) + public void HandleSeriousError(SeriousError ser) { ErrorCount++; @@ -857,7 +858,7 @@ namespace Zapf Console.Error.WriteLine("error: {0}", ser.Message); } - public void HandleFatalError([NotNull] FatalError fer) + public void HandleFatalError(FatalError fer) { ErrorCount++; @@ -886,7 +887,7 @@ namespace Zapf } [SuppressMessage("ReSharper", "ConvertIfStatementToReturnStatement")] - public string FindInsertedFile(string name) + public string? FindInsertedFile(string name) { if (FileExists(name)) return name; @@ -938,12 +939,9 @@ namespace Zapf } } - public int GetHeaderValue([NotNull] string name, bool required) - { - return GetHeaderValue(name, null, required); - } + public int GetHeaderValue(string name, bool required) => GetHeaderValue(name, null, required); - public int GetHeaderValue([NotNull] string name1, string name2, bool required) + public int GetHeaderValue(string name1, string? name2, bool required) { if (GlobalSymbols.TryGetValue(name1, out var sym) || (name2 != null && GlobalSymbols.TryGetValue(name2, out sym))) @@ -959,12 +957,10 @@ namespace Zapf return 0; } } - else - { - if (required) - Errors.Serious(this, "required global symbol '{0}' is missing", name1); - return 0; - } + + if (required) + Errors.Serious(this, "required global symbol '{0}' is missing", name1); + return 0; } } @@ -1005,8 +1001,7 @@ namespace Zapf /// /// The symbol's name in the source code. /// - [CanBeNull] - public readonly string Name; + public readonly string? Name; /// /// The symbol's type. /// @@ -1031,7 +1026,7 @@ namespace Zapf Value = value; } - public Symbol([CanBeNull] string name, SymbolType type, int value) + public Symbol(string? name, SymbolType type, int value) { Name = name; Type = type; diff --git a/src/Zapf/IDebugFileWriter.cs b/src/Zapf/IDebugFileWriter.cs index 2e561c1..3989980 100644 --- a/src/Zapf/IDebugFileWriter.cs +++ b/src/Zapf/IDebugFileWriter.cs @@ -33,24 +33,17 @@ namespace Zapf public readonly ushort Line; public readonly byte Col; - public static bool operator ==(LineRef a, LineRef b) - { - return a.File == b.File && - a.Line == b.Line && - a.Col == b.Col; - } + public static bool operator ==(LineRef a, LineRef b) => + a.File == b.File && + a.Line == b.Line && + a.Col == b.Col; - public static bool operator !=(LineRef a, LineRef b) - { - return a.File != b.File || - a.Line != b.Line || - a.Col != b.Col; - } + public static bool operator !=(LineRef a, LineRef b) => + a.File != b.File || + a.Line != b.Line || + a.Col != b.Col; - public override bool Equals(object obj) - { - return obj is LineRef lineRef && lineRef == this; - } + public override bool Equals(object? obj) => obj is LineRef lineRef && lineRef == this; public override int GetHashCode() { diff --git a/src/Zapf/Program.cs b/src/Zapf/Program.cs index 6cf8634..08b1b0d 100644 --- a/src/Zapf/Program.cs +++ b/src/Zapf/Program.cs @@ -40,7 +40,7 @@ namespace Zapf public const byte DEFAULT_ZVERSION = 3; - public static int Main([ItemNotNull] [NotNull] string[] args) + public static int Main(string[] args) { var ctx = ParseArgs(args); if (ctx == null) @@ -113,15 +113,13 @@ namespace Zapf } } - [NotNull] internal static string GetVersion() => typeof(Program).Assembly.GetCustomAttribute() - .InformationalVersion ?? ""; + ?.InformationalVersion ?? ""; - [NotNull] internal static string GetBanner() => $"ZAPF {GetVersion()}"; - static void FindAndPrintAbbreviations([NotNull] Context ctx) + static void FindAndPrintAbbreviations(Context ctx) { if (ctx.AbbreviateMode) { @@ -154,7 +152,7 @@ namespace Zapf } } - static void PrintLabelAddresses([NotNull] Context ctx) + static void PrintLabelAddresses(Context ctx) { if (ctx.ListAddresses) { @@ -197,7 +195,6 @@ namespace Zapf } } - [NotNull] static string SanitizeString(string text) { var sb = new StringBuilder(text); @@ -209,7 +206,6 @@ namespace Zapf return sb.ToString(); } - [NotNull] internal static Dictionary> MakeOpcodeDict( int zversion, bool inform) { @@ -227,7 +223,7 @@ namespace Zapf foreach (ZOpAttribute attr in attrs) if (effectiveVersion >= attr.MinVer && effectiveVersion <= attr.MaxVer) { - var pair = new KeyValuePair((ushort)fi.GetValue(null), attr); + var pair = new KeyValuePair((ushort)fi.GetValue(null)!, attr); result.Add(inform ? attr.InformName : attr.ClassicName, pair); break; } @@ -236,10 +232,9 @@ namespace Zapf return result; } - [CanBeNull] - internal static Context ParseArgs([ItemNotNull] [NotNull] IReadOnlyList args) + internal static Context? ParseArgs(IReadOnlyList args) { - var result = new Context(); + using var result = new Context(); for (int i = 0; i < args.Count; i++) { @@ -334,9 +329,10 @@ General switches: } /// An occurred while reading the input file(s). - internal static void Assemble([NotNull] Context ctx) + internal static void Assemble(Context ctx) { List file; + Debug.Assert(ctx.InFile != null); ctx.PushFile(ctx.InFile); try { @@ -418,6 +414,8 @@ General switches: if (sym.Value < 65536) continue; + Debug.Assert(sym.Name != null); + switch (sym.Type) { case SymbolType.Function: @@ -480,7 +478,7 @@ General switches: /// The node to process. /// The current node's index. The method may change this /// to rewind the source file. - static void PassOne(Context ctx, [NotNull] AsmLine node, ref int nodeIndex) + static void PassOne(Context ctx, AsmLine node, ref int nodeIndex) { switch (node) { @@ -545,7 +543,7 @@ General switches: } } - static void WriteHeader([NotNull] Context ctx, bool strict) + static void WriteHeader(Context ctx, bool strict) { ctx.WriteByte(ctx.ZVersion); ctx.WriteByte(ctx.ZFlags); @@ -591,14 +589,13 @@ General switches: Errors.ThrowSerious("ENDLOD must be after IMPURE"); } - [CanBeNull] - static Symbol GetDebugMapValue([NotNull] Context ctx, [NotNull] string name) + static Symbol? GetDebugMapValue(Context ctx, string name) { ctx.GlobalSymbols.TryGetValue(name, out var sym); return sym; } - static void FinalizeOutput([NotNull] Context ctx) + static void FinalizeOutput(Context ctx) { const int MINSIZE = 512; @@ -704,27 +701,29 @@ General switches: Debug.Assert(ctx.DebugWriter != null); // finish map - if (!ctx.DebugFileMap.ContainsKey(DEBF.AbbrevMapName)) - ctx.DebugFileMap[DEBF.AbbrevMapName] = GetDebugMapValue(ctx, "WORDS"); - if (!ctx.DebugFileMap.ContainsKey(DEBF.GlobalsMapName)) - ctx.DebugFileMap[DEBF.GlobalsMapName] = GetDebugMapValue(ctx, "GLOBAL"); + void CopyDebugMapValue(string debfName, string symbolName) + { + if (!ctx.DebugFileMap.ContainsKey(debfName) && GetDebugMapValue(ctx, symbolName) is Symbol sym) + ctx.DebugFileMap[debfName] = sym; + } + + CopyDebugMapValue(DEBF.AbbrevMapName, "WORDS"); + CopyDebugMapValue(DEBF.GlobalsMapName, "GLOBAL"); + CopyDebugMapValue(DEBF.PropsMapName, "OBJECT"); + CopyDebugMapValue(DEBF.VocabMapName, "VOCAB"); + if (!ctx.DebugFileMap.ContainsKey(DEBF.ObjectsMapName)) { var objTable = GetDebugMapValue(ctx, "OBJECT"); if (objTable != null) { - var objTree = new Symbol + ctx.DebugFileMap[DEBF.ObjectsMapName] = new Symbol { Type = objTable.Type, Value = objTable.Value + (ctx.ZVersion < 4 ? 31 : 63) }; - ctx.DebugFileMap[DEBF.ObjectsMapName] = objTree; } } - if (!ctx.DebugFileMap.ContainsKey(DEBF.PropsMapName)) - ctx.DebugFileMap[DEBF.PropsMapName] = GetDebugMapValue(ctx, "OBJECT"); - if (!ctx.DebugFileMap.ContainsKey(DEBF.VocabMapName)) - ctx.DebugFileMap[DEBF.VocabMapName] = GetDebugMapValue(ctx, "VOCAB"); // write map ctx.DebugWriter.WriteMap( @@ -754,7 +753,7 @@ General switches: /// The node to process. /// The current node's index. The method may change this /// to rewind the source file. - static void PassTwo(Context ctx, [NotNull] AsmLine node, ref int nodeIndex) + static void PassTwo(Context ctx, AsmLine node, ref int nodeIndex) { switch (node) { @@ -773,7 +772,7 @@ General switches: } } - static IEnumerable ReadAllCode(Context ctx, [NotNull] IEnumerable roots) + static IEnumerable ReadAllCode(Context ctx, IEnumerable roots) { foreach (var node in roots) { @@ -807,22 +806,20 @@ General switches: } } - static IEnumerable ReadRootsFromFile([NotNull] Context ctx, [NotNull] string path) + static IEnumerable ReadRootsFromFile(Context ctx, string path) { - using (var stream = ctx.OpenFile(path, false)) - { - Debug.Assert(ctx.OpcodeDict != null); - var parser = new ZapParser(ctx, ctx.OpcodeDict); - var result = parser.Parse(stream, path); + using var stream = ctx.OpenFile(path, false); + Debug.Assert(ctx.OpcodeDict != null); + var parser = new ZapParser(ctx, ctx.OpcodeDict); + var result = parser.Parse(stream, path); - if (result.NumberOfSyntaxErrors > 0) - Errors.ThrowFatal("syntax error"); + if (result.NumberOfSyntaxErrors > 0) + Errors.ThrowFatal("syntax error"); - return result.Lines; - } + return result.Lines; } - static Symbol EvalExpr(Context ctx, [NotNull] AsmExpr node) + static Symbol EvalExpr(Context ctx, AsmExpr node) { switch (node) { @@ -859,7 +856,7 @@ General switches: throw new NotImplementedException($"Unimplemented symbol addition: {left.Type} + {right.Type}"); // we can add numbers and non-packed addresses - bool Addable(SymbolType type) + static bool Addable(SymbolType type) { switch (type) { @@ -878,12 +875,12 @@ General switches: } } - static void EvalOperand(Context ctx, AsmExpr node, out byte type, out ushort value, [CanBeNull] out Fixup fixup) + static void EvalOperand(Context ctx, AsmExpr node, out byte type, out ushort value, out Fixup? fixup) { EvalOperand(ctx, node, out type, out value, out fixup, false); } - static void EvalOperand(Context ctx, AsmExpr node, out byte type, out ushort value, [CanBeNull] out Fixup fixup, + static void EvalOperand(Context ctx, AsmExpr node, out byte type, out ushort value, out Fixup? fixup, bool allowLocalLabel) { fixup = null; @@ -957,7 +954,7 @@ General switches: type = OPERAND_BYTE; } - static bool IsLongConstant(Context ctx, [NotNull] AsmExpr node) + static bool IsLongConstant(Context ctx, AsmExpr node) { switch (node) { @@ -998,7 +995,7 @@ General switches: } } - static void HandleDirective(Context ctx, [NotNull] AsmLine node, int nodeIndex, bool assembling) + static void HandleDirective(Context ctx, AsmLine node, int nodeIndex, bool assembling) { // local scope is terminated by any directive except .DEBUG_LINE (not counting labels) if (!(node is DebugLineDirective)) @@ -1139,6 +1136,7 @@ General switches: { // global labels inside the vocab table need to be fixed up at .VOCEND, // since they may refer to other vocab words + Debug.Assert(sym.Name != null); var fixup = new Fixup(sym.Name) { Location = ctx.Position }; ctx.Fixups.Add(fixup); } @@ -1288,7 +1286,7 @@ General switches: } } - static void HandleDebugDirective([NotNull] Context ctx, [NotNull] DebugDirective node) + static void HandleDebugDirective(Context ctx, DebugDirective node) { Debug.Assert(ctx.DebugWriter != null); @@ -1323,7 +1321,7 @@ General switches: } var sym2 = EvalExpr(ctx, darr.Number); ctx.DebugWriter.WriteArray( - (ushort)(sym2.Value - sym1.Value), + (ushort)(sym2.Value - sym1!.Value), darr.Name); break; @@ -1415,7 +1413,7 @@ General switches: } } - static void BeginFunction([NotNull] [ProvidesContext] Context ctx, [NotNull] FunctDirective node, int nodeIndex) + static void BeginFunction([ProvidesContext] Context ctx, FunctDirective node, int nodeIndex) { var localNames = new List(); var localValues = new List(); @@ -1457,7 +1455,7 @@ General switches: sym = new Symbol(name, SymbolType.Function, paddr); ctx.GlobalSymbols.Add(name, sym); } - else if (sym.Type != SymbolType.Unknown && (!sym.Phantom || sym.Type != SymbolType.Function)) + else if (sym!.Type != SymbolType.Unknown && (!sym.Phantom || sym.Type != SymbolType.Function)) { Errors.ThrowSerious("function redefined: " + name); } @@ -1487,13 +1485,13 @@ General switches: } } - static void AlignUnpacked([NotNull] Context ctx, int divisor) + static void AlignUnpacked(Context ctx, int divisor) { while (ctx.Position % divisor != 0) ctx.WriteByte(0); } - static void AlignPacked([NotNull] Context ctx, ref int offset) + static void AlignPacked(Context ctx, ref int offset) { if (ctx.UsePackingOffsets && offset == 0) { @@ -1508,17 +1506,17 @@ General switches: ctx.WriteByte(0); } - static void AlignRoutine([NotNull] Context ctx) + static void AlignRoutine(Context ctx) { AlignPacked(ctx, ref ctx.FunctionsOffset); } - static void AlignString([NotNull] Context ctx) + static void AlignString(Context ctx) { AlignPacked(ctx, ref ctx.StringsOffset); } - static void PackString([NotNull] Context ctx, [NotNull] GstrDirective node) + static void PackString(Context ctx, GstrDirective node) { string name = node.Name; @@ -1530,7 +1528,7 @@ General switches: sym = new Symbol(name, SymbolType.String, paddr); ctx.GlobalSymbols.Add(name, sym); } - else if (sym.Type != SymbolType.Unknown && (!sym.Phantom || sym.Type != SymbolType.String)) + else if (sym!.Type != SymbolType.Unknown && (!sym.Phantom || sym.Type != SymbolType.String)) { Errors.ThrowSerious("string redefined: " + name); } @@ -1548,7 +1546,7 @@ General switches: ctx.WriteZString(node.Text, false); } - static void AddAbbreviation([NotNull] Context ctx, [NotNull] FstrDirective node) + static void AddAbbreviation(Context ctx, FstrDirective node) { if (ctx.StringEncoder.Frozen) Errors.ThrowSerious(node, "abbreviations must be defined before strings"); @@ -1574,9 +1572,9 @@ General switches: static readonly byte[] tmpOperandTypes = new byte[8]; static readonly ushort[] tmpOperandValues = new ushort[8]; - static readonly Fixup[] tmpOperandFixups = new Fixup[8]; + static readonly Fixup?[] tmpOperandFixups = new Fixup[8]; - static void HandleInstruction([NotNull] Context ctx, [NotNull] Instruction node) + static void HandleInstruction(Context ctx, Instruction node) { Debug.Assert(ctx.OpcodeDict != null); var pair = ctx.OpcodeDict[node.Name]; @@ -1641,8 +1639,8 @@ General switches: ctx.WriteByte(b); if (tmpOperandFixups[0] != null) { - tmpOperandFixups[0].Location = ctx.Position; - ctx.Fixups.Add(tmpOperandFixups[0]); + tmpOperandFixups[0]!.Location = ctx.Position; + ctx.Fixups.Add(tmpOperandFixups[0]!); tmpOperandFixups[0] = null; } if (tmpOperandTypes[0] == OPERAND_WORD) @@ -1712,8 +1710,8 @@ General switches: { if (tmpOperandFixups[i] != null) { - tmpOperandFixups[i].Location = ctx.Position; - ctx.Fixups.Add(tmpOperandFixups[i]); + tmpOperandFixups[i]!.Location = ctx.Position; + ctx.Fixups.Add(tmpOperandFixups[i]!); tmpOperandFixups[i] = null; } @@ -1733,9 +1731,9 @@ General switches: } else { - if (ctx.LocalSymbols.TryGetValue(node.StoreTarget, out var sym) == false && - ctx.GlobalSymbols.TryGetValue(node.StoreTarget, out sym) == false || - sym.Type != SymbolType.Variable) + if ((ctx.LocalSymbols.TryGetValue(node.StoreTarget, out var sym) == false && + ctx.GlobalSymbols.TryGetValue(node.StoreTarget, out sym) == false) || + sym!.Type != SymbolType.Variable) { Errors.ThrowSerious(node, "expected local or global variable as store target"); } @@ -1793,7 +1791,7 @@ General switches: } } - static void HandleLabel([NotNull] Context ctx, [NotNull] AsmLine node, ref int nodeIndex) + static void HandleLabel(Context ctx, AsmLine node, ref int nodeIndex) { string name; @@ -1866,7 +1864,7 @@ General switches: else ctx.LocalSymbols.Add(name, new Symbol(name, SymbolType.Label, ctx.Position)); } - else if (sym.Type == SymbolType.Label && sym.Phantom) + else if (sym!.Type == SymbolType.Label && sym.Phantom) { if (sym.Value != ctx.Position) nodeIndex = ctx.Reassemble(name) - 1; diff --git a/src/Zapf/XmlDebugFileWriter.cs b/src/Zapf/XmlDebugFileWriter.cs index 36ea4c3..c6de842 100644 --- a/src/Zapf/XmlDebugFileWriter.cs +++ b/src/Zapf/XmlDebugFileWriter.cs @@ -29,7 +29,7 @@ namespace Zapf readonly XmlWriter xml; bool inRoutine; - public XmlDebugFileWriter([NotNull] Stream debugStream) + public XmlDebugFileWriter(Stream debugStream) { var settings = new XmlWriterSettings() { @@ -52,7 +52,7 @@ namespace Zapf xml.Close(); } - public void StartRoutine(LineRef start, int address, string name, [NotNull] IEnumerable locals) + public void StartRoutine(LineRef start, int address, string name, IEnumerable locals) { xml.WriteStartElement("routine"); @@ -159,7 +159,7 @@ namespace Zapf xml.WriteEndElement(); } - public void WriteFile(byte number, [NotNull] string includeName, [NotNull] string actualName) + public void WriteFile(byte number, string includeName, string actualName) { xml.WriteStartElement("source"); xml.WriteAttributeString("index", number.ToString()); @@ -182,14 +182,14 @@ namespace Zapf xml.WriteEndElement(); } - public void WriteHeader([NotNull] byte[] header) + public void WriteHeader(byte[] header) { xml.WriteStartElement("story-file-prefix"); xml.WriteBase64(header, 0, header.Length); xml.WriteEndElement(); } - public void WriteMap([NotNull] IEnumerable> map) + public void WriteMap(IEnumerable> map) { foreach (var entry in map) { diff --git a/src/Zapf/Zapf.csproj b/src/Zapf/Zapf.csproj index c15d9aa..e27d04f 100644 --- a/src/Zapf/Zapf.csproj +++ b/src/Zapf/Zapf.csproj @@ -1,13 +1,13 @@  - netcoreapp2.2 + netcoreapp3.0 win-x86;win-x64;linux-arm;linux-x64;osx-x64 true - 7.3 Exe An assembler for Z-machine story files. false true + enable diff --git a/src/Zapf/ZapfAssembler.cs b/src/Zapf/ZapfAssembler.cs index 6aa3a2e..753a882 100644 --- a/src/Zapf/ZapfAssembler.cs +++ b/src/Zapf/ZapfAssembler.cs @@ -26,43 +26,38 @@ namespace Zapf { class OpeningFileEventArgs : EventArgs { - public OpeningFileEventArgs([NotNull] string filename, bool writing) + public OpeningFileEventArgs(string filename, bool writing) { FileName = filename; Writing = writing; } - [NotNull] public string FileName { get; } public bool Writing { get; } - [CanBeNull] - public Stream Stream { get; set; } + public Stream? Stream { get; set; } } class CheckingFilePresenceEventArgs : EventArgs { - public CheckingFilePresenceEventArgs([NotNull] string filename) => FileName = filename; + public CheckingFilePresenceEventArgs(string filename) => FileName = filename; - [NotNull] public string FileName { get; } - [CanBeNull] public bool? Exists { get; set; } } class InitializingContextEventArgs : EventArgs { - public InitializingContextEventArgs([NotNull] Context ctx) => Context = ctx; + public InitializingContextEventArgs(Context ctx) => Context = ctx; - [NotNull] public Context Context { get; set; } } struct AssemblyResult { - public AssemblyResult(bool success, Context context) + public AssemblyResult(bool success, Context? context) { Success = success; Context = context; @@ -71,17 +66,16 @@ namespace Zapf public static readonly AssemblyResult Failed = new AssemblyResult(false, null); public bool Success { get; } - public Context Context { get; } + public Context? Context { get; } } sealed class ZapfAssembler { - public event EventHandler OpeningFile; - public event EventHandler CheckingFilePresence; - public event EventHandler InitializingContext; + public event EventHandler? OpeningFile; + public event EventHandler? CheckingFilePresence; + public event EventHandler? InitializingContext; - [NotNull] - Stream OpenFile([NotNull] string path, bool writing) + Stream OpenFile(string path, bool writing) { var handler = OpeningFile; if (handler != null) @@ -116,8 +110,7 @@ namespace Zapf return File.Exists(path); } - [NotNull] - Context InitializeContext([NotNull] string inputFileName, [CanBeNull] string outputFileName) + Context InitializeContext(string inputFileName, string? outputFileName) { var ctx = new Context { @@ -143,7 +136,7 @@ namespace Zapf public AssemblyResult Assemble(string inputFileName, string outputFileName) { - var ctx = InitializeContext(inputFileName, outputFileName); + using var ctx = InitializeContext(inputFileName, outputFileName); //XXX redirect log messages diff --git a/src/Zilf.Common/StringEncoding/Horspool.cs b/src/Zilf.Common/StringEncoding/Horspool.cs index 30bfe2e..b54defa 100644 --- a/src/Zilf.Common/StringEncoding/Horspool.cs +++ b/src/Zilf.Common/StringEncoding/Horspool.cs @@ -91,7 +91,7 @@ namespace Zilf.Common.StringEncoding class CharMap { readonly int[] small = new int[256]; - Dictionary big; + Dictionary? big; public CharMap(int defaultValue) { diff --git a/src/Zilf.Common/UnhandledCaseException.cs b/src/Zilf.Common/UnhandledCaseException.cs index b87d106..a9d0035 100644 --- a/src/Zilf.Common/UnhandledCaseException.cs +++ b/src/Zilf.Common/UnhandledCaseException.cs @@ -23,7 +23,7 @@ namespace Zilf.Common [Serializable] public sealed class UnhandledCaseException : Exception { - public static UnhandledCaseException FromEnum(T enumValue, string usage = null) + public static UnhandledCaseException FromEnum(T enumValue, string? usage = null) where T : struct { return new UnhandledCaseException( @@ -31,15 +31,22 @@ namespace Zilf.Common $"{typeof(T).Name}.{enumValue}"); } - public static UnhandledCaseException FromTypeOf(T value, string usage = null) + public static UnhandledCaseException FromTypeOf(T value, string? usage = null) { return new UnhandledCaseException( $"Unhandled {(usage == null ? "type" : usage + " type")}: " + $"{(value == null ? "null" : value.GetType().Name)}"); } - public UnhandledCaseException(string message) - : base(message) + public UnhandledCaseException() : base() + { + } + + public UnhandledCaseException(string message) : base(message) + { + } + + public UnhandledCaseException(string message, Exception innerException) : base(message, innerException) { } } diff --git a/src/Zilf.Common/UnreachableCodeException.cs b/src/Zilf.Common/UnreachableCodeException.cs index a18cd12..5eded2e 100644 --- a/src/Zilf.Common/UnreachableCodeException.cs +++ b/src/Zilf.Common/UnreachableCodeException.cs @@ -23,15 +23,28 @@ namespace Zilf.Common /// /// Thrown at locations that should be unreachable, e.g. because previous function calls always throw an exception. /// + [Serializable] public sealed class UnreachableCodeException : Exception { /// /// Shouldn't get here. /// - public UnreachableCodeException(Exception innerException = null) + public UnreachableCodeException(Exception? innerException = null) : base("Shouldn't get here", innerException) { } + + public UnreachableCodeException() : base() + { + } + + public UnreachableCodeException(string message) : base(message) + { + } + + public UnreachableCodeException(string message, Exception innerException) : base(message, innerException) + { + } } } diff --git a/src/Zilf.Common/Zilf.Common.csproj b/src/Zilf.Common/Zilf.Common.csproj index 9e343f3..e296c7a 100644 --- a/src/Zilf.Common/Zilf.Common.csproj +++ b/src/Zilf.Common/Zilf.Common.csproj @@ -1,8 +1,9 @@  - netstandard2.0 + netstandard2.1 Provides Z-machine utility classes for ZILF and ZAPF. + enable diff --git a/src/Zilf.Emit/.editorconfig b/src/Zilf.Emit/.editorconfig new file mode 100644 index 0000000..e8d8986 --- /dev/null +++ b/src/Zilf.Emit/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# RCS1139: Add summary element to documentation comment. +dotnet_diagnostic.RCS1139.severity = silent diff --git a/src/Zilf.Emit/IConstantOperand.cs b/src/Zilf.Emit/IConstantOperand.cs index 0452662..f737ba0 100644 --- a/src/Zilf.Emit/IConstantOperand.cs +++ b/src/Zilf.Emit/IConstantOperand.cs @@ -22,6 +22,6 @@ namespace Zilf.Emit { public interface IConstantOperand : IOperand { - [NotNull] IConstantOperand Add([NotNull] IConstantOperand other); + IConstantOperand Add(IConstantOperand other); } } \ No newline at end of file diff --git a/src/Zilf.Emit/IDebugFileBuilder.cs b/src/Zilf.Emit/IDebugFileBuilder.cs index 651be06..0b882fc 100644 --- a/src/Zilf.Emit/IDebugFileBuilder.cs +++ b/src/Zilf.Emit/IDebugFileBuilder.cs @@ -27,27 +27,27 @@ namespace Zilf.Emit /// /// The operand whose value identifies an action. /// The name of the action. - void MarkAction([NotNull] IOperand action, [NotNull] string name); + void MarkAction(IOperand action, string name); /// /// Marks the bounds of an object definition. /// /// The object being defined. /// The position where the object definition begins. /// The position where the object definition ends. - void MarkObject([NotNull] IObjectBuilder obj, DebugLineRef start, DebugLineRef end); + void MarkObject(IObjectBuilder obj, DebugLineRef start, DebugLineRef end); /// /// Marks the bounds of a routine definition. /// /// The routine being defined. /// The position where the routine definition begins. /// The position where the routine definition ends. - void MarkRoutine([NotNull] IRoutineBuilder routine, DebugLineRef start, DebugLineRef end); + void MarkRoutine(IRoutineBuilder routine, DebugLineRef start, DebugLineRef end); /// /// Marks a sequence point at the current position in a routine. /// /// The routine being defined. /// The position corresponding to the next /// instruction emitted. - void MarkSequencePoint([NotNull] IRoutineBuilder routine, DebugLineRef point); + void MarkSequencePoint(IRoutineBuilder routine, DebugLineRef point); } } \ No newline at end of file diff --git a/src/Zilf.Emit/IGameBuilder.cs b/src/Zilf.Emit/IGameBuilder.cs index 5eb89de..471b33b 100644 --- a/src/Zilf.Emit/IGameBuilder.cs +++ b/src/Zilf.Emit/IGameBuilder.cs @@ -27,14 +27,12 @@ namespace Zilf.Emit /// /// Gets a target-specific options object. /// - [NotNull] IGameOptions Options { get; } /// /// Gets the debug file builder, if one exists. /// - [CanBeNull] - IDebugFileBuilder DebugFile { get; } + IDebugFileBuilder? DebugFile { get; } /// /// Defines a new global variable. @@ -42,8 +40,7 @@ namespace Zilf.Emit /// The name of the variable. /// A helper object which may be used to set the variable's default value /// or refer to the variable as an operand. - [NotNull] - IGlobalBuilder DefineGlobal([NotNull] string name); + IGlobalBuilder DefineGlobal(string name); /// /// Defines a new table. /// @@ -51,8 +48,7 @@ namespace Zilf.Emit /// true if the table should be stored in read-only memory. /// A helper object which may be used to add values to the table or refer /// to the table as an operand. - [NotNull] - ITableBuilder DefineTable([CanBeNull] string name, bool pure); + ITableBuilder DefineTable(string? name, bool pure); /// /// Defines a new routine. /// @@ -63,33 +59,29 @@ namespace Zilf.Emit /// sacrifice space to ensure the stack is kept clean. /// A helper object which may be used to add code to the routine or /// refer to the routine as an operand. - [NotNull] - IRoutineBuilder DefineRoutine([NotNull] string name, bool entryPoint, bool cleanStack); + IRoutineBuilder DefineRoutine(string name, bool entryPoint, bool cleanStack); /// /// Defines a new object. /// /// The name of the object. /// A helper object which may be used to add properties to the object /// or refer to the object as an operand. - [NotNull] - IObjectBuilder DefineObject([NotNull] string name); + IObjectBuilder DefineObject(string name); /// /// Defines a new object property. /// /// The name of the property. /// A helper object which may be used to set the property's default /// value or refer to the property as an operand. - [NotNull] - IPropertyBuilder DefineProperty([NotNull] string name); + IPropertyBuilder DefineProperty(string name); /// /// Defines a new object flag. /// /// The name of the flag. /// A helper object which may be used to refer to the flag as an /// operand. - [NotNull] - IFlagBuilder DefineFlag([NotNull] string name); - + IFlagBuilder DefineFlag(string name); + /// /// Gets the maximum allowable length of a property, in bytes. /// @@ -113,27 +105,23 @@ namespace Zilf.Emit /// /// Gets a predefined operand representing the constant 0. /// - [NotNull] INumericOperand Zero { get; } /// /// Gets a predefined operand representing the constant 1. /// - [NotNull] INumericOperand One { get; } /// /// Gets an operand representing a numeric constant. /// /// The numeric constant. /// The operand. - [NotNull] INumericOperand MakeOperand(int value); /// /// Gets an operand representing a string constant. /// /// The string constant. /// The operand. - [NotNull] - IOperand MakeOperand([NotNull] string value); + IOperand MakeOperand(string value); /// /// Defines a new constant to represent an existing operand, or redefines /// an existing constant. @@ -149,8 +137,7 @@ namespace Zilf.Emit /// The effect of redefining an existing constant when the constant /// has already been emitted in routine code is undefined. /// - [NotNull] - IOperand DefineConstant([NotNull] string name, [NotNull] IOperand value); + IOperand DefineConstant(string name, IOperand value); /// /// Defines a new vocabulary word. @@ -162,13 +149,12 @@ namespace Zilf.Emit /// If extra data is used, the extra data of all vocabulary words must /// be the same size. /// - [NotNull] - IWordBuilder DefineVocabularyWord([NotNull] string word); + IWordBuilder DefineVocabularyWord(string word); /// /// Deletes a previously defined vocabulary word. /// /// The vocabulary word. - void RemoveVocabularyWord([NotNull] string word); + void RemoveVocabularyWord(string word); /// /// Gets the collection of self-inserting word break characters. /// @@ -177,12 +163,10 @@ namespace Zilf.Emit /// and READ instructions, such that if '.' is in the set, "Mrs. Smith" /// will be lexed as three words: {"mrs", ".", "smith"}. /// - [NotNull] ICollection SelfInsertingBreaks { get; } /// /// Gets a predefined operand representing the vocabulary table. /// - [NotNull] IConstantOperand VocabularyTable { get; } /// @@ -194,7 +178,7 @@ namespace Zilf.Emit /// if a global symbol is defined with that name, or /// otherwise. [ContractAnnotation("=> true, type: notnull; => false, type: null")] - bool IsGloballyDefined([NotNull] string name, [CanBeNull] out string type); + bool IsGloballyDefined(string name, out string? type); /// /// Writes the final output and closes the game builder. diff --git a/src/Zilf.Emit/IGlobalBuilder.cs b/src/Zilf.Emit/IGlobalBuilder.cs index 4829eb1..d66ae76 100644 --- a/src/Zilf.Emit/IGlobalBuilder.cs +++ b/src/Zilf.Emit/IGlobalBuilder.cs @@ -22,7 +22,6 @@ namespace Zilf.Emit { public interface IGlobalBuilder : IVariable { - [CanBeNull] - IOperand DefaultValue { get; set; } + IOperand? DefaultValue { get; set; } } } \ No newline at end of file diff --git a/src/Zilf.Emit/IIndirectOperand.cs b/src/Zilf.Emit/IIndirectOperand.cs index f56e399..115f38f 100644 --- a/src/Zilf.Emit/IIndirectOperand.cs +++ b/src/Zilf.Emit/IIndirectOperand.cs @@ -22,7 +22,6 @@ namespace Zilf.Emit { public interface IIndirectOperand : IConstantOperand { - [NotNull] IVariable Variable { get; } } } \ No newline at end of file diff --git a/src/Zilf.Emit/ILocalBuilder.cs b/src/Zilf.Emit/ILocalBuilder.cs index 062d5a8..ebab83a 100644 --- a/src/Zilf.Emit/ILocalBuilder.cs +++ b/src/Zilf.Emit/ILocalBuilder.cs @@ -16,13 +16,10 @@ * along with ZILF. If not, see . */ -using JetBrains.Annotations; - namespace Zilf.Emit { public interface ILocalBuilder : IVariable { - [CanBeNull] - IOperand DefaultValue { get; set; } + IOperand? DefaultValue { get; set; } } } \ No newline at end of file diff --git a/src/Zilf.Emit/IObjectBuilder.cs b/src/Zilf.Emit/IObjectBuilder.cs index 7b00afd..590e773 100644 --- a/src/Zilf.Emit/IObjectBuilder.cs +++ b/src/Zilf.Emit/IObjectBuilder.cs @@ -23,19 +23,15 @@ namespace Zilf.Emit [PublicAPI] public interface IObjectBuilder : IConstantOperand { - [NotNull] string DescriptiveName { get; set; } - [CanBeNull] - IObjectBuilder Parent { get; set; } - [CanBeNull] - IObjectBuilder Child { get; set; } - [CanBeNull] - IObjectBuilder Sibling { get; set; } + IObjectBuilder? Parent { get; set; } + IObjectBuilder? Child { get; set; } + IObjectBuilder? Sibling { get; set; } - void AddByteProperty([NotNull] IPropertyBuilder prop, [NotNull] IOperand value); - void AddWordProperty([NotNull] IPropertyBuilder prop, [NotNull] IOperand value); - [NotNull] ITableBuilder AddComplexProperty([NotNull] IPropertyBuilder prop); + void AddByteProperty(IPropertyBuilder prop, IOperand value); + void AddWordProperty(IPropertyBuilder prop, IOperand value); + ITableBuilder AddComplexProperty(IPropertyBuilder prop); - void AddFlag([NotNull] IFlagBuilder flag); + void AddFlag(IFlagBuilder flag); } } \ No newline at end of file diff --git a/src/Zilf.Emit/IPropertyBuilder.cs b/src/Zilf.Emit/IPropertyBuilder.cs index 16cfb8a..1928253 100644 --- a/src/Zilf.Emit/IPropertyBuilder.cs +++ b/src/Zilf.Emit/IPropertyBuilder.cs @@ -22,7 +22,6 @@ namespace Zilf.Emit { public interface IPropertyBuilder : IConstantOperand { - [CanBeNull] - IOperand DefaultValue { get; set; } + IOperand? DefaultValue { get; set; } } } \ No newline at end of file diff --git a/src/Zilf.Emit/IRoutineBuilder.cs b/src/Zilf.Emit/IRoutineBuilder.cs index e1187cf..14968fb 100644 --- a/src/Zilf.Emit/IRoutineBuilder.cs +++ b/src/Zilf.Emit/IRoutineBuilder.cs @@ -31,13 +31,10 @@ namespace Zilf.Emit /// bool CleanStack { get; } - [NotNull] ILabel RTrue { get; } - [NotNull] ILabel RFalse { get; } - [NotNull] IVariable Stack { get; } /// @@ -46,8 +43,7 @@ namespace Zilf.Emit /// /// The routine is the entry point and thus not allowed to have local variables. /// - [NotNull] - ILocalBuilder DefineRequiredParameter([NotNull] string name); + ILocalBuilder DefineRequiredParameter(string name); /// /// A local variable already exists by that paramName. @@ -55,8 +51,7 @@ namespace Zilf.Emit /// /// The routine is the entry point and thus not allowed to have local variables. /// - [NotNull] - ILocalBuilder DefineOptionalParameter([NotNull] string paramName); + ILocalBuilder DefineOptionalParameter(string paramName); /// /// A local variable already exists by that localName. @@ -64,34 +59,31 @@ namespace Zilf.Emit /// /// The routine is the entry point and thus not allowed to have local variables. /// - [NotNull] - ILocalBuilder DefineLocal([NotNull] string localName); + ILocalBuilder DefineLocal(string localName); - [NotNull] ILabel RoutineStart { get; } - [NotNull] ILabel DefineLabel(); - void MarkLabel([NotNull] ILabel label); + void MarkLabel(ILabel label); /// /// Gets a value indicating whether is supported. /// bool HasArgCount { get; } - void Branch([NotNull] ILabel label); - void Branch(Condition cond, [CanBeNull] IOperand left, [CanBeNull] IOperand right, [NotNull] ILabel label, bool polarity); - void BranchIfZero([NotNull] IOperand operand, [NotNull] ILabel label, bool polarity); - void BranchIfEqual([NotNull] IOperand value, [NotNull] IOperand option1, [NotNull] ILabel label, bool polarity); + void Branch(ILabel label); + void Branch(Condition cond, IOperand? left, IOperand? right, ILabel label, bool polarity); + void BranchIfZero(IOperand operand, ILabel label, bool polarity); + void BranchIfEqual(IOperand value, IOperand option1, ILabel label, bool polarity); - void BranchIfEqual([NotNull] IOperand value, [NotNull] IOperand option1, [NotNull] IOperand option2, - [NotNull] ILabel label, bool polarity); + void BranchIfEqual(IOperand value, IOperand option1, IOperand option2, + ILabel label, bool polarity); - void BranchIfEqual([NotNull] IOperand value, [NotNull] IOperand option1, [NotNull] IOperand option2, - [NotNull] IOperand option3, [NotNull] ILabel label, bool polarity); + void BranchIfEqual(IOperand value, IOperand option1, IOperand option2, + IOperand option3, ILabel label, bool polarity); - void Return([NotNull] IOperand result); + void Return(IOperand result); void EmitRestart(); void EmitQuit(); @@ -101,8 +93,8 @@ namespace Zilf.Emit /// bool HasBranchSave { get; } - void EmitSave([NotNull] ILabel label, bool polarity); - void EmitRestore([NotNull] ILabel label, bool polarity); + void EmitSave(ILabel label, bool polarity); + void EmitRestore(ILabel label, bool polarity); /// /// Gets a value indicating whether the forms of and @@ -110,8 +102,8 @@ namespace Zilf.Emit /// bool HasStoreSave { get; } - void EmitSave([NotNull] IVariable result); - void EmitRestore([NotNull] IVariable result); + void EmitSave(IVariable result); + void EmitRestore(IVariable result); /// /// Gets a value indicating whether the forms of and @@ -119,19 +111,19 @@ namespace Zilf.Emit /// bool HasExtendedSave { get; } - void EmitSave([NotNull] IOperand table, [NotNull] IOperand size, [NotNull] IOperand name, - [NotNull] IVariable result); + void EmitSave(IOperand table, IOperand size, IOperand name, + IVariable result); - void EmitRestore([NotNull] IOperand table, [NotNull] IOperand size, [NotNull] IOperand name, - [NotNull] IVariable result); + void EmitRestore(IOperand table, IOperand size, IOperand name, + IVariable result); // form may be null - void EmitScanTable([NotNull] IOperand value, [NotNull] IOperand table, [NotNull] IOperand length, [CanBeNull] IOperand form, - [NotNull] IVariable result, [NotNull] ILabel label, bool polarity); + void EmitScanTable(IOperand value, IOperand table, IOperand length, IOperand? form, + IVariable result, ILabel label, bool polarity); - void EmitGetChild([NotNull] IOperand value, [NotNull] IVariable result, [NotNull] ILabel label, bool polarity); + void EmitGetChild(IOperand value, IVariable result, ILabel label, bool polarity); - void EmitGetSibling([NotNull] IOperand value, [NotNull] IVariable result, [NotNull] ILabel label, + void EmitGetSibling(IOperand value, IVariable result, ILabel label, bool polarity); /// @@ -140,48 +132,48 @@ namespace Zilf.Emit /// bool HasUndo { get; } - void EmitNullary(NullaryOp op, [CanBeNull] IVariable result); - void EmitUnary(UnaryOp op, [NotNull] IOperand value, [CanBeNull] IVariable result); - void EmitBinary(BinaryOp op, [NotNull] IOperand left, [NotNull] IOperand right, [CanBeNull] IVariable result); + void EmitNullary(NullaryOp op, IVariable? result); + void EmitUnary(UnaryOp op, IOperand value, IVariable? result); + void EmitBinary(BinaryOp op, IOperand left, IOperand right, IVariable? result); - void EmitTernary(TernaryOp op, [NotNull] IOperand left, [NotNull] IOperand center, [NotNull] IOperand right, - [CanBeNull] IVariable result); + void EmitTernary(TernaryOp op, IOperand left, IOperand center, IOperand right, + IVariable? result); - void EmitPrint([NotNull] string text, bool crlfRtrue); + void EmitPrint(string text, bool crlfRtrue); - void EmitPrint(PrintOp op, [NotNull] IOperand value); + void EmitPrint(PrintOp op, IOperand value); // height and skip may be null - void EmitPrintTable([NotNull] IOperand table, [NotNull] IOperand width, [CanBeNull] IOperand height, [CanBeNull] IOperand skip); + void EmitPrintTable(IOperand table, IOperand width, IOperand? height, IOperand? skip); void EmitPrintNewLine(); // V3: interval, routine, and result must be null // V4: interval and routine may be null, result must be null // V5+: lexbuf, interval, and routine may be null - void EmitRead([NotNull] IOperand chrbuf, [CanBeNull] IOperand lexbuf, [CanBeNull] IOperand interval, [CanBeNull] IOperand routine, - [CanBeNull] IVariable result); + void EmitRead(IOperand chrbuf, IOperand? lexbuf, IOperand? interval, IOperand? routine, + IVariable? result); // interval and routine may be null - void EmitReadChar([CanBeNull] IOperand interval, [CanBeNull] IOperand routine, [NotNull] IVariable result); + void EmitReadChar(IOperand? interval, IOperand? routine, IVariable result); // V3: routine must be null // effect, volume, and routine may always be null - void EmitPlaySound([NotNull] IOperand number, [CanBeNull] IOperand effect, [CanBeNull] IOperand volume, [CanBeNull] IOperand routine); + void EmitPlaySound(IOperand number, IOperand? effect, IOperand? volume, IOperand? routine); // TODO: make EmitQuaternary for EncodeText, PlaySound, Read, and Tokenize? - void EmitEncodeText([NotNull] IOperand src, [NotNull] IOperand length, [NotNull] IOperand srcOffset, - [NotNull] IOperand dest); + void EmitEncodeText(IOperand src, IOperand length, IOperand srcOffset, + IOperand dest); - void EmitTokenize([NotNull] IOperand text, [NotNull] IOperand parse, [CanBeNull] IOperand dictionary, [CanBeNull] IOperand flag); + void EmitTokenize(IOperand text, IOperand parse, IOperand? dictionary, IOperand? flag); // result may be null - void EmitCall([NotNull] IOperand routine, [NotNull] IOperand[] args, [CanBeNull] IVariable result); + void EmitCall(IOperand routine, IOperand[] args, IVariable? result); - void EmitStore([NotNull] IVariable dest, [NotNull] IOperand src); + void EmitStore(IVariable dest, IOperand src); void EmitPopStack(); - void EmitPushUserStack([NotNull] IOperand value, [NotNull] IOperand stack, [NotNull] ILabel label, + void EmitPushUserStack(IOperand value, IOperand stack, ILabel label, bool polarity); void Finish(); diff --git a/src/Zilf.Emit/ITableBuilder.cs b/src/Zilf.Emit/ITableBuilder.cs index 22a5883..b09f547 100644 --- a/src/Zilf.Emit/ITableBuilder.cs +++ b/src/Zilf.Emit/ITableBuilder.cs @@ -16,15 +16,13 @@ * along with ZILF. If not, see . */ -using JetBrains.Annotations; - namespace Zilf.Emit { public interface ITableBuilder : IConstantOperand { void AddByte(byte value); - void AddByte([NotNull] IOperand value); + void AddByte(IOperand value); void AddShort(short value); - void AddShort([NotNull] IOperand value); + void AddShort(IOperand value); } } \ No newline at end of file diff --git a/src/Zilf.Emit/IVariable.cs b/src/Zilf.Emit/IVariable.cs index 197c6f2..b1738b8 100644 --- a/src/Zilf.Emit/IVariable.cs +++ b/src/Zilf.Emit/IVariable.cs @@ -22,7 +22,6 @@ namespace Zilf.Emit { public interface IVariable : IOperand { - [NotNull] IIndirectOperand Indirect { get; } } } \ No newline at end of file diff --git a/src/Zilf.Emit/Peephole.cs b/src/Zilf.Emit/Peephole.cs index 0ff7e98..8899e00 100644 --- a/src/Zilf.Emit/Peephole.cs +++ b/src/Zilf.Emit/Peephole.cs @@ -18,6 +18,8 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using JetBrains.Annotations; @@ -60,12 +62,12 @@ namespace Zilf.Emit struct CombinableLine { - public ILabel Label { get; } + public ILabel? Label { get; } public TCode Code { get; } - public ILabel Target { get; } + public ILabel? Target { get; } public PeepholeLineType Type { get; } - public CombinableLine(ILabel label, TCode code, ILabel target, PeepholeLineType type) + public CombinableLine(ILabel? label, TCode code, ILabel? target, PeepholeLineType type) : this() { Label = label; @@ -79,10 +81,9 @@ namespace Zilf.Emit { public readonly int LinesConsumed; - [NotNull] public readonly IEnumerable> NewLines; - public CombinerResult(int linesConsumed, [NotNull] IEnumerable> newLines) + public CombinerResult(int linesConsumed, IEnumerable> newLines) { LinesConsumed = linesConsumed; NewLines = newLines; @@ -137,8 +138,8 @@ namespace Zilf.Emit /// The original instruction sequence. /// A value indicating how many instructions were consumed /// and which instructions they should be replaced with. - CombinerResult Apply([NotNull] IEnumerable> lines); - + CombinerResult Apply(IEnumerable> lines); + /// /// Generates code for an unconditional branch. /// @@ -204,7 +205,6 @@ namespace Zilf.Emit /// Allocates a new label. /// /// The new label. - [NotNull] ILabel NewLabel(); } @@ -216,18 +216,15 @@ namespace Zilf.Emit { class Line { - [CanBeNull] - public ILabel Label; + public ILabel? Label; public TCode Code; - [CanBeNull] - public ILabel TargetLabel; + public ILabel? TargetLabel; public PeepholeLineType Type; - [CanBeNull] - public Line TargetLine; + public Line? TargetLine; public bool Flag; // toggled to mark reachability - public Line([CanBeNull] ILabel label, TCode code, [CanBeNull] ILabel target, PeepholeLineType type) + public Line(ILabel? label, TCode code, ILabel? target, PeepholeLineType type) { Label = label; Code = code; @@ -235,7 +232,7 @@ namespace Zilf.Emit Type = type; } - public void CopyFrom([NotNull] Line other) + public void CopyFrom(Line other) { Label = other.Label; Code = other.Code; @@ -280,19 +277,14 @@ namespace Zilf.Emit } } - [CanBeNull] - ILabel pendingLabel; - [NotNull] + ILabel? pendingLabel; readonly Dictionary aliases = new Dictionary(); - [ItemNotNull] - [NotNull] readonly LinkedList lines = new LinkedList(); /// /// Gets or sets the delegate that will be used to combine adjacent instructions. /// - [CanBeNull] - public IPeepholeCombiner Combiner { get; set; } + public IPeepholeCombiner? Combiner { get; set; } /// /// Adds an instruction to the buffer. @@ -300,7 +292,7 @@ namespace Zilf.Emit /// The instruction. /// The target label of this instruction, or null. /// The type of instruction. - public void AddLine(TCode code, [CanBeNull] ILabel target, PeepholeLineType type) + public void AddLine(TCode code, ILabel? target, PeepholeLineType type) { lines.AddLast(new Line(pendingLabel, code, target, type)); pendingLabel = null; @@ -313,7 +305,7 @@ namespace Zilf.Emit /// /// One of the labels in the other buffer's also exists in this buffer's . /// - public void InsertBufferFirst([NotNull] PeepholeBuffer other) + public void InsertBufferFirst(PeepholeBuffer other) { // turn pending label into a label on our first line, or copy it if we have no lines if (other.pendingLabel != null) @@ -360,7 +352,7 @@ namespace Zilf.Emit /// Marks a label at the current position. /// /// The label to mark. - public void MarkLabel([NotNull] ILabel label) + public void MarkLabel(ILabel label) { if (pendingLabel == null) pendingLabel = label; @@ -396,7 +388,7 @@ namespace Zilf.Emit /// /// /// - public void Finish([NotNull] [InstantHandle] Action handler) + public void Finish([InstantHandle] Action handler) { Optimize(); @@ -405,7 +397,7 @@ namespace Zilf.Emit } [System.Diagnostics.Conditional("TRACE_PEEPHOLE")] - void Trace([CanBeNull] string message = null) + void Trace(string? message = null) { Console.WriteLine(); Console.WriteLine(); @@ -549,7 +541,7 @@ namespace Zilf.Emit } // apply optimizations to each line - for (var node = lines.First; node != null; node = node.Next) + for (LinkedListNode? node = lines.First; node != null; node = node!.Next) { var line = node.Value; bool delete = false; @@ -655,7 +647,7 @@ namespace Zilf.Emit (node.Next.Value.Type == PeepholeLineType.BranchAlways && node.Next.Value.TargetLine == originalTarget))) { ILabel jumpTargetLabel; - Line jumpTargetLine; + Line? jumpTargetLine; if (sameCondition) { if (lineAfterTarget.Label == null) @@ -669,6 +661,7 @@ namespace Zilf.Emit } else { + Debug.Assert(originalTarget.TargetLabel != null); jumpTargetLabel = originalTarget.TargetLabel; jumpTargetLine = originalTarget.TargetLine; } @@ -682,7 +675,7 @@ namespace Zilf.Emit TargetLine = jumpTargetLine, Flag = reachableFlag }; - usedLabels[newLine.TargetLabel] = true; + usedLabels[jumpTargetLabel] = true; node = lines.AddAfter(node, newLine); } @@ -759,7 +752,7 @@ namespace Zilf.Emit } else if (line.Type == PeepholeLineType.BranchAlways && line.TargetLine.Type == PeepholeLineType.Terminator && - Combiner.CanDuplicate(line.TargetLine.Code)) + Combiner?.CanDuplicate(line.TargetLine.Code) == true) { // handle "branch to terminator" by replacing the branch with a copy of the terminator var oldLabel = line.Label; @@ -878,7 +871,7 @@ namespace Zilf.Emit { l.TargetLabel = nextLine.Label; l.TargetLine = nextLine; - usedLabels[l.TargetLabel] = true; + usedLabels[l.TargetLabel!] = true; } } @@ -955,7 +948,7 @@ namespace Zilf.Emit // delete code that has been doomed if (delete) { - var next = node.Next; + var next = node!.Next; lines.Remove(node); changed = true; @@ -963,7 +956,7 @@ namespace Zilf.Emit /* if the line is labeled, update references to it. we assume the * optimization rules will never delete the labeled last line of * the function unless it's unreachable. */ - if (line.Label != null /*&& next != null*/) + if (line.Label != null && next != null) { MarkReachable(next); @@ -992,13 +985,15 @@ namespace Zilf.Emit node = next.Previous; } else + { break; + } } } } while (changed); } - static IEnumerable> EnumerateCombinableLines([NotNull] LinkedListNode node) + static IEnumerable> EnumerateCombinableLines(LinkedListNode node) { yield return new CombinableLine(node.Value.Label, node.Value.Code, node.Value.TargetLabel, node.Value.Type); @@ -1008,25 +1003,15 @@ namespace Zilf.Emit } } - static bool IsInvertibleBranch(PeepholeLineType type) - { - return type == PeepholeLineType.BranchNegative || - type == PeepholeLineType.BranchPositive; - } + static bool IsInvertibleBranch(PeepholeLineType type) => + type == PeepholeLineType.BranchNegative || type == PeepholeLineType.BranchPositive; - static PeepholeLineType InvertBranch(PeepholeLineType type) - { - switch (type) + static PeepholeLineType InvertBranch(PeepholeLineType type) => + type switch { - case PeepholeLineType.BranchPositive: - return PeepholeLineType.BranchNegative; - - case PeepholeLineType.BranchNegative: - return PeepholeLineType.BranchPositive; - - default: - throw new ArgumentOutOfRangeException(); - } - } + PeepholeLineType.BranchPositive => PeepholeLineType.BranchNegative, + PeepholeLineType.BranchNegative => PeepholeLineType.BranchPositive, + _ => throw new ArgumentOutOfRangeException(), + }; } } diff --git a/src/Zilf.Emit/Zap/DebugFileBuilder.cs b/src/Zilf.Emit/Zap/DebugFileBuilder.cs index 13c9d66..8892690 100644 --- a/src/Zilf.Emit/Zap/DebugFileBuilder.cs +++ b/src/Zilf.Emit/Zap/DebugFileBuilder.cs @@ -26,7 +26,7 @@ namespace Zilf.Emit.Zap readonly Dictionary files = new Dictionary(); readonly List storedLines = new List(); - public int GetFileNumber([CanBeNull] string filename) + public int GetFileNumber(string? filename) { if (filename == null) return 0; diff --git a/src/Zilf.Emit/Zap/GameBuilder.cs b/src/Zilf.Emit/Zap/GameBuilder.cs index 7cf9f53..7b72c98 100644 --- a/src/Zilf.Emit/Zap/GameBuilder.cs +++ b/src/Zilf.Emit/Zap/GameBuilder.cs @@ -30,13 +30,10 @@ namespace Zilf.Emit.Zap { const string INDENT = "\t"; - [NotNull] internal static readonly NumericOperand ZERO = new NumericOperand(0); - [NotNull] internal static readonly NumericOperand ONE = new NumericOperand(1); - [NotNull] static readonly ConstantLiteralOperand VOCAB = new ConstantLiteralOperand("VOCAB"); // all global names go in here @@ -56,18 +53,18 @@ namespace Zilf.Emit.Zap readonly IZapStreamFactory streamFactory; internal readonly int zversion; - internal readonly DebugFileBuilder debug; + internal readonly DebugFileBuilder? debug; readonly GameOptions options; - IRoutineBuilder entryRoutine; + IRoutineBuilder? entryRoutine; - Stream stream; + Stream? stream; TextWriter writer; /// is not a supported Z-machine version. /// is the wrong type for this Z-machine version. - public GameBuilder(int zversion, [NotNull] IZapStreamFactory streamFactory, bool wantDebugInfo, - [CanBeNull] GameOptions options = null) + public GameBuilder(int zversion, IZapStreamFactory streamFactory, bool wantDebugInfo, + GameOptions? options = null) { if (!IsSupportedZversion(zversion)) throw new ArgumentOutOfRangeException(nameof(zversion), "Unsupported Z-machine version"); @@ -103,22 +100,11 @@ namespace Zilf.Emit.Zap public void Dispose() { - if (writer != null) - { - var w = writer; - writer = null; - w.Dispose(); - } - - if (stream != null) - { - var s = stream; - stream = null; - s.Dispose(); - } + writer?.Dispose(); + stream?.Dispose(); } - static void GetOptionsTypeForZVersion(int zversion, [NotNull] out Type requiredOptionsType, [NotNull] out Type concreteOptionsType) + static void GetOptionsTypeForZVersion(int zversion, out Type requiredOptionsType, out Type concreteOptionsType) { switch (zversion) { @@ -232,8 +218,7 @@ namespace Zilf.Emit.Zap writer.WriteLine(INDENT + ".INSERT \"{0}\"", streamFactory.GetDataFileName(false)); } - [NotNull] - static string ExpandChrSet([CanBeNull] string alphabet) + static string ExpandChrSet(string? alphabet) { var sb = new StringBuilder(100); if (alphabet == null) @@ -254,7 +239,7 @@ namespace Zilf.Emit.Zap return sb.ToString(); } - public IDebugFileBuilder DebugFile => debug; + public IDebugFileBuilder? DebugFile => debug; public IGameOptions Options => options; @@ -286,7 +271,7 @@ namespace Zilf.Emit.Zap } /// A symbol called is already defined. - public ITableBuilder DefineTable(string name, bool pure) + public ITableBuilder DefineTable(string? name, bool pure) { if (name == null) name = "T?" + Convert.ToString(pureTables.Count + impureTables.Count); @@ -393,8 +378,7 @@ namespace Zilf.Emit.Zap public ICollection SelfInsertingBreaks => siBreaks; - [NotNull] - public static string SanitizeString([NotNull] string text) + public static string SanitizeString(string text) { // escape '"' as '""' var sb = new StringBuilder(text); @@ -406,8 +390,7 @@ namespace Zilf.Emit.Zap return sb.ToString(); } - [NotNull] - public static string SanitizeSymbol([NotNull] string symbol) + public static string SanitizeSymbol(string symbol) { switch (symbol) { @@ -478,7 +461,7 @@ namespace Zilf.Emit.Zap public INumericOperand One => ONE; public IConstantOperand VocabularyTable => VOCAB; - public bool IsGloballyDefined(string name, out string type) => symbols.TryGetValue(name, out type); + public bool IsGloballyDefined(string name, out string? type) => symbols.TryGetValue(name, out type); public void Finish() { @@ -572,8 +555,8 @@ namespace Zilf.Emit.Zap } // done - writer = null; - stream = null; + writer.Close(); + stream.Close(); } void FinishSymbols() @@ -695,7 +678,7 @@ namespace Zilf.Emit.Zap else writer.WriteLine(INDENT + "; Unused property #{0}", row.num); - writer.WriteLine(INDENT + ".WORD {0}", (object)row.def ?? "0"); + writer.WriteLine(INDENT + ".WORD {0}", (object?)row.def ?? "0"); } // object structures @@ -709,9 +692,9 @@ namespace Zilf.Emit.Zap ob.Flags1, ob.Flags2, (zversion < 4) ? "" : "," + ob.Flags3, - (object)ob.Parent ?? "0", - (object)ob.Sibling ?? "0", - (object)ob.Child ?? "0", + (object?)ob.Parent ?? "0", + (object?)ob.Sibling ?? "0", + (object?)ob.Child ?? "0", "?PTBL?" + ob.SymbolicName); } @@ -753,7 +736,7 @@ namespace Zilf.Emit.Zap // global variables foreach (var gb in globals) - writer.WriteLine(INDENT + ".GVAR {0}={1}", gb.Name, (object)gb.DefaultValue?.StripIndirect() ?? "0"); + writer.WriteLine(INDENT + ".GVAR {0}={1}", gb.Name, (object?)gb.DefaultValue?.StripIndirect() ?? "0"); writer.WriteLine(INDENT + ".ENDT"); } diff --git a/src/Zilf.Emit/Zap/GameOptions.cs b/src/Zilf.Emit/Zap/GameOptions.cs index 52b1ae6..d8d07b6 100644 --- a/src/Zilf.Emit/Zap/GameOptions.cs +++ b/src/Zilf.Emit/Zap/GameOptions.cs @@ -65,11 +65,11 @@ namespace Zilf.Emit.Zap public bool Mouse { get; set; } public bool Color { get; set; } - public ITableBuilder HeaderExtensionTable { get; set; } + public ITableBuilder? HeaderExtensionTable { get; set; } - public string Charset0 { get; set; } - public string Charset1 { get; set; } - public string Charset2 { get; set; } + public string? Charset0 { get; set; } + public string? Charset1 { get; set; } + public string? Charset2 { get; set; } public int LanguageId { get; set; } public char? LanguageEscapeChar { get; set; } diff --git a/src/Zilf.Emit/Zap/GlobalBuilder.cs b/src/Zilf.Emit/Zap/GlobalBuilder.cs index 7f72fe4..e0d56a9 100644 --- a/src/Zilf.Emit/Zap/GlobalBuilder.cs +++ b/src/Zilf.Emit/Zap/GlobalBuilder.cs @@ -22,16 +22,15 @@ namespace Zilf.Emit.Zap { class GlobalBuilder : IGlobalBuilder { - public GlobalBuilder([NotNull] string name) + public GlobalBuilder(string name) { Name = name; } public IIndirectOperand Indirect => new IndirectOperand(this); - public IOperand DefaultValue { get; set; } + public IOperand? DefaultValue { get; set; } - [NotNull] public string Name { get; } public override string ToString() diff --git a/src/Zilf.Emit/Zap/IZapStreamFactory.cs b/src/Zilf.Emit/Zap/IZapStreamFactory.cs index 2e8b5ca..2a58c3c 100644 --- a/src/Zilf.Emit/Zap/IZapStreamFactory.cs +++ b/src/Zilf.Emit/Zap/IZapStreamFactory.cs @@ -23,15 +23,15 @@ namespace Zilf.Emit.Zap { public interface IZapStreamFactory { - [NotNull] Stream CreateMainStream(); - [NotNull] Stream CreateFrequentWordsStream(); - [NotNull] Stream CreateDataStream(); - [NotNull] Stream CreateStringStream(); + Stream CreateMainStream(); + Stream CreateFrequentWordsStream(); + Stream CreateDataStream(); + Stream CreateStringStream(); - [NotNull] string GetMainFileName(bool withExt); - [NotNull] string GetDataFileName(bool withExt); - [NotNull] string GetFrequentWordsFileName(bool withExt); - [NotNull] string GetStringFileName(bool withExt); + string GetMainFileName(bool withExt); + string GetDataFileName(bool withExt); + string GetFrequentWordsFileName(bool withExt); + string GetStringFileName(bool withExt); bool FrequentWordsFileExists { get; } } diff --git a/src/Zilf.Emit/Zap/IndirectOperand.cs b/src/Zilf.Emit/Zap/IndirectOperand.cs index 70b195b..3093a2a 100644 --- a/src/Zilf.Emit/Zap/IndirectOperand.cs +++ b/src/Zilf.Emit/Zap/IndirectOperand.cs @@ -22,7 +22,7 @@ namespace Zilf.Emit.Zap { class IndirectOperand : ConstantOperandBase, IIndirectOperand { - public IndirectOperand([NotNull] IVariable variable) + public IndirectOperand(IVariable variable) { Variable = variable; } diff --git a/src/Zilf.Emit/Zap/LocalBuilder.cs b/src/Zilf.Emit/Zap/LocalBuilder.cs index 4de9fba..29167fc 100644 --- a/src/Zilf.Emit/Zap/LocalBuilder.cs +++ b/src/Zilf.Emit/Zap/LocalBuilder.cs @@ -22,24 +22,17 @@ namespace Zilf.Emit.Zap { class LocalBuilder : ILocalBuilder { - [NotNull] - readonly string name; - - public LocalBuilder([NotNull] string name) + public LocalBuilder(string name) { - this.name = name; + this.Name = name; } public IIndirectOperand Indirect => new IndirectOperand(this); - public IOperand DefaultValue { get; set; } + public IOperand? DefaultValue { get; set; } - [NotNull] - public string Name => name; + public string Name { get; } - public override string ToString() - { - return name; - } + public override string ToString() => Name; } } \ No newline at end of file diff --git a/src/Zilf.Emit/Zap/NumericConstantOperand.cs b/src/Zilf.Emit/Zap/NumericConstantOperand.cs index 97e61c6..fa366eb 100644 --- a/src/Zilf.Emit/Zap/NumericConstantOperand.cs +++ b/src/Zilf.Emit/Zap/NumericConstantOperand.cs @@ -22,10 +22,9 @@ namespace Zilf.Emit.Zap { class NumericConstantOperand : ConstantOperandBase, INumericOperand { - [NotNull] readonly string literal; - public NumericConstantOperand([NotNull] string literal, int value) + public NumericConstantOperand(string literal, int value) { this.literal = literal; Value = value; diff --git a/src/Zilf.Emit/Zap/ObjectBuilder.cs b/src/Zilf.Emit/Zap/ObjectBuilder.cs index 8303bd7..e17db57 100644 --- a/src/Zilf.Emit/Zap/ObjectBuilder.cs +++ b/src/Zilf.Emit/Zap/ObjectBuilder.cs @@ -57,22 +57,18 @@ namespace Zilf.Emit.Zap public string DescriptiveName { get; set; } = ""; - public IObjectBuilder Parent { get; set; } + public IObjectBuilder? Parent { get; set; } - public IObjectBuilder Child { get; set; } + public IObjectBuilder? Child { get; set; } - public IObjectBuilder Sibling { get; set; } + public IObjectBuilder? Sibling { get; set; } - [NotNull] public string Flags1 => GetFlagsString(0); - [NotNull] public string Flags2 => GetFlagsString(16); - [NotNull] public string Flags3 => GetFlagsString(32); - [NotNull] string GetFlagsString(int start) { var sb = new StringBuilder(); @@ -120,7 +116,7 @@ namespace Zilf.Emit.Zap flags.Add(fb); } - internal void WriteProperties([NotNull] TextWriter writer) + internal void WriteProperties(TextWriter writer) { writer.WriteLine(INDENT + ".STRL \"{0}\"", GameBuilder.SanitizeString(DescriptiveName)); diff --git a/src/Zilf.Emit/Zap/OperandExtensions.cs b/src/Zilf.Emit/Zap/OperandExtensions.cs index 79f75a3..e3765ea 100644 --- a/src/Zilf.Emit/Zap/OperandExtensions.cs +++ b/src/Zilf.Emit/Zap/OperandExtensions.cs @@ -16,6 +16,7 @@ * along with ZILF. If not, see . */ +using System.Diagnostics.CodeAnalysis; using JetBrains.Annotations; using Zapf.Parsing.Expressions; @@ -23,14 +24,12 @@ namespace Zilf.Emit.Zap { static class OperandExtensions { - [NotNull] - public static IOperand StripIndirect([NotNull] this IOperand operand) + public static IOperand StripIndirect(this IOperand operand) { return operand is IIndirectOperand indirect ? indirect.Variable : operand; } - [NotNull] - public static AsmExpr ToAsmExpr([NotNull] this IOperand operand) + public static AsmExpr ToAsmExpr(this IOperand operand) { switch (operand) { @@ -48,13 +47,10 @@ namespace Zilf.Emit.Zap } } - public static bool IsStack([NotNull] this AsmExpr asmExpr) - { - return asmExpr is SymbolExpr sym && sym.Text == "STACK"; - } + public static bool IsStack(this AsmExpr asmExpr) => asmExpr is SymbolExpr sym && sym.Text == "STACK"; [ContractAnnotation("=> false, inner: null; => true, inner: notnull")] - public static bool IsQuote([NotNull] this AsmExpr asmExpr, out AsmExpr inner) + public static bool IsQuote(this AsmExpr asmExpr, [NotNullWhen(true)] out AsmExpr? inner) { if (asmExpr is QuoteExpr quote) { diff --git a/src/Zilf.Emit/Zap/PropertyBuilder.cs b/src/Zilf.Emit/Zap/PropertyBuilder.cs index 8b1a71d..cc20497 100644 --- a/src/Zilf.Emit/Zap/PropertyBuilder.cs +++ b/src/Zilf.Emit/Zap/PropertyBuilder.cs @@ -22,10 +22,9 @@ namespace Zilf.Emit.Zap { class PropertyBuilder : ConstantOperandBase, IPropertyBuilder { - [NotNull] readonly string name; - public PropertyBuilder([NotNull] string name, int number) + public PropertyBuilder(string name, int number) { this.name = name; Number = number; @@ -33,7 +32,7 @@ namespace Zilf.Emit.Zap public int Number { get; } - public IOperand DefaultValue { get; set; } + public IOperand? DefaultValue { get; set; } public override string ToString() { diff --git a/src/Zilf.Emit/Zap/RoutineBuilder.cs b/src/Zilf.Emit/Zap/RoutineBuilder.cs index 70afa33..81ee405 100644 --- a/src/Zilf.Emit/Zap/RoutineBuilder.cs +++ b/src/Zilf.Emit/Zap/RoutineBuilder.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using JetBrains.Annotations; @@ -43,7 +44,7 @@ namespace Zilf.Emit.Zap readonly PeepholeBuffer peep; int nextLabelNum; - string pendingDebugText; + string? pendingDebugText; readonly List requiredParams = new List(); readonly List optionalParams = new List(); @@ -135,7 +136,7 @@ namespace Zilf.Emit.Zap peep.MarkLabel(label); } - void AddLine(Instruction code, ILabel target, PeepholeLineType type) + void AddLine(Instruction code, ILabel? target, PeepholeLineType type) { ZapCode zc; zc.Instruction = code; @@ -161,7 +162,7 @@ namespace Zilf.Emit.Zap /// This condition requires a variable, but is not a variable. /// The wrong number of operands were provided. - public void Branch(Condition cond, IOperand left, IOperand right, ILabel label, bool polarity) + public void Branch(Condition cond, IOperand? left, IOperand? right, ILabel label, bool polarity) { string opcode; bool leftVar = false, nullary = false, unary = false; @@ -228,25 +229,25 @@ namespace Zilf.Emit.Zap else if (unary) { if (right != null) - throw new ArgumentException("Expected only one operand for unary condition", nameof(right)); + throw new ArgumentException("Expected one operand for unary condition", nameof(right)); } else { - if (right == null) + if (left == null || right == null) throw new ArgumentException("Expected two operands for binary condition", nameof(right)); } var instruction = new Instruction(opcode); if (unary) { - instruction.Operands.Add(new QuoteExpr(left.ToAsmExpr())); + instruction.Operands.Add(new QuoteExpr(left!.ToAsmExpr())); } else if (!nullary) { Debug.Assert(left != null); var leftExpr = left.ToAsmExpr(); instruction.Operands.Add(leftVar ? new QuoteExpr(leftExpr) : leftExpr); - instruction.Operands.Add(right.ToAsmExpr()); + instruction.Operands.Add(right!.ToAsmExpr()); } AddLine( @@ -266,7 +267,7 @@ namespace Zilf.Emit.Zap public void BranchIfEqual(IOperand value, IOperand option1, ILabel label, bool polarity) { AddLine( - new Instruction("EQUAL?", value.ToAsmExpr(), option1.ToAsmExpr()), + new Instruction("EQUAL?", value.ToAsmExpr(), option1.ToAsmExpr()), label, polarity ? PeepholeLineType.BranchPositive : PeepholeLineType.BranchNegative); } @@ -274,7 +275,7 @@ namespace Zilf.Emit.Zap public void BranchIfEqual(IOperand value, IOperand option1, IOperand option2, ILabel label, bool polarity) { AddLine( - new Instruction("EQUAL?", value.ToAsmExpr(), option1.ToAsmExpr(), option2.ToAsmExpr()), + new Instruction("EQUAL?", value.ToAsmExpr(), option1.ToAsmExpr(), option2.ToAsmExpr()), label, polarity ? PeepholeLineType.BranchPositive : PeepholeLineType.BranchNegative); } @@ -301,49 +302,29 @@ namespace Zilf.Emit.Zap public bool HasUndo => game.zversion >= 5; - public void EmitNullary(NullaryOp op, IVariable result) + public void EmitNullary(NullaryOp op, IVariable? result) { - string opcode; - - switch (op) + var opcode = op switch { - case NullaryOp.RestoreUndo: - opcode = "IRESTORE"; - break; - case NullaryOp.SaveUndo: - opcode = "ISAVE"; - break; - case NullaryOp.ShowStatus: - opcode = "USL"; - break; - case NullaryOp.Catch: - opcode = "CATCH"; - break; - default: - throw UnhandledCaseException.FromEnum(op, "nullary operation"); - } + NullaryOp.RestoreUndo => "IRESTORE", + NullaryOp.SaveUndo => "ISAVE", + NullaryOp.ShowStatus => "USL", + NullaryOp.Catch => "CATCH", + _ => throw UnhandledCaseException.FromEnum(op, "nullary operation") + }; AddLine( - new Instruction(opcode) { StoreTarget = result?.ToString() }, + new Instruction(opcode) { StoreTarget = result?.ToString() }, null, PeepholeLineType.Plain); } - [NotNull] - static string OptResult([CanBeNull] IVariable result) - { - if (result == null) - return string.Empty; - - return " >" + result; - } - - public void EmitUnary(UnaryOp op, IOperand value, IVariable result) + public void EmitUnary(UnaryOp op, IOperand value, IVariable? result) { if (op == UnaryOp.Neg) { AddLine( - new Instruction("SUB", new NumericLiteral(0), value.ToAsmExpr()) { StoreTarget = result?.ToString() }, + new Instruction("SUB", new NumericLiteral(0), value.ToAsmExpr()) { StoreTarget = result?.ToString() }, null, PeepholeLineType.Plain); return; @@ -440,7 +421,7 @@ namespace Zilf.Emit.Zap var label = DefineLabel(); AddLine( - new Instruction(opcode, value.ToAsmExpr()) { StoreTarget = result?.ToString() }, + new Instruction(opcode, value.ToAsmExpr()) { StoreTarget = result?.ToString() }, label, PeepholeLineType.BranchPositive); @@ -455,7 +436,7 @@ namespace Zilf.Emit.Zap } } - public void EmitBinary(BinaryOp op, IOperand left, IOperand right, IVariable result) + public void EmitBinary(BinaryOp op, IOperand left, IOperand right, IVariable? result) { switch (op) { @@ -471,88 +452,35 @@ namespace Zilf.Emit.Zap return; } - string opcode; - - switch (op) + var opcode = op switch { - case BinaryOp.Add: - opcode = "ADD"; - break; - case BinaryOp.And: - opcode = "BAND"; - break; - case BinaryOp.ArtShift: - opcode = "ASHIFT"; - break; - case BinaryOp.Div: - opcode = "DIV"; - break; - case BinaryOp.GetByte: - opcode = "GETB"; - break; - case BinaryOp.GetPropAddress: - opcode = "GETPT"; - break; - case BinaryOp.GetProperty: - opcode = "GETP"; - break; - case BinaryOp.GetNextProp: - opcode = "NEXTP"; - break; - case BinaryOp.GetWord: - opcode = "GET"; - break; - case BinaryOp.LogShift: - opcode = "SHIFT"; - break; - case BinaryOp.Mod: - opcode = "MOD"; - break; - case BinaryOp.Mul: - opcode = "MUL"; - break; - case BinaryOp.Or: - opcode = "BOR"; - break; - case BinaryOp.Sub: - opcode = "SUB"; - break; - case BinaryOp.MoveObject: - opcode = "MOVE"; - break; - case BinaryOp.SetFlag: - opcode = "FSET"; - break; - case BinaryOp.ClearFlag: - opcode = "FCLEAR"; - break; - case BinaryOp.DirectOutput: - opcode = "DIROUT"; - break; - case BinaryOp.SetCursor: - opcode = "CURSET"; - break; - case BinaryOp.SetColor: - opcode = "COLOR"; - break; - case BinaryOp.Throw: - opcode = "THROW"; - break; - case BinaryOp.StoreIndirect: - opcode = "SET"; - break; - case BinaryOp.FlushUserStack: - opcode = "FSTACK"; - break; - case BinaryOp.GetWindowProperty: - opcode = "WINGET"; - break; - case BinaryOp.ScrollWindow: - opcode = "SCROLL"; - break; - default: - throw UnhandledCaseException.FromEnum(op, "binary operation"); - } + BinaryOp.Add => "ADD", + BinaryOp.And => "BAND", + BinaryOp.ArtShift => "ASHIFT", + BinaryOp.Div => "DIV", + BinaryOp.GetByte => "GETB", + BinaryOp.GetPropAddress => "GETPT", + BinaryOp.GetProperty => "GETP", + BinaryOp.GetNextProp => "NEXTP", + BinaryOp.GetWord => "GET", + BinaryOp.LogShift => "SHIFT", + BinaryOp.Mod => "MOD", + BinaryOp.Mul => "MUL", + BinaryOp.Or => "BOR", + BinaryOp.Sub => "SUB", + BinaryOp.MoveObject => "MOVE", + BinaryOp.SetFlag => "FSET", + BinaryOp.ClearFlag => "FCLEAR", + BinaryOp.DirectOutput => "DIROUT", + BinaryOp.SetCursor => "CURSET", + BinaryOp.SetColor => "COLOR", + BinaryOp.Throw => "THROW", + BinaryOp.StoreIndirect => "SET", + BinaryOp.FlushUserStack => "FSTACK", + BinaryOp.GetWindowProperty => "WINGET", + BinaryOp.ScrollWindow => "SCROLL", + _ => throw UnhandledCaseException.FromEnum(op, "binary operation") + }; AddLine( new Instruction(opcode, left.ToAsmExpr(), right.ToAsmExpr()) { StoreTarget = result?.ToString() }, @@ -560,54 +488,25 @@ namespace Zilf.Emit.Zap PeepholeLineType.Plain); } - public void EmitTernary(TernaryOp op, IOperand left, IOperand center, IOperand right, IVariable result) + public void EmitTernary(TernaryOp op, IOperand left, IOperand center, IOperand right, IVariable? result) { - string opcode; - - switch (op) + var opcode = op switch { - case TernaryOp.PutByte: - opcode = "PUTB"; - break; - case TernaryOp.PutProperty: - opcode = "PUTP"; - break; - case TernaryOp.PutWord: - opcode = "PUT"; - break; - case TernaryOp.CopyTable: - opcode = "COPYT"; - break; - case TernaryOp.PutWindowProperty: - opcode = "WINPUT"; - break; - case TernaryOp.DrawPicture: - opcode = "DISPLAY"; - break; - case TernaryOp.WindowStyle: - opcode = "WINATTR"; - break; - case TernaryOp.MoveWindow: - opcode = "WINPOS"; - break; - case TernaryOp.WindowSize: - opcode = "WINSIZE"; - break; - case TernaryOp.SetMargins: - opcode = "MARGIN"; - break; - case TernaryOp.SetCursor: - opcode = "CURSET"; - break; - case TernaryOp.DirectOutput: - opcode = "DIROUT"; - break; - case TernaryOp.ErasePicture: - opcode = "DCLEAR"; - break; - default: - throw UnhandledCaseException.FromEnum(op, "ternary operation"); - } + TernaryOp.PutByte => "PUTB", + TernaryOp.PutProperty => "PUTP", + TernaryOp.PutWord => "PUT", + TernaryOp.CopyTable => "COPYT", + TernaryOp.PutWindowProperty => "WINPUT", + TernaryOp.DrawPicture => "DISPLAY", + TernaryOp.WindowStyle => "WINATTR", + TernaryOp.MoveWindow => "WINPOS", + TernaryOp.WindowSize => "WINSIZE", + TernaryOp.SetMargins => "MARGIN", + TernaryOp.SetCursor => "CURSET", + TernaryOp.DirectOutput => "DIROUT", + TernaryOp.ErasePicture => "DCLEAR", + _ => throw UnhandledCaseException.FromEnum(op, "ternary operation") + }; AddLine( new Instruction(opcode, left.ToAsmExpr(), center.ToAsmExpr(), right.ToAsmExpr()) { StoreTarget = result?.ToString() }, @@ -623,7 +522,7 @@ namespace Zilf.Emit.Zap PeepholeLineType.Plain); } - public void EmitTokenize(IOperand text, IOperand parse, IOperand dictionary, IOperand flag) + public void EmitTokenize(IOperand text, IOperand parse, IOperand? dictionary, IOperand? flag) { var inst = new Instruction("LEX", text.ToAsmExpr(), parse.ToAsmExpr()); if (dictionary != null) @@ -678,7 +577,7 @@ namespace Zilf.Emit.Zap IVariable result) { AddLine( - new Instruction("SAVE", table.ToAsmExpr(), size.ToAsmExpr(), filename.ToAsmExpr()) { StoreTarget = result.ToString() }, + new Instruction("SAVE", table.ToAsmExpr(), size.ToAsmExpr(), filename.ToAsmExpr()) { StoreTarget = result.ToString() }, null, PeepholeLineType.Plain); } @@ -687,12 +586,12 @@ namespace Zilf.Emit.Zap IVariable result) { AddLine( - new Instruction("RESTORE", table.ToAsmExpr(), size.ToAsmExpr(), filename.ToAsmExpr()) { StoreTarget = result.ToString() }, + new Instruction("RESTORE", table.ToAsmExpr(), size.ToAsmExpr(), filename.ToAsmExpr()) { StoreTarget = result.ToString() }, null, PeepholeLineType.Plain); } - public void EmitScanTable(IOperand value, IOperand table, IOperand length, IOperand form, + public void EmitScanTable(IOperand value, IOperand table, IOperand length, IOperand? form, IVariable result, ILabel label, bool polarity) { var sb = new StringBuilder("INTBL? "); @@ -723,7 +622,7 @@ namespace Zilf.Emit.Zap public void EmitGetChild(IOperand value, IVariable result, ILabel label, bool polarity) { AddLine( - new Instruction("FIRST?", value.ToAsmExpr()) { StoreTarget = result.ToString() }, + new Instruction("FIRST?", value.ToAsmExpr()) { StoreTarget = result.ToString() }, label, polarity ? PeepholeLineType.BranchPositive : PeepholeLineType.BranchNegative); } @@ -753,36 +652,21 @@ namespace Zilf.Emit.Zap public void EmitPrint(PrintOp op, IOperand value) { - string opcode; - - switch (op) + var opcode = op switch { - case PrintOp.Address: - opcode = "PRINTB"; - break; - case PrintOp.Character: - opcode = "PRINTC"; - break; - case PrintOp.Number: - opcode = "PRINTN"; - break; - case PrintOp.Object: - opcode = "PRINTD"; - break; - case PrintOp.PackedAddr: - opcode = "PRINT"; - break; - case PrintOp.Unicode: - opcode = "PRINTU"; - break; - default: - throw UnhandledCaseException.FromEnum(op, "print operation"); - } + PrintOp.Address => "PRINTB", + PrintOp.Character => "PRINTC", + PrintOp.Number => "PRINTN", + PrintOp.Object => "PRINTD", + PrintOp.PackedAddr => "PRINT", + PrintOp.Unicode => "PRINTU", + _ => throw UnhandledCaseException.FromEnum(op, "print operation") + }; AddLine(new Instruction(opcode, value.ToAsmExpr()), null, PeepholeLineType.Plain); } - public void EmitPrintTable(IOperand table, IOperand width, IOperand height, IOperand skip) + public void EmitPrintTable(IOperand table, IOperand width, IOperand? height, IOperand? skip) { var inst = new Instruction("PRINTT", table.ToAsmExpr(), width.ToAsmExpr()); @@ -797,7 +681,7 @@ namespace Zilf.Emit.Zap AddLine(inst, null, PeepholeLineType.Plain); } - public void EmitPlaySound(IOperand number, IOperand effect, IOperand volume, IOperand routine) + public void EmitPlaySound(IOperand number, IOperand? effect, IOperand? volume, IOperand? routine) { var inst = new Instruction("SOUND", number.ToAsmExpr()); @@ -819,8 +703,8 @@ namespace Zilf.Emit.Zap AddLine(inst, null, PeepholeLineType.Plain); } - public void EmitRead(IOperand chrbuf, IOperand lexbuf, IOperand interval, IOperand routine, - IVariable result) + public void EmitRead(IOperand chrbuf, IOperand? lexbuf, IOperand? interval, IOperand? routine, + IVariable? result) { var inst = new Instruction("READ", chrbuf.ToAsmExpr()) { StoreTarget = result?.ToString() }; @@ -842,7 +726,7 @@ namespace Zilf.Emit.Zap AddLine(inst, null, PeepholeLineType.Plain); } - public void EmitReadChar(IOperand interval, IOperand routine, IVariable result) + public void EmitReadChar(IOperand? interval, IOperand? routine, IVariable result) { var inst = new Instruction("INPUT", new NumericLiteral(1)) { StoreTarget = result.ToString() }; @@ -860,7 +744,7 @@ namespace Zilf.Emit.Zap } /// Too many arguments were supplied for the Z-machine version. - public void EmitCall(IOperand routine, IOperand[] args, IVariable result) + public void EmitCall(IOperand routine, IOperand[] args, IVariable? result) { /* V1-3: CALL (0-3, store) * V4: CALL1 (0, store), CALL2 (1, store), XCALL (0-7, store) @@ -1008,7 +892,7 @@ namespace Zilf.Emit.Zap public void EmitPushUserStack(IOperand value, IOperand stack, ILabel label, bool polarity) { AddLine( - new Instruction("XPUSH", value.ToAsmExpr(), stack.ToAsmExpr()), + new Instruction("XPUSH", value.ToAsmExpr(), stack.ToAsmExpr()), label, polarity ? PeepholeLineType.BranchPositive : PeepholeLineType.BranchNegative); } @@ -1181,43 +1065,44 @@ namespace Zilf.Emit.Zap this.routineBuilder = routineBuilder; } - void BeginMatch([NotNull] IEnumerable> lines) + void BeginMatch(IEnumerable> lines) { enumerator = lines.GetEnumerator(); matches = new List>(); } - bool Match([ItemNotNull] [NotNull] [InstantHandle] params Predicate>[] criteria) + bool Match([InstantHandle] params Predicate>[] criteria) { + Debug.Assert(matches != null && enumerator != null); while (matches.Count < criteria.Length) { - if (enumerator.MoveNext() == false) + if (!enumerator.MoveNext()) return false; matches.Add(enumerator.Current); } - + return criteria.Zip(matches, (c, m) => c(m)).All(ok => ok); } void EndMatch() { - enumerator.Dispose(); + enumerator?.Dispose(); enumerator = null; matches = null; } - IEnumerator> enumerator; - List> matches; + IEnumerator>? enumerator; + List>? matches; - CombinerResult Combine1To1(Instruction newInstruction, PeepholeLineType? type = null, [CanBeNull] ILabel target = null) + CombinerResult Combine1To1(Instruction newInstruction, PeepholeLineType? type = null, ILabel? target = null) { return new CombinerResult( 1, new[] { new CombinableLine( - matches[0].Label, + matches![0].Label, new ZapCode { Instruction = newInstruction, DebugText = matches[0].Code.DebugText @@ -1227,13 +1112,13 @@ namespace Zilf.Emit.Zap }); } - CombinerResult Combine2To1(Instruction newInstruction, PeepholeLineType? type = null, [CanBeNull] ILabel target = null) + CombinerResult Combine2To1(Instruction newInstruction, PeepholeLineType? type = null, ILabel? target = null) { return new CombinerResult( 2, new[] { new CombinableLine( - matches[0].Label, + matches![0].Label, new ZapCode { Instruction = newInstruction, DebugText = MergeDebugText(matches[0].Code.DebugText, matches[1].Code.DebugText), @@ -1246,13 +1131,13 @@ namespace Zilf.Emit.Zap CombinerResult Combine2To2( Instruction newInstruction1, Instruction newInstruction2, PeepholeLineType? type1 = null, PeepholeLineType? type2 = null, - [CanBeNull] ILabel target1 = null, [CanBeNull] ILabel target2 = null) + ILabel? target1 = null, ILabel? target2 = null) { return new CombinerResult( 2, new[] { new CombinableLine( - matches[0].Label, + matches![0].Label, new ZapCode { Instruction = newInstruction1, DebugText = matches[0].Code.DebugText @@ -1276,21 +1161,20 @@ namespace Zilf.Emit.Zap } [ContractAnnotation("=> true, otherSide: notnull; => false, otherSide: null")] - static bool IsEqualZero([NotNull] Instruction inst, out AsmExpr otherSide) + static bool IsEqualZero(Instruction inst, + [NotNullWhen(true)] out AsmExpr? otherSide) { if (inst.Name == "EQUAL?" && inst.Operands.Count == 2) { - if (inst.Operands[0] is NumericLiteral num && num.Value == 0) + switch (inst.Operands[0], inst.Operands[1]) { - otherSide = inst.Operands[1]; - return true; - } + case (NumericLiteral { Value: 0 }, var rhs): + otherSide = rhs; + return true; - num = inst.Operands[1] as NumericLiteral; - if (num != null && num.Value == 0) - { - otherSide = inst.Operands[0]; - return true; + case (var lhs, NumericLiteral { Value: 0 }): + otherSide = lhs; + return true; } } @@ -1299,33 +1183,35 @@ namespace Zilf.Emit.Zap } [ContractAnnotation("=> true, dest: notnull, constant: notnull; => false, dest: null, constant: null")] - static bool IsBANDConstantWithStack([NotNull] Instruction inst, out NumericLiteral constant, out string dest) => + static bool IsBANDConstantWithStack(Instruction inst, + [NotNullWhen(true)] out NumericLiteral? constant, [NotNullWhen(true)] out string? dest) => IsCommutativeConstantWithStack("BAND", inst, out constant, out dest); [ContractAnnotation("=> true, dest: notnull, constant: notnull; => false, dest: null, constant: null")] - static bool IsBORConstantWithStack([NotNull] Instruction inst, out NumericLiteral constant, out string dest) => + static bool IsBORConstantWithStack(Instruction inst, + [NotNullWhen(true)] out NumericLiteral? constant, [NotNullWhen(true)] out string? dest) => IsCommutativeConstantWithStack("BOR", inst, out constant, out dest); [ContractAnnotation("=> true, dest: notnull, constant: notnull; => false, dest: null, constant: null")] static bool IsCommutativeConstantWithStack( - [NotNull] string instructionName, [NotNull] Instruction inst, - out NumericLiteral constant, out string dest) + string instructionName, Instruction inst, + [NotNullWhen(true)] out NumericLiteral? constant, [NotNullWhen(true)] out string? dest) { if (inst.Name == instructionName && inst.Operands.Count == 2) { - if (inst.Operands[0] is NumericLiteral num && inst.Operands[1].IsStack()) - { - constant = num; - dest = inst.StoreTarget; - return true; - } + Debug.Assert(inst.StoreTarget != null); - num = inst.Operands[1] as NumericLiteral; - if (num != null && inst.Operands[0].IsStack()) + switch (inst.Operands[0], inst.Operands[1]) { - constant = num; - dest = inst.StoreTarget; - return true; + case (NumericLiteral num, var other) when other.IsStack(): + constant = num; + dest = inst.StoreTarget; + return true; + + case (var other, NumericLiteral num) when other.IsStack(): + constant = num; + dest = inst.StoreTarget; + return true; } } @@ -1336,37 +1222,37 @@ namespace Zilf.Emit.Zap [ContractAnnotation( "=> true, variable: notnull, constant: notnull; => false, variable: null, constant: null")] - static bool IsBANDConstantToStack([NotNull] Instruction inst, out AsmExpr variable, - out NumericLiteral constant) => + static bool IsBANDConstantToStack(Instruction inst, + [NotNullWhen(true)] out AsmExpr? variable, + [NotNullWhen(true)] out NumericLiteral? constant) => IsCommutativeConstantToStack("BAND", inst, out variable, out constant); [ContractAnnotation( "=> true, variable: notnull, constant: notnull; => false, variable: null, constant: null")] - static bool IsBORConstantToStack([NotNull] Instruction inst, out AsmExpr variable, - out NumericLiteral constant) => + static bool IsBORConstantToStack(Instruction inst, + [NotNullWhen(true)] out AsmExpr? variable, + [NotNullWhen(true)] out NumericLiteral? constant) => IsCommutativeConstantToStack("BOR", inst, out variable, out constant); [ContractAnnotation( "=> true, variable: notnull, constant: notnull; => false, variable: null, constant: null")] static bool IsCommutativeConstantToStack( - [NotNull] string instructionName, [NotNull] Instruction inst, - out AsmExpr variable, out NumericLiteral constant) + string instructionName, Instruction inst, + [NotNullWhen(true)] out AsmExpr? variable, [NotNullWhen(true)] out NumericLiteral? constant) { if (inst.Name == instructionName && inst.Operands.Count == 2 && inst.StoreTarget == "STACK") { - if (inst.Operands[0] is NumericLiteral num) - { - variable = inst.Operands[1]; - constant = num; - return true; - } - - num = inst.Operands[1] as NumericLiteral; - if (num != null) + switch (inst.Operands[0], inst.Operands[1]) { - variable = inst.Operands[0]; - constant = num; - return true; + case (NumericLiteral num, var other): + variable = other; + constant = num; + return true; + + case (var other, NumericLiteral num): + variable = other; + constant = num; + return true; } } @@ -1375,7 +1261,8 @@ namespace Zilf.Emit.Zap } [ContractAnnotation("=> true, dest: notnull; => false, dest: null")] - static bool IsPopToVariable([NotNull] Instruction inst, out string dest) + static bool IsPopToVariable(Instruction inst, + [NotNullWhen(true)] out string? dest) { switch (inst.Name) { @@ -1396,9 +1283,9 @@ namespace Zilf.Emit.Zap /// public CombinerResult Apply(IEnumerable> lines) { - AsmExpr expr1 = null; - NumericLiteral const1 = null, const2 = null; - string destStr = null; + AsmExpr? expr1 = null; + NumericLiteral? const1 = null, const2 = null; + string? destStr = null; BeginMatch(lines); try @@ -1406,13 +1293,13 @@ namespace Zilf.Emit.Zap if (Match(a => IsEqualZero(a.Code.Instruction, out expr1))) { // EQUAL? x,0 | EQUAL? 0,x => ZERO? x - return Combine1To1(new Instruction("ZERO?", expr1)); + return Combine1To1(new Instruction("ZERO?", expr1!)); } - if (Match(a => a.Code.Instruction.Name=="JUMP" && (a.Target == RTRUE || a.Target==RFALSE))) + if (Match(a => a.Code.Instruction.Name == "JUMP" && (a.Target == RTRUE || a.Target == RFALSE))) { // JUMP to TRUE/FALSE => RTRUE/RFALSE - return Combine1To1(new Instruction(matches[0].Target == RTRUE ? "RTRUE" : "RFALSE")); + return Combine1To1(new Instruction(matches![0].Target == RTRUE ? "RTRUE" : "RFALSE")); } //if (Match(a => a.Code.Text.StartsWith("PUSH ", StringComparison.Ordinal), b => b.Code.Text == "RSTACK")) @@ -1420,22 +1307,25 @@ namespace Zilf.Emit.Zap b => b.Code.Instruction.Name == "RSTACK")) { // PUSH + RSTACK => RFALSE/RTRUE/RETURN - switch (matches[0].Code.Instruction.Operands[0]) + return matches![0].Code.Instruction.Operands[0] switch { - case NumericLiteral lit when lit.Value == 0: - return Combine2To1(new Instruction("RFALSE"), PeepholeLineType.BranchAlways, RFALSE); - case NumericLiteral lit when lit.Value == 1: - return Combine2To1(new Instruction("RTRUE"), PeepholeLineType.BranchAlways, RTRUE); - default: - return Combine2To1(matches[0].Code.Instruction.WithName("RETURN")); - } + NumericLiteral { Value: 0 } => + Combine2To1(new Instruction("RFALSE"), + PeepholeLineType.BranchAlways, + RFALSE), + NumericLiteral { Value: 1 } => + Combine2To1(new Instruction("RTRUE"), + PeepholeLineType.BranchAlways, + RTRUE), + _ => Combine2To1(matches[0].Code.Instruction.WithName("RETURN")) + }; } if (Match(a => a.Code.Instruction.StoreTarget == "STACK", b => IsPopToVariable(b.Code.Instruction, out destStr))) { // >STACK + POP 'dest => >dest - return Combine2To1(matches[0].Code.Instruction.WithStoreTarget(destStr)); + return Combine2To1(matches![0].Code.Instruction.WithStoreTarget(destStr)); } if (Match(a => a.Code.Instruction.Name == "PUSH", @@ -1444,31 +1334,31 @@ namespace Zilf.Emit.Zap // PUSH + POP 'dest => SET 'dest return Combine2To1(new Instruction( "SET", - new QuoteExpr(new SymbolExpr(destStr)), - matches[0].Code.Instruction.Operands[0])); + new QuoteExpr(new SymbolExpr(destStr!)), + matches![0].Code.Instruction.Operands[0])); } if (Match( a => a.Code.Instruction.Name == "INC" && a.Code.Instruction.Operands[0].IsQuote(out expr1) && !expr1.IsStack(), - b => b.Code.Instruction.Name == "GRTR?" && b.Code.Instruction.Operands[0].Equals(expr1))) + b => b.Code.Instruction.Name == "GRTR?" && b.Code.Instruction.Operands[0].Equals(expr1!))) { // INC 'v + GRTR? v,w => IGRTR? 'v,w return Combine2To1(new Instruction( "IGRTR?", - matches[0].Code.Instruction.Operands[0], + matches![0].Code.Instruction.Operands[0], matches[1].Code.Instruction.Operands[1])); } if (Match( a => a.Code.Instruction.Name == "DEC" && a.Code.Instruction.Operands[0].IsQuote(out expr1) && !expr1.IsStack(), - b => b.Code.Instruction.Name == "LESS?" && b.Code.Instruction.Operands[0].Equals(expr1))) + b => b.Code.Instruction.Name == "LESS?" && b.Code.Instruction.Operands[0].Equals(expr1!))) { // DEC 'v + LESS? v,w => DLESS? 'v,w return Combine2To1(new Instruction( "DLESS?", - matches[0].Code.Instruction.Operands[0], + matches![0].Code.Instruction.Operands[0], matches[1].Code.Instruction.Operands[1])); } @@ -1478,9 +1368,9 @@ namespace Zilf.Emit.Zap b => (b.Code.Instruction.Name == "EQUAL?" || b.Code.Instruction.Name == "ZERO?") && b.Type == PeepholeLineType.BranchPositive)) { - if (matches[0].Target == matches[1].Target) + if (matches![0].Target == matches[1].Target) { - IList GetParts(Instruction inst) + static IList GetParts(Instruction inst) { return inst.Name == "ZERO?" ? new[] { inst.Operands[0], new NumericLiteral(0) } @@ -1523,10 +1413,10 @@ namespace Zilf.Emit.Zap } //if (Match(a => a.Code.Text.StartsWith("PRINTI ", StringComparison.Ordinal), b => b.Code.Text == "CRLF+RTRUE")) - if (Match(a => a.Code.Instruction.Name == "PRINTI", b => b.Code.Instruction.Name=="CRLF+RTRUE")) + if (Match(a => a.Code.Instruction.Name == "PRINTI", b => b.Code.Instruction.Name == "CRLF+RTRUE")) { // PRINTI + (CRLF + RTRUE) => PRINTR - return Combine2To1(matches[0].Code.Instruction.WithName("PRINTR"), PeepholeLineType.HeavyTerminator); + return Combine2To1(matches![0].Code.Instruction.WithName("PRINTR"), PeepholeLineType.HeavyTerminator); } // BAND v,c >STACK + ZERO? STACK /L => @@ -1535,24 +1425,24 @@ namespace Zilf.Emit.Zap if (Match(a => IsBANDConstantToStack(a.Code.Instruction, out expr1, out const1), b => b.Code.Instruction.Name == "ZERO?" && b.Code.Instruction.Operands[0].IsStack())) { - var constantValue = const1.Value; + var constantValue = const1!.Value; if (constantValue == 0) { - if (!expr1.IsStack()) + if (!expr1!.IsStack()) { - return matches[1].Type == PeepholeLineType.BranchPositive + return matches![1].Type == PeepholeLineType.BranchPositive ? Combine2To1(new Instruction("JUMP"), PeepholeLineType.BranchAlways, matches[1].Target) : Consume(2); } } else if ((constantValue & (constantValue - 1)) == 0) { - var oppositeType = matches[1].Type == PeepholeLineType.BranchPositive + var oppositeType = matches![1].Type == PeepholeLineType.BranchPositive ? PeepholeLineType.BranchNegative : PeepholeLineType.BranchPositive; - return Combine2To1(new Instruction("BTST", expr1, const1), oppositeType); + return Combine2To1(new Instruction("BTST", expr1!, const1), oppositeType); } } @@ -1560,18 +1450,18 @@ namespace Zilf.Emit.Zap if (Match(a => IsBANDConstantToStack(a.Code.Instruction, out expr1, out const1), b => IsBANDConstantWithStack(b.Code.Instruction, out const2, out destStr))) { - var combined = const1.Value & const2.Value; + var combined = const1!.Value & const2!.Value; return Combine2To1( - new Instruction("BAND", expr1, new NumericLiteral(combined)) { StoreTarget = destStr }); + new Instruction("BAND", expr1!, new NumericLiteral(combined)) { StoreTarget = destStr }); } // BOR v,c1 >STACK + BOR STACK,c2 >dest => BOR v,(c1|c2) >dest if (Match(a => IsBORConstantToStack(a.Code.Instruction, out expr1, out const1), b => IsBORConstantWithStack(b.Code.Instruction, out const2, out destStr))) { - var combined = const1.Value | const2.Value; + var combined = const1!.Value | const2!.Value; return Combine2To1( - new Instruction("BOR", expr1, new NumericLiteral(combined)) { StoreTarget = destStr }); + new Instruction("BOR", expr1!, new NumericLiteral(combined)) { StoreTarget = destStr }); } // no matches @@ -1588,8 +1478,7 @@ namespace Zilf.Emit.Zap return new ZapCode { Instruction = new Instruction("JUMP") }; } - [CanBeNull] - private static string MergeDebugText([CanBeNull] string text1, [CanBeNull] string text2) + private static string? MergeDebugText(string? text1, string? text2) { return text1 == null ? text2 @@ -1598,10 +1487,7 @@ namespace Zilf.Emit.Zap : $"{text1}{Environment.NewLine}{INDENT}{text2}"; } - public bool AreIdentical(ZapCode a, ZapCode b) - { - return a.Instruction.Equals(b.Instruction); - } + public bool AreIdentical(ZapCode a, ZapCode b) => a.Instruction.Equals(b.Instruction); public ZapCode MergeIdentical(ZapCode a, ZapCode b) { diff --git a/src/Zilf.Emit/Zap/SumOperand.cs b/src/Zilf.Emit/Zap/SumOperand.cs index 590c4c3..abc856a 100644 --- a/src/Zilf.Emit/Zap/SumOperand.cs +++ b/src/Zilf.Emit/Zap/SumOperand.cs @@ -22,16 +22,14 @@ namespace Zilf.Emit.Zap { class SumOperand : IConstantOperand { - public SumOperand([NotNull] IConstantOperand left, [NotNull] IConstantOperand right) + public SumOperand(IConstantOperand left, IConstantOperand right) { Left = left; Right = right; } - [NotNull] public IConstantOperand Left { get; } - [NotNull] public IConstantOperand Right { get; } public override string ToString() diff --git a/src/Zilf.Emit/Zap/TableBuilder.cs b/src/Zilf.Emit/Zap/TableBuilder.cs index 445e24f..cf92b66 100644 --- a/src/Zilf.Emit/Zap/TableBuilder.cs +++ b/src/Zilf.Emit/Zap/TableBuilder.cs @@ -39,12 +39,11 @@ namespace Zilf.Emit.Zap protected const string INDENT = "\t"; - public TableBuilder([NotNull] string name) + public TableBuilder(string name) { Name = name; } - [NotNull] public string Name { get; } public int Size => size; @@ -82,7 +81,7 @@ namespace Zilf.Emit.Zap return Name; } - public void WriteTo([NotNull] TextWriter writer) + public void WriteTo(TextWriter writer) { bool wasWord = false; int lineCount = 0, ni = 0, oi = 0; diff --git a/src/Zilf.Emit/Zap/WordBuilder.cs b/src/Zilf.Emit/Zap/WordBuilder.cs index 6fa068d..b6e681b 100644 --- a/src/Zilf.Emit/Zap/WordBuilder.cs +++ b/src/Zilf.Emit/Zap/WordBuilder.cs @@ -22,13 +22,12 @@ namespace Zilf.Emit.Zap { class WordBuilder : TableBuilder, IWordBuilder { - public WordBuilder([NotNull] string tableName, [NotNull] string word) + public WordBuilder(string tableName, string word) : base(tableName) { Word = word; } - [NotNull] public string Word { get; } } } \ No newline at end of file diff --git a/src/Zilf.Emit/Zap/ZapCode.cs b/src/Zilf.Emit/Zap/ZapCode.cs index b511554..e6e5b8e 100644 --- a/src/Zilf.Emit/Zap/ZapCode.cs +++ b/src/Zilf.Emit/Zap/ZapCode.cs @@ -23,11 +23,8 @@ namespace Zilf.Emit.Zap struct ZapCode { public Instruction Instruction; - public string DebugText; + public string? DebugText; - public override string ToString() - { - return Instruction.ToString(); - } + public override string ToString() => Instruction.ToString(); } } diff --git a/src/Zilf.Emit/Zilf.Emit.csproj b/src/Zilf.Emit/Zilf.Emit.csproj index 303199c..d8964f5 100644 --- a/src/Zilf.Emit/Zilf.Emit.csproj +++ b/src/Zilf.Emit/Zilf.Emit.csproj @@ -1,11 +1,8 @@  - netstandard2.0 - 7.3 + netstandard2.1 Provides ZAP code generation interfaces for ZILF. - - - 7.3 + enable diff --git a/src/Zilf/.editorconfig b/src/Zilf/.editorconfig new file mode 100644 index 0000000..e0066fe --- /dev/null +++ b/src/Zilf/.editorconfig @@ -0,0 +1,16 @@ +[*.cs] + +# CA1303: Do not pass literals as localized parameters +dotnet_diagnostic.CA1303.severity = none + +# RCS1139: Add summary element to documentation comment. +dotnet_diagnostic.RCS1139.severity = none + +# CA1305: Specify IFormatProvider +dotnet_diagnostic.CA1305.severity = suggestion + +# CA1710: Identifiers should have correct suffix +dotnet_diagnostic.CA1710.severity = suggestion + +# CA1307: Specify StringComparison +dotnet_diagnostic.CA1307.severity = suggestion diff --git a/src/Zilf/Compiler/Action.cs b/src/Zilf/Compiler/Action.cs index c9f6fe0..e75d5e9 100644 --- a/src/Zilf/Compiler/Action.cs +++ b/src/Zilf/Compiler/Action.cs @@ -25,11 +25,13 @@ namespace Zilf.Compiler { public readonly int Index; public readonly IOperand Constant; - public readonly IRoutineBuilder Routine, PreRoutine; - public readonly ZilAtom RoutineName, PreRoutineName; + public readonly IRoutineBuilder Routine; + public readonly IRoutineBuilder? PreRoutine; + public readonly ZilAtom RoutineName; + public readonly ZilAtom? PreRoutineName; - public Action(int index, IOperand constant, IRoutineBuilder routine, IRoutineBuilder preRoutine, - ZilAtom routineName, ZilAtom preRoutineName) + public Action(int index, IOperand constant, IRoutineBuilder routine, IRoutineBuilder? preRoutine, + ZilAtom routineName, ZilAtom? preRoutineName) { Index = index; Constant = constant; diff --git a/src/Zilf/Compiler/Block.cs b/src/Zilf/Compiler/Block.cs index 50faf92..7202d87 100644 --- a/src/Zilf/Compiler/Block.cs +++ b/src/Zilf/Compiler/Block.cs @@ -26,16 +26,16 @@ namespace Zilf.Compiler /// /// The activation atom identifying the block, or null if it is unnamed. /// - public ZilAtom Name; + public ZilAtom? Name; /// /// The label to which <AGAIN> should branch. /// - public ILabel AgainLabel; + public ILabel? AgainLabel; /// /// The label to which <RETURN> should branch, or null if /// it should return from the routine. /// - public ILabel ReturnLabel; + public ILabel? ReturnLabel; /// /// The context flags for <RETURN>. /// @@ -45,6 +45,6 @@ namespace Zilf.Compiler /// , if /// is set in . /// - public IVariable ResultStorage; + public IVariable? ResultStorage; } } diff --git a/src/Zilf/Compiler/Builtins/BuiltinArg.cs b/src/Zilf/Compiler/Builtins/BuiltinArg.cs index 99383dc..65568e5 100644 --- a/src/Zilf/Compiler/Builtins/BuiltinArg.cs +++ b/src/Zilf/Compiler/Builtins/BuiltinArg.cs @@ -21,9 +21,9 @@ namespace Zilf.Compiler.Builtins struct BuiltinArg { public readonly BuiltinArgType Type; - public readonly object Value; + public readonly object? Value; - public BuiltinArg(BuiltinArgType type, object value) + public BuiltinArg(BuiltinArgType type, object? value) { Type = type; Value = value; diff --git a/src/Zilf/Compiler/Builtins/BuiltinAttribute.cs b/src/Zilf/Compiler/Builtins/BuiltinAttribute.cs index 5e3b1e3..f62d236 100644 --- a/src/Zilf/Compiler/Builtins/BuiltinAttribute.cs +++ b/src/Zilf/Compiler/Builtins/BuiltinAttribute.cs @@ -34,7 +34,7 @@ namespace Zilf.Compiler.Builtins { } - public BuiltinAttribute(string name, params string[] aliases) + public BuiltinAttribute(string name, params string[]? aliases) { this.name = name; this.aliases = aliases; @@ -46,7 +46,7 @@ namespace Zilf.Compiler.Builtins } readonly string name; - readonly string[] aliases; + readonly string[]? aliases; public IEnumerable Names { @@ -62,7 +62,7 @@ namespace Zilf.Compiler.Builtins } } - public object Data { get; set; } + public object? Data { get; set; } public int MinVersion { get; set; } public int MaxVersion { get; set; } public bool HasSideEffect { get; set; } diff --git a/src/Zilf/Compiler/Builtins/BuiltinSpec.cs b/src/Zilf/Compiler/Builtins/BuiltinSpec.cs index 558952d..506c415 100644 --- a/src/Zilf/Compiler/Builtins/BuiltinSpec.cs +++ b/src/Zilf/Compiler/Builtins/BuiltinSpec.cs @@ -21,9 +21,9 @@ using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; +using System.Runtime.CompilerServices; using Zilf.Emit; using Zilf.ZModel; -using JetBrains.Annotations; namespace Zilf.Compiler.Builtins { @@ -31,18 +31,18 @@ namespace Zilf.Compiler.Builtins { public readonly int MinArgs; public readonly int? MaxArgs; - [NotNull] public readonly Type CallType; - [NotNull] public readonly BuiltinAttribute Attr; - [NotNull] public readonly MethodInfo Method; /// The attribute values or method signature are invalid. // ReSharper disable once NotNullMemberIsNotInitialized - public BuiltinSpec([NotNull] BuiltinAttribute attr, [NotNull] MethodInfo method) + public BuiltinSpec(BuiltinAttribute attr, MethodInfo method) { + // suppress CS8618 - the compiler can't tell we always set CallType + CallType = typeof(void); + try { Attr = attr; @@ -51,7 +51,7 @@ namespace Zilf.Compiler.Builtins // count args and find call type int min = 0; int? max = 0; - Type dataParamType = null; + Type? dataParamType = null; var parameters = method.GetParameters(); if (parameters.Length == 0) @@ -159,14 +159,16 @@ namespace Zilf.Compiler.Builtins catch (ArgumentException ex) { throw new ArgumentException(string.Format( - CultureInfo.CurrentCulture, - "Bad attribute {0} on method {1}", - attr.Names.First(), method.Name), + CultureInfo.CurrentCulture, + "Bad attribute {0} on method {1}", + attr.Names.First(), method.Name), ex); } + + Debug.Assert(CallType != typeof(void)); } - public bool AppliesTo(int zversion, int argCount, [CanBeNull] Type callType = null) + public bool AppliesTo(int zversion, int argCount, Type? callType = null) { if (!ZEnvironment.VersionMatches(zversion, Attr.MinVersion, Attr.MaxVersion)) return false; diff --git a/src/Zilf/Compiler/Builtins/ParameterTypeHandler.cs b/src/Zilf/Compiler/Builtins/ParameterTypeHandler.cs index df20ad8..f5d7165 100644 --- a/src/Zilf/Compiler/Builtins/ParameterTypeHandler.cs +++ b/src/Zilf/Compiler/Builtins/ParameterTypeHandler.cs @@ -30,17 +30,15 @@ namespace Zilf.Compiler.Builtins { abstract class ParameterTypeHandler { - public abstract BuiltinArg Process([NotNull] Compilation cc, [NotNull] [InstantHandle] Action error, - [NotNull] ZilObject arg, [NotNull] ParameterInfo pi); + public abstract BuiltinArg Process(Compilation cc, [InstantHandle] Action error, + ZilObject arg, ParameterInfo pi); public virtual bool IsVariable => false; /// /// Does not need to handle optional or varargs. /// - [NotNull] - public abstract SignaturePart ToSignaturePart([NotNull] ParameterInfo pi); + public abstract SignaturePart ToSignaturePart(ParameterInfo pi); - [NotNull] public static readonly IReadOnlyDictionary Handlers = new Dictionary { @@ -54,16 +52,16 @@ namespace Zilf.Compiler.Builtins { typeof(ZilObject), new ZilObjectHandler() }, }; - static VariableRef? GetVariable([NotNull] Compilation cc, [NotNull] ZilObject expr, QuirksMode quirks = QuirksMode.None) + static VariableRef? GetVariable(Compilation cc, ZilObject expr, VariableScopeQuirks quirks = VariableScopeQuirks.None) { if (!(expr is ZilAtom atom) && - ((quirks & QuirksMode.Global) == 0 || !expr.IsGVAL(out atom)) && - ((quirks & QuirksMode.Local) == 0 || !expr.IsLVAL(out atom))) + ((quirks & VariableScopeQuirks.Global) == 0 || !expr.IsGVAL(out atom!)) && + ((quirks & VariableScopeQuirks.Local) == 0 || !expr.IsLVAL(out atom!))) { return null; } - if (quirks == QuirksMode.Global) + if (quirks == VariableScopeQuirks.Global) { // prefer global over local if (cc.Globals.TryGetValue(atom, out var gb)) @@ -108,7 +106,7 @@ namespace Zilf.Compiler.Builtins public override SignaturePart ToSignaturePart(ParameterInfo pi) { return SignatureBuilder.Constrained( - SignatureBuilder.Identifier(pi.Name), + SignatureBuilder.Identifier(pi.Name!), Constraint.OfType(StdAtom.ACTIVATION)); } } @@ -126,7 +124,7 @@ namespace Zilf.Compiler.Builtins public override SignaturePart ToSignaturePart(ParameterInfo pi) { return SignatureBuilder.Constrained( - SignatureBuilder.Identifier(pi.Name), + SignatureBuilder.Identifier(pi.Name!), Constraint.OfType(StdAtom.FIX)); } } @@ -144,7 +142,7 @@ namespace Zilf.Compiler.Builtins public override SignaturePart ToSignaturePart(ParameterInfo pi) { return SignatureBuilder.Constrained( - SignatureBuilder.Identifier(pi.Name), + SignatureBuilder.Identifier(pi.Name!), Constraint.OfType(StdAtom.ATOM)); } } @@ -158,7 +156,7 @@ namespace Zilf.Compiler.Builtins public override SignaturePart ToSignaturePart(ParameterInfo pi) { - return SignatureBuilder.Identifier(pi.Name); + return SignatureBuilder.Identifier(pi.Name!); } } @@ -170,7 +168,7 @@ namespace Zilf.Compiler.Builtins var varAttr = pi.GetCustomAttributes().SingleOrDefault(); if (varAttr != null) { - if (GetVariable(cc, arg, varAttr.QuirksMode) is VariableRef variable) + if (GetVariable(cc, arg, varAttr.VariableScopeQuirks) is VariableRef variable) { if (!variable.IsHard) { @@ -179,7 +177,7 @@ namespace Zilf.Compiler.Builtins } else { - return new BuiltinArg(BuiltinArgType.Operand, variable.Hard.Indirect); + return new BuiltinArg(BuiltinArgType.Operand, variable.Hard!.Indirect); } } else if (arg is ZilAtom) @@ -200,7 +198,7 @@ namespace Zilf.Compiler.Builtins public override SignaturePart ToSignaturePart(ParameterInfo pi) { - return SignatureBuilder.Identifier(pi.Name); + return SignatureBuilder.Identifier(pi.Name!); } } @@ -221,7 +219,7 @@ namespace Zilf.Compiler.Builtins public override SignaturePart ToSignaturePart(ParameterInfo pi) { return SignatureBuilder.Constrained( - SignatureBuilder.Identifier(pi.Name), + SignatureBuilder.Identifier(pi.Name!), Constraint.OfType(StdAtom.STRING)); } } @@ -232,12 +230,12 @@ namespace Zilf.Compiler.Builtins public override BuiltinArg Process(Compilation cc, Action error, ZilObject arg, ParameterInfo pi) { - var quirks = pi.GetCustomAttributes().Single().QuirksMode; + var quirks = pi.GetCustomAttributes().Single().VariableScopeQuirks; // arg must be an atom, or or in quirks mode var atom = arg as ZilAtom; - if (atom == null && !((quirks & QuirksMode.Global) != 0 && arg.IsGVAL(out atom) || - (quirks & QuirksMode.Local) != 0 && arg.IsLVAL(out atom))) + if (atom == null && !((quirks & VariableScopeQuirks.Global) != 0 && arg.IsGVAL(out atom) || + (quirks & VariableScopeQuirks.Local) != 0 && arg.IsLVAL(out atom))) { error("argument must be a variable"); return new BuiltinArg(BuiltinArgType.Operand, null); @@ -265,22 +263,22 @@ namespace Zilf.Compiler.Builtins { var constraint = Constraint.OfType(StdAtom.ATOM); - var quirks = pi.GetCustomAttributes().Single().QuirksMode; + var quirks = pi.GetCustomAttributes().Single().VariableScopeQuirks; - if ((quirks & QuirksMode.Global) != 0) + if ((quirks & VariableScopeQuirks.Global) != 0) { //XXX constraint = constraint.Or(Constraint.OfType(StdAtom.GVAL)); } - if ((quirks & QuirksMode.Local) != 0) + if ((quirks & VariableScopeQuirks.Local) != 0) { //XXX constraint = constraint.Or(Constraint.OfType(StdAtom.LVAL)); } return SignatureBuilder.Constrained( - SignatureBuilder.Identifier(pi.Name), + SignatureBuilder.Identifier(pi.Name!), constraint); } } diff --git a/src/Zilf/Compiler/Builtins/PredCall.cs b/src/Zilf/Compiler/Builtins/PredCall.cs index e4a3b3e..db51df5 100644 --- a/src/Zilf/Compiler/Builtins/PredCall.cs +++ b/src/Zilf/Compiler/Builtins/PredCall.cs @@ -27,18 +27,14 @@ namespace Zilf.Compiler.Builtins [SuppressMessage("ReSharper", "InconsistentNaming")] struct PredCall { - [NotNull] public Compilation cc { get; } - [NotNull] public IRoutineBuilder rb { get; } - [NotNull] public ZilForm form { get; } - [NotNull] public ILabel label { get; } public bool polarity { get; } - public PredCall([NotNull] Compilation cc, [NotNull] IRoutineBuilder rb, [NotNull] ZilForm form, [NotNull] ILabel label, bool polarity) + public PredCall(Compilation cc, IRoutineBuilder rb, ZilForm form, ILabel label, bool polarity) : this() { this.cc = cc; diff --git a/src/Zilf/Compiler/Builtins/ValueCall.cs b/src/Zilf/Compiler/Builtins/ValueCall.cs index c3dc524..962c027 100644 --- a/src/Zilf/Compiler/Builtins/ValueCall.cs +++ b/src/Zilf/Compiler/Builtins/ValueCall.cs @@ -28,17 +28,13 @@ namespace Zilf.Compiler.Builtins [SuppressMessage("ReSharper", "InconsistentNaming")] struct ValueCall { - [NotNull] public Compilation cc { get; } - [NotNull] public IRoutineBuilder rb { get; } - [NotNull] public ZilForm form { get; } - [NotNull] public IVariable resultStorage { get; } - public ValueCall([NotNull] Compilation cc, [NotNull] IRoutineBuilder rb, [NotNull] ZilForm form, [NotNull] IVariable resultStorage) + public ValueCall(Compilation cc, IRoutineBuilder rb, ZilForm form, IVariable resultStorage) : this() { this.cc = cc; @@ -47,7 +43,6 @@ namespace Zilf.Compiler.Builtins this.resultStorage = resultStorage; } - [NotNull] public IOperand HandleMessage(int code, params object[] args) { cc.Context.HandleError(new CompilerError(form, code, args)); diff --git a/src/Zilf/Compiler/Builtins/ValuePredCall.cs b/src/Zilf/Compiler/Builtins/ValuePredCall.cs index 580b257..33b2b21 100644 --- a/src/Zilf/Compiler/Builtins/ValuePredCall.cs +++ b/src/Zilf/Compiler/Builtins/ValuePredCall.cs @@ -28,22 +28,22 @@ namespace Zilf.Compiler.Builtins [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] struct ValuePredCall { - [NotNull, PublicAPI] + [PublicAPI] public Compilation cc { get; } - [NotNull, PublicAPI] + [PublicAPI] public IRoutineBuilder rb { get; } - [NotNull, PublicAPI] + [PublicAPI] public ZilForm form { get; } - [NotNull, PublicAPI] + [PublicAPI] public IVariable resultStorage { get; } - [NotNull, PublicAPI] + [PublicAPI] public ILabel label { get; } [PublicAPI] public bool polarity { get; } - public ValuePredCall([NotNull] Compilation cc, [NotNull] IRoutineBuilder rb, [NotNull] ZilForm form, - [NotNull] IVariable resultStorage, [NotNull] ILabel label, bool polarity) + public ValuePredCall(Compilation cc, IRoutineBuilder rb, ZilForm form, + IVariable resultStorage, ILabel label, bool polarity) : this() { this.cc = cc; diff --git a/src/Zilf/Compiler/Builtins/VariableAttribute.cs b/src/Zilf/Compiler/Builtins/VariableAttribute.cs index 9c95701..428a069 100644 --- a/src/Zilf/Compiler/Builtins/VariableAttribute.cs +++ b/src/Zilf/Compiler/Builtins/VariableAttribute.cs @@ -35,6 +35,6 @@ namespace Zilf.Compiler.Builtins /// as referring to its index. Use <VALUE X> to force the /// value to be used. /// - public QuirksMode QuirksMode { get; set; } + public VariableScopeQuirks VariableScopeQuirks { get; set; } } } \ No newline at end of file diff --git a/src/Zilf/Compiler/Builtins/QuirksMode.cs b/src/Zilf/Compiler/Builtins/VariableScopeQuirks.cs similarity index 89% rename from src/Zilf/Compiler/Builtins/QuirksMode.cs rename to src/Zilf/Compiler/Builtins/VariableScopeQuirks.cs index 60a84ab..a7ce7fb 100644 --- a/src/Zilf/Compiler/Builtins/QuirksMode.cs +++ b/src/Zilf/Compiler/Builtins/VariableScopeQuirks.cs @@ -21,11 +21,11 @@ using System; namespace Zilf.Compiler.Builtins { [Flags] - public enum QuirksMode + public enum VariableScopeQuirks { None = 0, Local = 1, Global = 2, - Both = 3, + Both = Local | Global, } } \ No newline at end of file diff --git a/src/Zilf/Compiler/Builtins/VoidCall.cs b/src/Zilf/Compiler/Builtins/VoidCall.cs index 8ce1c40..db3052d 100644 --- a/src/Zilf/Compiler/Builtins/VoidCall.cs +++ b/src/Zilf/Compiler/Builtins/VoidCall.cs @@ -28,14 +28,11 @@ namespace Zilf.Compiler.Builtins [SuppressMessage("ReSharper", "InconsistentNaming")] struct VoidCall { - [NotNull] public Compilation cc { get; } - [NotNull] public IRoutineBuilder rb { get; } - [NotNull] public ZilForm form { get; } - public VoidCall([NotNull] Compilation cc, [NotNull] IRoutineBuilder rb, [NotNull] ZilForm form) + public VoidCall(Compilation cc, IRoutineBuilder rb, ZilForm form) : this() { this.cc = cc; diff --git a/src/Zilf/Compiler/Builtins/ZBuiltins.cs b/src/Zilf/Compiler/Builtins/ZBuiltins.cs index 432fa49..d68867d 100644 --- a/src/Zilf/Compiler/Builtins/ZBuiltins.cs +++ b/src/Zilf/Compiler/Builtins/ZBuiltins.cs @@ -37,12 +37,12 @@ using Zilf.ZModel.Values; namespace Zilf.Compiler.Builtins { [SuppressMessage("Style", "IDE0060", Justification = "ZBuiltins parameters are needed for validation, even if the values aren't used.")] + [SuppressMessage("Redundancy", "RCS1163:Unused parameter.", Justification = "ZBuiltins parameters are needed for validation, even if the values aren't used.")] + [SuppressMessage("Performance", "CA1801", Justification = "ZBuiltins parameters are needed for validation, even if the values aren't used.")] static class ZBuiltins { #region Infrastructure - [ItemNotNull] - [NotNull] static readonly ILookup builtins = (from mi in typeof(ZBuiltins).GetMethods(BindingFlags.Public | BindingFlags.Static) from a in mi.GetCustomAttributes() @@ -50,21 +50,17 @@ namespace Zilf.Compiler.Builtins select new { Name = name, Attr = a, Method = mi }) .ToLookup(r => r.Name, r => new BuiltinSpec(r.Attr, r.Method)); - [NotNull] - [ItemNotNull] public static IEnumerable GetBuiltinNames() { return builtins.Select(g => g.Key); } - [NotNull] - [ItemNotNull] - public static IEnumerable GetBuiltinSignatures([NotNull] string name) + public static IEnumerable GetBuiltinSignatures(string name) { return builtins[name].Select(ZBuiltinSignature.FromBuiltinSpec); } - public static bool IsBuiltinValueCall([NotNull] string name, int zversion, int argCount) + public static bool IsBuiltinValueCall(string name, int zversion, int argCount) { return builtins[name].Any(s => { @@ -73,7 +69,7 @@ namespace Zilf.Compiler.Builtins }); } - public static bool IsBuiltinVoidCall([NotNull] string name, int zversion, int argCount) + public static bool IsBuiltinVoidCall(string name, int zversion, int argCount) { return builtins[name].Any(s => { @@ -82,7 +78,7 @@ namespace Zilf.Compiler.Builtins }); } - public static bool IsBuiltinPredCall([NotNull] string name, int zversion, int argCount) + public static bool IsBuiltinPredCall(string name, int zversion, int argCount) { return builtins[name].Any(s => { @@ -91,7 +87,7 @@ namespace Zilf.Compiler.Builtins }); } - public static bool IsBuiltinValuePredCall([NotNull] string name, int zversion, int argCount) + public static bool IsBuiltinValuePredCall(string name, int zversion, int argCount) { return builtins[name].Any(s => { @@ -100,7 +96,7 @@ namespace Zilf.Compiler.Builtins }); } - public static bool IsBuiltinWithSideEffects([NotNull] string name, int zversion, int argCount) + public static bool IsBuiltinWithSideEffects(string name, int zversion, int argCount) { // true if there's a void, value, or predicate version with side effects return builtins[name].Any(s => @@ -111,7 +107,7 @@ namespace Zilf.Compiler.Builtins } [ContractAnnotation("=> true, error: notnull; => false, error: null")] - public static bool IsNearMatchBuiltin([NotNull] string name, int zversion, int argCount, [CanBeNull] out CompilerError error) + public static bool IsNearMatchBuiltin(string name, int zversion, int argCount, [NotNullWhen(true)] out CompilerError? error) { // is there a match with this zversion but any arg count? var wrongArgCount = @@ -158,14 +154,13 @@ namespace Zilf.Compiler.Builtins return false; } - delegate void InvalidArgumentDelegate(int index, [NotNull] string message); + delegate void InvalidArgumentDelegate(int index, string message); [SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)")] [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] - [NotNull] static IList ValidateArguments( - [NotNull] Compilation cc, [NotNull] BuiltinSpec spec, [ItemNotNull] [NotNull] ParameterInfo[] builtinParamInfos, - [ItemNotNull] [NotNull] IReadOnlyList args, [NotNull] [InstantHandle] InvalidArgumentDelegate error) + Compilation cc, BuiltinSpec spec, ParameterInfo[] builtinParamInfos, + IReadOnlyList args, [InstantHandle] InvalidArgumentDelegate error) { // args may be short (for optional params) @@ -209,15 +204,14 @@ namespace Zilf.Compiler.Builtins return result; } - [NotNull] - static List MakeBuiltinMethodParams( - [NotNull] BuiltinSpec spec, [ItemNotNull] [NotNull] ParameterInfo[] builtinParamInfos, - [NotNull] object call, [NotNull] IList args) + static List MakeBuiltinMethodParams( + BuiltinSpec spec, ParameterInfo[] builtinParamInfos, + object call, IList args) { /* args.Length (plus call and data) may differ from builtinParamInfos.Length, * due to optional arguments and params arrays. */ - var result = new List(builtinParamInfos.Length) { call }; + var result = new List(builtinParamInfos.Length) { call }; // data (optional) int i = 1; @@ -236,15 +230,15 @@ namespace Zilf.Compiler.Builtins { // add all remaining operands as a param array result.Add(j >= args.Count - ? new IOperand[0] - : args.Skip(j).Select(a => (IOperand)a.Value).ToArray()); + ? Array.Empty() + : args.Skip(j).Select(a => (IOperand?)a.Value).ToArray()); } else if (pi.ParameterType == typeof(ZilObject[])) { // add all remaining values as a param array result.Add(j >= args.Count - ? new ZilObject[0] - : args.Skip(j).Select(a => (ZilObject)a.Value).ToArray()); + ? Array.Empty() + : args.Skip(j).Select(a => (ZilObject?)a.Value).ToArray()); } else if (j >= args.Count) { @@ -259,9 +253,8 @@ namespace Zilf.Compiler.Builtins return result; } - [NotNull] - static object CompileBuiltinCall([NotNull] string name, [NotNull] Compilation cc, - [NotNull] IRoutineBuilder rb, [NotNull] ZilListoidBase form, TCall call) + static IOperand? CompileBuiltinCall(string name, Compilation cc, + IRoutineBuilder rb, ZilListoidBase form, TCall call) where TCall : struct { int zversion = cc.Context.ZEnvironment.ZVersion; @@ -312,56 +305,58 @@ namespace Zilf.Compiler.Builtins .Select((a, oidx) => new { a, oidx }) .Where(p => p.a.Type == BuiltinArgType.NeedsEval) .ToArray(); - var needEvalExprs = Array.ConvertAll(needEval, p => (ZilObject)p.a.Value); + var needEvalExprs = Array.ConvertAll(needEval, p => (ZilObject)p.a.Value!); // generate code for arguments Debug.Assert(form.SourceLine != null, "form.SourceLine != null"); - using (var operands = cc.CompileOperands(rb, form.SourceLine, needEvalExprs)) + using var operands = cc.CompileOperands(rb, form.SourceLine, needEvalExprs); + + // update validatedArgs with the evaluated operands + for (int i = 0; i < operands.Count; i++) { - // update validatedArgs with the evaluated operands - for (int i = 0; i < operands.Count; i++) - { - Debug.Assert(needEval[i] != null); - var oidx = needEval[i].oidx; - validatedArgs[oidx] = new BuiltinArg(BuiltinArgType.Operand, operands[i]); - } + Debug.Assert(needEval[i] != null); + var oidx = needEval[i].oidx; + validatedArgs[oidx] = new BuiltinArg(BuiltinArgType.Operand, operands[i]); + } - // call the spec method to generate code for the builtin - var builtinParams = MakeBuiltinMethodParams(spec, builtinParamInfos, call, validatedArgs); - try - { - var result = spec.Method.Invoke(null, builtinParams.ToArray()); - return result; - } - catch (TargetInvocationException ex) when (ex.InnerException is ZilErrorBase zex) - { - ExceptionDispatchInfo.Capture(zex).Throw(); - // ReSharper disable once HeuristicUnreachableCode - throw new UnreachableCodeException(); - } + // call the spec method to generate code for the builtin + var builtinParams = MakeBuiltinMethodParams(spec, builtinParamInfos, call, validatedArgs); + try + { + return spec.Method.Invoke(null, builtinParams.ToArray()) as IOperand; + } + catch (TargetInvocationException ex) when (ex.InnerException is ZilErrorBase zex) + { + ExceptionDispatchInfo.Capture(zex).Throw(); + // ReSharper disable once HeuristicUnreachableCode + throw new UnreachableCodeException(); } } - [NotNull] - public static IOperand CompileValueCall([NotNull] string name, [NotNull] Compilation cc, [NotNull] IRoutineBuilder rb, [NotNull] ZilForm form, - [CanBeNull] IVariable resultStorage) + public static IOperand CompileValueCall(string name, Compilation cc, IRoutineBuilder rb, ZilForm form, + IVariable? resultStorage) { - return (IOperand)CompileBuiltinCall(name, cc, rb, form, + var result = CompileBuiltinCall(name, + cc, + rb, + form, new ValueCall(cc, rb, form, resultStorage ?? rb.Stack)); + Debug.Assert(result != null); + return result; } - public static void CompileVoidCall([NotNull] string name, [NotNull] Compilation cc, [NotNull] IRoutineBuilder rb, [NotNull] ZilForm form) + public static void CompileVoidCall(string name, Compilation cc, IRoutineBuilder rb, ZilForm form) { CompileBuiltinCall(name, cc, rb, form, new VoidCall(cc, rb, form)); } - public static void CompilePredCall([NotNull] string name, [NotNull] Compilation cc, [NotNull] IRoutineBuilder rb, [NotNull] ZilForm form, [NotNull] ILabel label, bool polarity) + public static void CompilePredCall(string name, Compilation cc, IRoutineBuilder rb, ZilForm form, ILabel label, bool polarity) { CompileBuiltinCall(name, cc, rb, form, new PredCall(cc, rb, form, label, polarity)); } - public static void CompileValuePredCall([NotNull] string name, [NotNull] Compilation cc, [NotNull] IRoutineBuilder rb, [NotNull] ZilForm form, - [CanBeNull] IVariable resultStorage, [NotNull] ILabel label, bool polarity) + public static void CompileValuePredCall(string name, Compilation cc, IRoutineBuilder rb, ZilForm form, + IVariable? resultStorage, ILabel label, bool polarity) { CompileBuiltinCall(name, cc, rb, form, new ValuePredCall(cc, rb, form, resultStorage ?? rb.Stack, label, polarity)); @@ -376,8 +371,8 @@ namespace Zilf.Compiler.Builtins /// Local variables are not allowed here. [Builtin("EQUAL?", "=?", "==?")] public static void VarargsEqualityOp( - PredCall c, [NotNull] IOperand arg1, [NotNull] IOperand arg2, - [ItemNotNull] [NotNull] params IOperand[] restOfArgs) + PredCall c, IOperand arg1, IOperand arg2, + params IOperand[] restOfArgs) { if (arg1 is INumericOperand num1) { @@ -451,7 +446,7 @@ namespace Zilf.Compiler.Builtins } else { - ZilAtom tempAtom = null; + ZilAtom? tempAtom = null; if (arg1 == c.rb.Stack) { tempAtom = ZilAtom.Parse("?TMP", c.cc.Context); @@ -520,8 +515,8 @@ namespace Zilf.Compiler.Builtins /// Local variables are not allowed here. [Builtin("N=?", "N==?")] public static void NegatedVarargsEqualityOp( - PredCall c, [NotNull] IOperand arg1, [NotNull] IOperand arg2, - [NotNull] params IOperand[] restOfArgs) + PredCall c, IOperand arg1, IOperand arg2, + params IOperand[] restOfArgs) { var innerCall = new PredCall(c.cc, c.rb, c.form, c.label, !c.polarity); VarargsEqualityOp(innerCall, arg1, arg2, restOfArgs); @@ -539,7 +534,7 @@ namespace Zilf.Compiler.Builtins [Builtin("WINSIZE", Data = TernaryOp.WindowSize, MinVersion = 6, HasSideEffect = true)] public static void TernaryVoidOp( VoidCall c, [Data] TernaryOp op, - [NotNull] IOperand left, [NotNull] IOperand center, [NotNull] IOperand right) + IOperand left, IOperand center, IOperand right) { c.rb.EmitTernary(op, left, center, right, null); } @@ -548,7 +543,7 @@ namespace Zilf.Compiler.Builtins [Builtin("WINATTR", Data = TernaryOp.WindowStyle, MinVersion = 6, HasSideEffect = true)] public static void TernaryOptionalVoidOp( VoidCall c, [Data] TernaryOp op, - [NotNull] IOperand left, [NotNull] IOperand center, [CanBeNull] IOperand right = null) + IOperand left, IOperand center, IOperand? right = null) { c.rb.EmitTernary(op, left, center, right ?? c.cc.Game.Zero, null); } @@ -557,7 +552,7 @@ namespace Zilf.Compiler.Builtins [Builtin("PUTB", Data = TernaryOp.PutByte, HasSideEffect = true)] public static void TernaryTableVoidOp( VoidCall c, [Data] TernaryOp op, - [Table][NotNull] IOperand left, [NotNull] IOperand center, [NotNull] IOperand right) + [Table] IOperand left, IOperand center, IOperand right) { c.rb.EmitTernary(op, left, center, right, null); } @@ -565,7 +560,7 @@ namespace Zilf.Compiler.Builtins [Builtin("PUTP", Data = TernaryOp.PutProperty, HasSideEffect = true)] public static void TernaryObjectVoidOp( VoidCall c, [Data] TernaryOp op, - [Object][NotNull] IOperand left, [NotNull] IOperand center, [NotNull] IOperand right) + [Object] IOperand left, IOperand center, IOperand right) { c.rb.EmitTernary(op, left, center, right, null); } @@ -573,7 +568,7 @@ namespace Zilf.Compiler.Builtins [Builtin("COPYT", Data = TernaryOp.CopyTable, HasSideEffect = true, MinVersion = 5)] public static void TernaryTableTableVoidOp( VoidCall c, [Data] TernaryOp op, - [Table][NotNull] IOperand left, [Table][NotNull] IOperand center, [NotNull] IOperand right) + [Table] IOperand left, [Table] IOperand center, IOperand right) { c.rb.EmitTernary(op, left, center, right, null); } @@ -586,9 +581,8 @@ namespace Zilf.Compiler.Builtins [Builtin("ASH", "ASHIFT", Data = BinaryOp.ArtShift, MinVersion = 5)] [Builtin("LSH", "SHIFT", Data = BinaryOp.LogShift, MinVersion = 5)] [Builtin("WINGET", Data = BinaryOp.GetWindowProperty, MinVersion = 6)] - [NotNull] public static IOperand BinaryValueOp( - ValueCall c, [Data] BinaryOp op, [NotNull] IOperand left, [NotNull] IOperand right) + ValueCall c, [Data] BinaryOp op, IOperand left, IOperand right) { if (left is INumericOperand nleft && right is INumericOperand nright) { @@ -613,8 +607,7 @@ namespace Zilf.Compiler.Builtins /// The syntax is incorrect, or an error occurred while compiling a subexpression. [Builtin("XORB")] - [NotNull] - public static IOperand BinaryXorOp(ValueCall c, [NotNull] ZilObject left, [NotNull] ZilObject right) + public static IOperand BinaryXorOp(ValueCall c, ZilObject left, ZilObject right) { ZilObject value; if (left is ZilFix lf && lf.Value == -1) @@ -640,7 +633,6 @@ namespace Zilf.Compiler.Builtins return c.resultStorage; } - [NotNull] [Builtin("ADD", "+", Data = BinaryOp.Add)] [Builtin("SUB", "-", Data = BinaryOp.Sub)] [Builtin("MUL", "*", Data = BinaryOp.Mul)] @@ -648,7 +640,7 @@ namespace Zilf.Compiler.Builtins [Builtin("BAND", "ANDB", Data = BinaryOp.And)] [Builtin("BOR", "ORB", Data = BinaryOp.Or)] public static IOperand ArithmeticOp( - ValueCall c, [Data] BinaryOp op, [ItemNotNull] [NotNull] params IOperand[] args) + ValueCall c, [Data] BinaryOp op, params IOperand[] args) { GetArithmeticInfo(op, out var initialValue, out var operation, out var compileUnary); @@ -679,17 +671,19 @@ namespace Zilf.Compiler.Builtins { c.rb.EmitBinary(op, c.rb.Stack, args[i], c.rb.Stack); } - c.rb.EmitBinary(op, c.rb.Stack, args[args.Length - 1], c.resultStorage); + c.rb.EmitBinary(op, c.rb.Stack, args[^1], c.resultStorage); return c.resultStorage; } } static void GetArithmeticInfo(BinaryOp op, out short initialValue, - [NotNull] out Func operation, - [NotNull] out Func compileUnary) + out Func operation, + out Func compileUnary) { // a delegate implementing the actual arithmetic operation +#pragma warning disable IDE0066 // Convert switch statement to expression switch (op) +#pragma warning restore IDE0066 // Convert switch statement to expression { case BinaryOp.Add: operation = (a, b) => (short)(a + b); @@ -715,22 +709,17 @@ namespace Zilf.Compiler.Builtins // the initial value, which is returned as-is if there are no args, // or possibly combined with the single arg if there's only one - switch (op) + initialValue = (short)(op switch { - case BinaryOp.Mul: - case BinaryOp.Div: - initialValue = 1; - break; - case BinaryOp.And: - initialValue = -1; - break; - default: - initialValue = 0; - break; - } + BinaryOp.Mul => 1, + BinaryOp.Div => 1, + BinaryOp.And => -1, + _ => 0 + }); // another delegate describing how to combine the initial value // with the single arg in that case + // ReSharper disable once ConvertSwitchStatementToSwitchExpression switch (op) { case BinaryOp.Add: @@ -762,9 +751,8 @@ namespace Zilf.Compiler.Builtins } } - [CanBeNull] - static IOperand FoldConstantArithmetic([NotNull] Compilation cc, short init, [NotNull] Func op, - [ItemNotNull] [NotNull] IOperand[] args) + static IOperand? FoldConstantArithmetic(Compilation cc, short init, Func op, + IOperand[] args) { // make sure all args are constants foreach (var arg in args) @@ -782,7 +770,7 @@ namespace Zilf.Compiler.Builtins } [Builtin("BAND", "ANDB")] - public static void BinaryAndPredOp(PredCall c, [NotNull] IOperand left, [NotNull] IOperand right) + public static void BinaryAndPredOp(PredCall c, IOperand left, IOperand right) { var nleft = left as INumericOperand; var nright = right as INumericOperand; @@ -810,14 +798,14 @@ namespace Zilf.Compiler.Builtins } else { - constant = nright; + constant = nright!; variable = left; } if (constant.Value == 0) { // always false - if (c.polarity == false) + if (!c.polarity) c.rb.Branch(c.label); return; @@ -836,8 +824,7 @@ namespace Zilf.Compiler.Builtins } [Builtin("REST", "ZREST")] - [NotNull] - public static IOperand RestOp(ValueCall c, [NotNull] IOperand left, [CanBeNull] IOperand right = null) + public static IOperand RestOp(ValueCall c, IOperand left, IOperand? right = null) { // if left and right are constants, we can add them at assembly time if (left is IConstantOperand lconst) @@ -856,8 +843,7 @@ namespace Zilf.Compiler.Builtins } [Builtin("BACK", "ZBACK")] - [NotNull] - public static IOperand BackOp(ValueCall c, [NotNull] IOperand left, [CanBeNull] IOperand right = null) + public static IOperand BackOp(ValueCall c, IOperand left, IOperand? right = null) { return ArithmeticOp(c, BinaryOp.Sub, left, right ?? c.cc.Game.One); } @@ -868,14 +854,14 @@ namespace Zilf.Compiler.Builtins [Builtin("THROW", Data = BinaryOp.Throw, MinVersion = 5, HasSideEffect = true)] [Builtin("SCROLL", Data = BinaryOp.ScrollWindow, MinVersion = 6, HasSideEffect = true)] public static void BinaryVoidOp( - VoidCall c, [Data] BinaryOp op, [NotNull] IOperand left, [NotNull] IOperand right) + VoidCall c, [Data] BinaryOp op, IOperand left, IOperand right) { c.rb.EmitBinary(op, left, right, null); } [Builtin("CURSET", MinVersion = 6, HasSideEffect = true)] - public static void CursetVoidOp(VoidCall c, [NotNull] IOperand line, [CanBeNull] IOperand column = null, - [CanBeNull] IOperand window = null) + public static void CursetVoidOp(VoidCall c, IOperand line, IOperand? column = null, + IOperand? window = null) { if (window != null) { @@ -892,25 +878,17 @@ namespace Zilf.Compiler.Builtins [Builtin("LESS?", "L?", Data = Condition.Less)] [Builtin("BTST", Data = Condition.TestBits)] public static void BinaryPredOp( - PredCall c, [Data] Condition cond, [NotNull] IOperand left, [NotNull] IOperand right) + PredCall c, [Data] Condition cond, IOperand left, IOperand right) { if (left is INumericOperand nleft && right is INumericOperand nright) { - bool branch; - switch (cond) + var branch = cond switch { - case Condition.Greater: - branch = nleft.Value > nright.Value; - break; - case Condition.Less: - branch = nleft.Value < nright.Value; - break; - case Condition.TestBits: - branch = (nleft.Value & nright.Value) == nright.Value; - break; - default: - throw UnhandledCaseException.FromEnum(cond); - } + Condition.Greater => (nleft.Value > nright.Value), + Condition.Less => (nleft.Value < nright.Value), + Condition.TestBits => ((nleft.Value & nright.Value) == nright.Value), + _ => throw UnhandledCaseException.FromEnum(cond) + }; if (branch == c.polarity) c.rb.Branch(c.label); @@ -923,7 +901,7 @@ namespace Zilf.Compiler.Builtins [Builtin("MENU", MinVersion = 6, HasSideEffect = true)] public static void BinaryMenuOp( - PredCall c, [NotNull] IOperand menuId, [Table][NotNull] IOperand table) + PredCall c, IOperand menuId, [Table] IOperand table) { c.rb.Branch(Condition.MakeMenu, menuId, table, c.label, c.polarity); } @@ -931,7 +909,7 @@ namespace Zilf.Compiler.Builtins [Builtin("L=?", Data = Condition.Greater)] [Builtin("G=?", Data = Condition.Less)] public static void NegatedBinaryPredOp( - PredCall c, [Data] Condition cond, [NotNull] IOperand left, [NotNull] IOperand right) + PredCall c, [Data] Condition cond, IOperand left, IOperand right) { BinaryPredOp(new PredCall(c.cc, c.rb, c.form, c.label, !c.polarity), cond, left, right); } @@ -939,14 +917,14 @@ namespace Zilf.Compiler.Builtins [Builtin("DLESS?", Data = Condition.DecCheck, HasSideEffect = true)] [Builtin("IGRTR?", Data = Condition.IncCheck, HasSideEffect = true)] public static void BinaryVariablePredOp( - PredCall c, [Data] Condition cond, [Variable(QuirksMode = QuirksMode.Both)][NotNull] IVariable left, [NotNull] IOperand right) + PredCall c, [Data] Condition cond, [Variable(VariableScopeQuirks = VariableScopeQuirks.Both)] IVariable left, IOperand right) { c.cc.MarkVariableAsReadAndWritten(left); c.rb.Branch(cond, left, right, c.label, c.polarity); } [Builtin("PICINF", MinVersion = 6, HasSideEffect = true)] - public static void PicinfPredOp(PredCall c, [NotNull] IOperand left, [Table][NotNull] IOperand right) + public static void PicinfPredOp(PredCall c, IOperand left, [Table] IOperand right) { c.rb.Branch(Condition.PictureData, left, right, c.label, c.polarity); } @@ -954,7 +932,7 @@ namespace Zilf.Compiler.Builtins [Builtin("DLESS?", Data = Condition.Less, HasSideEffect = true)] [Builtin("IGRTR?", Data = Condition.Greater, HasSideEffect = true)] public static void BinaryVariablePredOp( - PredCall c, [Data] Condition cond, [Variable][NotNull] SoftGlobal left, [NotNull] IOperand right) + PredCall c, [Data] Condition cond, [Variable] SoftGlobal left, IOperand right) { Debug.Assert(c.cc.SoftGlobalsTable != null, "c.cc.SoftGlobalsTable != null"); @@ -988,9 +966,8 @@ namespace Zilf.Compiler.Builtins [Builtin("GETP", Data = BinaryOp.GetProperty)] [Builtin("NEXTP", Data = BinaryOp.GetNextProp)] - [NotNull] public static IOperand BinaryObjectValueOp( - ValueCall c, [Data] BinaryOp op, [Object][NotNull] IOperand left, [NotNull] IOperand right) + ValueCall c, [Data] BinaryOp op, [Object] IOperand left, IOperand right) { c.rb.EmitBinary(op, left, right, c.resultStorage); return c.resultStorage; @@ -999,37 +976,36 @@ namespace Zilf.Compiler.Builtins [Builtin("FSET", Data = BinaryOp.SetFlag, HasSideEffect = true)] [Builtin("FCLEAR", Data = BinaryOp.ClearFlag, HasSideEffect = true)] public static void BinaryObjectVoidOp( - VoidCall c, [Data] BinaryOp op, [Object][NotNull] IOperand left, [NotNull] IOperand right) + VoidCall c, [Data] BinaryOp op, [Object] IOperand left, IOperand right) { c.rb.EmitBinary(op, left, right, null); } [Builtin("FSET?", Data = Condition.TestAttr)] public static void BinaryObjectPredOp( - PredCall c, [Data] Condition cond, [Object][NotNull] IOperand left, [NotNull] IOperand right) + PredCall c, [Data] Condition cond, [Object] IOperand left, IOperand right) { c.rb.Branch(cond, left, right, c.label, c.polarity); } [Builtin("IN?", Data = Condition.Inside)] public static void BinaryObjectObjectPredOp( - PredCall c, [Data] Condition cond, [Object][NotNull] IOperand left, [Object][NotNull] IOperand right) + PredCall c, [Data] Condition cond, [Object] IOperand left, [Object] IOperand right) { c.rb.Branch(cond, left, right, c.label, c.polarity); } [Builtin("MOVE", Data = BinaryOp.MoveObject, HasSideEffect = true)] public static void BinaryObjectObjectVoidOp( - VoidCall c, [Data] BinaryOp op, [Object][NotNull] IOperand left, [Object][NotNull] IOperand right) + VoidCall c, [Data] BinaryOp op, [Object] IOperand left, [Object] IOperand right) { c.rb.EmitBinary(op, left, right, null); } [Builtin("GETPT", Data = BinaryOp.GetPropAddress)] [return: Table] - [NotNull] public static IOperand BinaryObjectToTableValueOp( - ValueCall c, [Data] BinaryOp op, [Object][NotNull] IOperand left, [NotNull] IOperand right) + ValueCall c, [Data] BinaryOp op, [Object] IOperand left, IOperand right) { c.rb.EmitBinary(op, left, right, c.resultStorage); return c.resultStorage; @@ -1037,9 +1013,8 @@ namespace Zilf.Compiler.Builtins [Builtin("GET", "NTH", "ZGET", Data = BinaryOp.GetWord)] [Builtin("GETB", Data = BinaryOp.GetByte)] - [NotNull] public static IOperand BinaryTableValueOp( - ValueCall c, [Data] BinaryOp op, [Table][NotNull] IOperand left, [NotNull] IOperand right) + ValueCall c, [Data] BinaryOp op, [Table] IOperand left, IOperand right) { c.rb.EmitBinary(op, left, right, c.resultStorage); return c.resultStorage; @@ -1053,9 +1028,8 @@ namespace Zilf.Compiler.Builtins [Builtin("RANDOM", "ZRANDOM", Data = UnaryOp.Random, HasSideEffect = true)] [Builtin("FONT", Data = UnaryOp.SetFont, MinVersion = 5, HasSideEffect = true)] [Builtin("CHECKU", Data = UnaryOp.CheckUnicode, MinVersion = 5)] - [NotNull] public static IOperand UnaryValueOp( - ValueCall c, [Data] UnaryOp op, [NotNull] IOperand value) + ValueCall c, [Data] UnaryOp op, IOperand value) { if (op == UnaryOp.Not && value is INumericOperand num) { @@ -1076,13 +1050,13 @@ namespace Zilf.Compiler.Builtins [Builtin("ERASE", Data = UnaryOp.EraseLine, MinVersion = 4, HasSideEffect = true)] [Builtin("MOUSE-LIMIT", Data = UnaryOp.MouseWindow, MinVersion = 6, HasSideEffect = true)] public static void UnaryVoidOp( - VoidCall c, [Data] UnaryOp op, [NotNull] IOperand value) + VoidCall c, [Data] UnaryOp op, IOperand value) { c.rb.EmitUnary(op, value, null); } [Builtin("ZERO?", "0?")] - public static void ZeroPredOp(PredCall c, [NotNull] IOperand value) + public static void ZeroPredOp(PredCall c, IOperand value) { if (value is INumericOperand num) { @@ -1096,7 +1070,7 @@ namespace Zilf.Compiler.Builtins } [Builtin("1?")] - public static void OnePredOp(PredCall c, [NotNull] IOperand value) + public static void OnePredOp(PredCall c, IOperand value) { if (value is INumericOperand num) { @@ -1110,9 +1084,8 @@ namespace Zilf.Compiler.Builtins } [Builtin("LOC", Data = UnaryOp.GetParent)] - [NotNull] public static IOperand UnaryObjectValueOp( - ValueCall c, [Data] UnaryOp op, [Object][NotNull] IOperand obj) + ValueCall c, [Data] UnaryOp op, [Object] IOperand obj) { c.rb.EmitUnary(op, obj, c.resultStorage); return c.resultStorage; @@ -1121,7 +1094,7 @@ namespace Zilf.Compiler.Builtins [Builtin("FIRST?", Data = false)] [Builtin("NEXT?", Data = true)] public static void UnaryObjectValuePredOp( - ValuePredCall c, [Data] bool sibling, [Object][NotNull] IOperand obj) + ValuePredCall c, [Data] bool sibling, [Object] IOperand obj) { if (sibling) c.rb.EmitGetSibling(obj, c.resultStorage, c.label, c.polarity); @@ -1130,9 +1103,8 @@ namespace Zilf.Compiler.Builtins } [Builtin("PTSIZE", Data = UnaryOp.GetPropSize)] - [NotNull] public static IOperand UnaryTableValueOp( - ValueCall c, [Data] UnaryOp op, [Table][NotNull] IOperand value) + ValueCall c, [Data] UnaryOp op, [Table] IOperand value) { c.rb.EmitUnary(op, value, c.resultStorage); return c.resultStorage; @@ -1140,14 +1112,14 @@ namespace Zilf.Compiler.Builtins [Builtin("REMOVE", "ZREMOVE", Data = UnaryOp.RemoveObject, HasSideEffect = true)] public static void UnaryObjectVoidOp( - VoidCall c, [Data] UnaryOp op, [Object][NotNull] IOperand value) + VoidCall c, [Data] UnaryOp op, [Object] IOperand value) { c.rb.EmitUnary(op, value, null); } [Builtin("ASSIGNED?", Data = Condition.ArgProvided, MinVersion = 5)] public static void UnaryVariablePredOp( - PredCall c, [Data] Condition cond, [Variable][NotNull] IVariable var) + PredCall c, [Data] Condition cond, [Variable] IVariable var) { c.cc.MarkVariableAsRead(var); c.rb.Branch(cond, var, null, c.label, c.polarity); @@ -1155,7 +1127,7 @@ namespace Zilf.Compiler.Builtins [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "var")] [Builtin("ASSIGNED?", MinVersion = 5)] - public static void SoftGlobalAssignedOp(PredCall c, [Variable][NotNull] SoftGlobal var) + public static void SoftGlobalAssignedOp(PredCall c, [Variable] SoftGlobal var) { // globals are never "assigned" in this sense if (!c.polarity) @@ -1167,7 +1139,7 @@ namespace Zilf.Compiler.Builtins [Builtin("MOUSE-INFO", Data = UnaryOp.ReadMouse, MinVersion = 6, HasSideEffect = true)] [Builtin("PRINTF", Data = UnaryOp.PrintForm, MinVersion = 6, HasSideEffect = true)] public static void UnaryTableVoidOp( - VoidCall c, [Data] UnaryOp op, [Table][NotNull] IOperand value) + VoidCall c, [Data] UnaryOp op, [Table] IOperand value) { c.rb.EmitUnary(op, value, null); } @@ -1183,15 +1155,15 @@ namespace Zilf.Compiler.Builtins [Builtin("PRINTN", Data = PrintOp.Number, HasSideEffect = true)] [Builtin("PRINTU", Data = PrintOp.Unicode, HasSideEffect = true)] public static void UnaryPrintVoidOp( - VoidCall c, [Data] PrintOp op, [NotNull] IOperand value) + VoidCall c, [Data] PrintOp op, IOperand value) { c.rb.EmitPrint(op, value); } [Builtin("PRINTT", HasSideEffect = true)] public static void PrintTableOp( - VoidCall c, [Table] [NotNull] IOperand table, [NotNull] IOperand width, - [CanBeNull] IOperand height = null, [CanBeNull] IOperand skip = null) + VoidCall c, [Table] IOperand table, IOperand width, + IOperand? height = null, IOperand? skip = null) { c.rb.EmitPrintTable(table, width, height, skip); } @@ -1199,7 +1171,7 @@ namespace Zilf.Compiler.Builtins [Builtin("PRINTI", Data = false, HasSideEffect = true)] [Builtin("PRINTR", Data = true, HasSideEffect = true)] public static void UnaryPrintStringOp( - VoidCall c, [Data] bool crlfRtrue, [NotNull] string text) + VoidCall c, [Data] bool crlfRtrue, string text) { c.rb.EmitPrint(text, crlfRtrue); } @@ -1216,9 +1188,8 @@ namespace Zilf.Compiler.Builtins /// The syntax is incorrect, or an error occurred while compiling a subexpression. [Builtin("SET", HasSideEffect = true)] - [NotNull] public static IOperand SetValueOp( - ValueCall c, [Variable(QuirksMode = QuirksMode.Local)] [NotNull] IVariable dest, [NotNull] ZilObject value) + ValueCall c, [Variable(VariableScopeQuirks = VariableScopeQuirks.Local)] IVariable dest, ZilObject value) { // in value context, we need to be able to return the newly set value, // so dest is IVariable. this means value> isn't @@ -1243,9 +1214,8 @@ namespace Zilf.Compiler.Builtins /// The syntax is incorrect, or an error occurred while compiling a subexpression. [Builtin("SET", HasSideEffect = true)] - [NotNull] public static IOperand SetValueOp( - ValueCall c, [Variable(QuirksMode = QuirksMode.Local)] [NotNull] SoftGlobal dest, [NotNull] ZilObject value) + ValueCall c, [Variable(VariableScopeQuirks = VariableScopeQuirks.Local)] SoftGlobal dest, ZilObject value) { var storage = c.cc.CompileAsOperand(c.rb, value, c.form.SourceLine, c.rb.Stack); @@ -1269,18 +1239,16 @@ namespace Zilf.Compiler.Builtins /// The syntax is incorrect, or an error occurred while compiling a subexpression. [Builtin("SETG", HasSideEffect = true)] - [NotNull] public static IOperand SetgValueOp( - ValueCall c, [Variable(QuirksMode = QuirksMode.Global)][NotNull] IVariable dest, [NotNull] ZilObject value) + ValueCall c, [Variable(VariableScopeQuirks = VariableScopeQuirks.Global)] IVariable dest, ZilObject value) { return SetValueOp(c, dest, value); } /// The syntax is incorrect, or an error occurred while compiling a subexpression. [Builtin("SETG", HasSideEffect = true)] - [NotNull] public static IOperand SetgValueOp( - ValueCall c, [Variable(QuirksMode = QuirksMode.Global)][NotNull] SoftGlobal dest, [NotNull] ZilObject value) + ValueCall c, [Variable(VariableScopeQuirks = VariableScopeQuirks.Global)] SoftGlobal dest, ZilObject value) { return SetValueOp(c, dest, value); } @@ -1288,7 +1256,7 @@ namespace Zilf.Compiler.Builtins /// Local variables are not allowed here. [Builtin("SET")] public static void SetVoidOp( - VoidCall c, [Variable(QuirksMode = QuirksMode.Local)][NotNull] IOperand dest, [NotNull] ZilObject value) + VoidCall c, [Variable(VariableScopeQuirks = VariableScopeQuirks.Local)] IOperand dest, ZilObject value) { // in void context, we don't need to return the newly set value, so we // can support value>. @@ -1303,35 +1271,34 @@ namespace Zilf.Compiler.Builtins } else { - using (var operands = c.cc.CompileOperands(c.rb, c.form.SourceLine, value)) + using var operands = c.cc.CompileOperands(c.rb, c.form.SourceLine, value); + + if (dest == c.rb.Stack && operands[0] == c.rb.Stack) { - if (dest == c.rb.Stack && operands[0] == c.rb.Stack) + var tempAtom = ZilAtom.Parse("?TMP", c.cc.Context); + c.cc.PushInnerLocal(c.rb, tempAtom, LocalBindingType.CompilerTemporary, c.form.SourceLine); + try { - var tempAtom = ZilAtom.Parse("?TMP", c.cc.Context); - c.cc.PushInnerLocal(c.rb, tempAtom, LocalBindingType.CompilerTemporary, c.form.SourceLine); - try - { - var tempLocal = c.cc.Locals[tempAtom].LocalBuilder; - c.rb.EmitStore(tempLocal, operands[0]); - c.rb.EmitBinary(BinaryOp.StoreIndirect, dest, tempLocal, null); - } - finally - { - c.cc.PopInnerLocal(tempAtom); - } + var tempLocal = c.cc.Locals[tempAtom].LocalBuilder; + c.rb.EmitStore(tempLocal, operands[0]); + c.rb.EmitBinary(BinaryOp.StoreIndirect, dest, tempLocal, null); } - else + finally { - c.rb.EmitBinary(BinaryOp.StoreIndirect, dest, operands[0], null); + c.cc.PopInnerLocal(tempAtom); } } + else + { + c.rb.EmitBinary(BinaryOp.StoreIndirect, dest, operands[0], null); + } } } /// The syntax is incorrect, or an error occurred while compiling a subexpression. [Builtin("SET")] public static void SetVoidOp( - VoidCall c, [Variable(QuirksMode = QuirksMode.Local)][NotNull] SoftGlobal dest, [NotNull] ZilObject value) + VoidCall c, [Variable(VariableScopeQuirks = VariableScopeQuirks.Local)] SoftGlobal dest, ZilObject value) { Debug.Assert(c.cc.SoftGlobalsTable != null); c.rb.EmitTernary( @@ -1345,7 +1312,7 @@ namespace Zilf.Compiler.Builtins /// Local variables are not allowed here. [Builtin("SETG")] public static void SetgVoidOp( - VoidCall c, [Variable(QuirksMode = QuirksMode.Global)][NotNull] IOperand dest, [NotNull] ZilObject value) + VoidCall c, [Variable(VariableScopeQuirks = VariableScopeQuirks.Global)] IOperand dest, ZilObject value) { SetVoidOp(c, dest, value); } @@ -1353,7 +1320,7 @@ namespace Zilf.Compiler.Builtins /// The syntax is incorrect, or an error occurred while compiling a subexpression. [Builtin("SETG")] public static void SetgVoidOp( - VoidCall c, [Variable(QuirksMode = QuirksMode.Global)][NotNull] SoftGlobal dest, [NotNull] ZilObject value) + VoidCall c, [Variable(VariableScopeQuirks = VariableScopeQuirks.Global)] SoftGlobal dest, ZilObject value) { SetVoidOp(c, dest, value); } @@ -1361,7 +1328,7 @@ namespace Zilf.Compiler.Builtins /// The syntax is incorrect, or an error occurred while compiling a subexpression. [Builtin("SET", HasSideEffect = true)] public static void SetPredOp( - PredCall c, [Variable(QuirksMode = QuirksMode.Local)][NotNull] IVariable dest, [NotNull] ZilObject value) + PredCall c, [Variable(VariableScopeQuirks = VariableScopeQuirks.Local)] IVariable dest, ZilObject value) { // see note in SetValueOp regarding dest being IVariable c.cc.MarkVariableAsWritten(dest); @@ -1371,16 +1338,15 @@ namespace Zilf.Compiler.Builtins /// The syntax is incorrect, or an error occurred while compiling a subexpression. [Builtin("SETG", HasSideEffect = true)] public static void SetgPredOp( - PredCall c, [Variable(QuirksMode = QuirksMode.Global)][NotNull] IVariable dest, [NotNull] ZilObject value) + PredCall c, [Variable(VariableScopeQuirks = VariableScopeQuirks.Global)] IVariable dest, ZilObject value) { SetPredOp(c, dest, value); } [Builtin("INC", Data = BinaryOp.Add, HasSideEffect = true)] [Builtin("DEC", Data = BinaryOp.Sub, HasSideEffect = true)] - [NotNull] public static IOperand IncValueOp(ValueCall c, [Data] BinaryOp op, - [Variable(QuirksMode = QuirksMode.Both)][NotNull] IVariable victim) + [Variable(VariableScopeQuirks = VariableScopeQuirks.Both)] IVariable victim) { c.cc.MarkVariableAsReadAndWritten(victim); c.rb.EmitBinary(op, victim, c.cc.Game.One, victim); @@ -1389,9 +1355,8 @@ namespace Zilf.Compiler.Builtins [Builtin("INC", Data = BinaryOp.Add, HasSideEffect = true)] [Builtin("DEC", Data = BinaryOp.Sub, HasSideEffect = true)] - [NotNull] public static IOperand IncValueOp(ValueCall c, [Data] BinaryOp op, - [Variable(QuirksMode = QuirksMode.Both)][NotNull] SoftGlobal victim) + [Variable(VariableScopeQuirks = VariableScopeQuirks.Both)] SoftGlobal victim) { var offset = c.cc.Game.MakeOperand(victim.Offset); @@ -1416,7 +1381,7 @@ namespace Zilf.Compiler.Builtins [Builtin("INC", Data = BinaryOp.Add, HasSideEffect = true)] [Builtin("DEC", Data = BinaryOp.Sub, HasSideEffect = true)] public static void IncVoidOp(VoidCall c, [Data] BinaryOp op, - [Variable(QuirksMode = QuirksMode.Both)][NotNull] IVariable victim) + [Variable(VariableScopeQuirks = VariableScopeQuirks.Both)] IVariable victim) { c.cc.MarkVariableAsReadAndWritten(victim); c.rb.EmitBinary(op, victim, c.cc.Game.One, victim); @@ -1425,7 +1390,7 @@ namespace Zilf.Compiler.Builtins [Builtin("INC", Data = BinaryOp.Add, HasSideEffect = true)] [Builtin("DEC", Data = BinaryOp.Sub, HasSideEffect = true)] public static void IncVoidOp(VoidCall c, [Data] BinaryOp op, - [Variable(QuirksMode = QuirksMode.Both)][NotNull] SoftGlobal victim) + [Variable(VariableScopeQuirks = VariableScopeQuirks.Both)] SoftGlobal victim) { var offset = c.cc.Game.MakeOperand(victim.Offset); @@ -1446,20 +1411,19 @@ namespace Zilf.Compiler.Builtins } [Builtin("PUSH", HasSideEffect = true)] - public static void PushVoidOp(VoidCall c, [NotNull] IOperand value) + public static void PushVoidOp(VoidCall c, IOperand value) { c.rb.EmitStore(c.rb.Stack, value); } [Builtin("XPUSH", MinVersion = 6, HasSideEffect = true)] - public static void XpushPredOp(PredCall c, [NotNull] IOperand value, [NotNull] IOperand stack) + public static void XpushPredOp(PredCall c, IOperand value, IOperand stack) { c.rb.EmitPushUserStack(value, stack, c.label, c.polarity); } - [NotNull] [Builtin("POP", MinVersion = 6, HasSideEffect = true)] - public static IOperand PopValueOp(ValueCall c, [CanBeNull] IOperand stack = null) + public static IOperand PopValueOp(ValueCall c, IOperand? stack = null) { if (stack == null) c.rb.EmitStore(c.resultStorage, c.rb.Stack); @@ -1470,7 +1434,7 @@ namespace Zilf.Compiler.Builtins } [Builtin("FSTACK", MinVersion = 6, HasSideEffect = true)] - public static void FstackVoidOp(VoidCall c, [NotNull] IOperand count, [CanBeNull] IOperand stack = null) + public static void FstackVoidOp(VoidCall c, IOperand count, IOperand? stack = null) { if (stack == null) c.rb.EmitUnary(UnaryOp.FlushStack, count, null); @@ -1492,16 +1456,14 @@ namespace Zilf.Compiler.Builtins } [Builtin("VALUE", Priority = 2)] - [NotNull] - public static IOperand ValueOp_Operand(ValueCall c, [Variable][NotNull] IOperand value) + public static IOperand ValueOp_Operand(ValueCall c, [Variable] IOperand value) { c.rb.EmitUnary(UnaryOp.LoadIndirect, value, c.resultStorage); return c.resultStorage; } - [NotNull] [Builtin("GVAL")] - public static IOperand GvalOp(ValueCall c, [NotNull] ZilAtom atom) + public static IOperand GvalOp(ValueCall c, ZilAtom atom) { // constant, global, object, or routine if (c.cc.Constants.TryGetValue(atom, out var operand)) @@ -1535,7 +1497,7 @@ namespace Zilf.Compiler.Builtins "global", atom, "local")); - c.cc.MarkVariableAsRead(lbr); + Compilation.MarkVariableAsRead(lbr); return lbr.LocalBuilder; } @@ -1548,14 +1510,13 @@ namespace Zilf.Compiler.Builtins return c.cc.Game.Zero; } - [NotNull] [Builtin("LVAL")] - public static IOperand LvalOp(ValueCall c, [NotNull] ZilAtom atom) + public static IOperand LvalOp(ValueCall c, ZilAtom atom) { // local if (c.cc.Locals.TryGetValue(atom, out var lbr)) { - c.cc.MarkVariableAsRead(lbr); + Compilation.MarkVariableAsRead(lbr); return lbr.LocalBuilder; } @@ -1620,7 +1581,6 @@ namespace Zilf.Compiler.Builtins [Builtin("CATCH", Data = NullaryOp.Catch, MinVersion = 5)] [Builtin("ISAVE", Data = NullaryOp.SaveUndo, HasSideEffect = true, MinVersion = 5)] [Builtin("IRESTORE", Data = NullaryOp.RestoreUndo, HasSideEffect = true, MinVersion = 5)] - [NotNull] public static IOperand NullaryValueOp(ValueCall c, [Data] NullaryOp op) { c.rb.EmitNullary(op, c.resultStorage); @@ -1672,34 +1632,32 @@ namespace Zilf.Compiler.Builtins #region Input Opcodes [Builtin("READ", "ZREAD", MaxVersion = 3, HasSideEffect = true)] - public static void ReadOp_V3(VoidCall c, [NotNull] IOperand text, IOperand parse) + public static void ReadOp_V3(VoidCall c, IOperand text, IOperand parse) { c.rb.EmitRead(text, parse, null, null, null); } [Builtin("READ", "ZREAD", MinVersion = 4, MaxVersion = 4, HasSideEffect = true)] - public static void ReadOp_V4(VoidCall c, [NotNull] IOperand text, [NotNull] IOperand parse, - [CanBeNull] IOperand time = null, [CanBeNull] [Routine] IOperand routine = null) + public static void ReadOp_V4(VoidCall c, IOperand text, IOperand parse, + IOperand? time = null, [Routine] IOperand? routine = null) { c.rb.EmitRead(text, parse, time, routine, null); } [Builtin("READ", "ZREAD", MinVersion = 5, HasSideEffect = true)] - [NotNull] - public static IOperand ReadOp_V5(ValueCall c, [NotNull] IOperand text, - [CanBeNull] IOperand parse = null, [CanBeNull] IOperand time = null, - [CanBeNull] [Routine] IOperand routine = null) + public static IOperand ReadOp_V5(ValueCall c, IOperand text, + IOperand? parse = null, IOperand? time = null, + [Routine] IOperand? routine = null) { c.rb.EmitRead(text, parse, time, routine, c.resultStorage); return c.resultStorage; } - [NotNull] [Builtin("INPUT", MinVersion = 4, HasSideEffect = true)] - public static IOperand InputOp(ValueCall c, [NotNull] IOperand dummy, - [CanBeNull] IOperand interval = null, [CanBeNull] [Routine] IOperand routine = null) + public static IOperand InputOp(ValueCall c, IOperand dummy, + IOperand? interval = null, [Routine] IOperand? routine = null) { - if (c.form.StartsWith(out ZilObject _, out ZilFix fix) && fix.Value != 1) + if (c.form.StartsWith(out ZilObject _, out ZilFix? fix) && fix.Value != 1) { return c.HandleMessage( CompilerMessages._0_Argument_1_2, @@ -1721,16 +1679,16 @@ namespace Zilf.Compiler.Builtins #region Sound Opcodes [Builtin("SOUND", MaxVersion = 4, HasSideEffect = true)] - public static void SoundOp_V3(VoidCall c, [NotNull] IOperand number, - [CanBeNull] IOperand effect = null, [CanBeNull] IOperand volume = null) + public static void SoundOp_V3(VoidCall c, IOperand number, + IOperand? effect = null, IOperand? volume = null) { c.rb.EmitPlaySound(number, effect, volume, null); } [Builtin("SOUND", MinVersion = 5, HasSideEffect = true)] - public static void SoundOp_V5(VoidCall c, [NotNull] IOperand number, - [CanBeNull] IOperand effect = null, [CanBeNull] IOperand volume = null, - [CanBeNull] [Routine] IOperand routine = null) + public static void SoundOp_V5(VoidCall c, IOperand number, + IOperand? effect = null, IOperand? volume = null, + [Routine] IOperand? routine = null) { c.rb.EmitPlaySound(number, effect, volume, routine); } @@ -1741,16 +1699,16 @@ namespace Zilf.Compiler.Builtins [Builtin("ZWSTR", MinVersion = 5, HasSideEffect = true)] public static void EncodeTextOp(VoidCall c, - [Table][NotNull] IOperand src, [NotNull] IOperand length, - [NotNull] IOperand srcOffset, [Table][NotNull] IOperand dest) + [Table] IOperand src, IOperand length, + IOperand srcOffset, [Table] IOperand dest) { c.rb.EmitEncodeText(src, length, srcOffset, dest); } [Builtin("LEX", MinVersion = 5, HasSideEffect = true)] public static void LexOp(VoidCall c, - [Table][NotNull] IOperand text, [Table][NotNull] IOperand parse, - [CanBeNull] [Table] IOperand dictionary = null, [CanBeNull] IOperand flag = null) + [Table] IOperand text, [Table] IOperand parse, + [Table] IOperand? dictionary = null, IOperand? flag = null) { c.rb.EmitTokenize(text, parse, dictionary, flag); } @@ -1774,7 +1732,6 @@ namespace Zilf.Compiler.Builtins } /// Wrong Z-machine version for this form of the opcode. - [NotNull] [Builtin("RESTORE", "ZRESTORE", MinVersion = 4, HasSideEffect = true)] public static IOperand RestoreOp_V4(ValueCall c) { @@ -1788,9 +1745,8 @@ namespace Zilf.Compiler.Builtins /// Wrong Z-machine version for this form of the opcode. [Builtin("RESTORE", "ZRESTORE", MinVersion = 5, HasSideEffect = true)] - [NotNull] - public static IOperand RestoreOp_V5(ValueCall c, [Table][NotNull] IOperand table, - [NotNull] IOperand bytes, [Table][NotNull] IOperand name) + public static IOperand RestoreOp_V5(ValueCall c, [Table] IOperand table, + IOperand bytes, [Table] IOperand name) { if (c.rb.HasExtendedSave) { @@ -1815,7 +1771,6 @@ namespace Zilf.Compiler.Builtins } /// Wrong Z-machine version for this form of the opcode. - [NotNull] [Builtin("SAVE", "ZSAVE", MinVersion = 4, HasSideEffect = true)] public static IOperand SaveOp_V4(ValueCall c) { @@ -1829,9 +1784,8 @@ namespace Zilf.Compiler.Builtins /// Wrong Z-machine version for this form of the opcode. [Builtin("SAVE", "ZSAVE", MinVersion = 5, HasSideEffect = true)] - [NotNull] - public static IOperand SaveOp_V5(ValueCall c, [Table][NotNull] IOperand table, - [NotNull] IOperand bytes, [Table][NotNull] IOperand name) + public static IOperand SaveOp_V5(ValueCall c, [Table] IOperand table, + IOperand bytes, [Table] IOperand name) { if (c.rb.HasExtendedSave) { @@ -1847,7 +1801,7 @@ namespace Zilf.Compiler.Builtins /// The syntax is incorrect, or an error occurred while compiling a subexpression. [Builtin("RETURN", HasSideEffect = true)] - public static void ReturnOp(VoidCall c, [CanBeNull] ZilObject expr = null, Block block = null) + public static void ReturnOp(VoidCall c, ZilObject? expr = null, Block? block = null) { var origBlock = block; @@ -1859,22 +1813,13 @@ namespace Zilf.Compiler.Builtins IOperand value; var quirkMode = c.cc.Context.ReturnQuirkMode; - bool preferRoutine; - switch (quirkMode) - { - case ReturnQuirkMode.ByVersion: - preferRoutine = c.cc.Context.ZEnvironment.ZVersion >= 5; - break; - case ReturnQuirkMode.PreferRoutine: - preferRoutine = true; - break; - - //case ReturnQuirkMode.PreferBlock: - default: - preferRoutine = false; - break; - } + var preferRoutine = quirkMode switch + { + ReturnQuirkMode.ByVersion => (c.cc.Context.ZEnvironment.ZVersion >= 5), + ReturnQuirkMode.PreferRoutine => true, + _ => false + }; if (block.ReturnLabel == null || (expr != null && preferRoutine)) { @@ -1930,7 +1875,7 @@ namespace Zilf.Compiler.Builtins } [Builtin("AGAIN", HasSideEffect = true)] - public static void AgainOp(VoidCall c, Block block = null) + public static void AgainOp(VoidCall c, Block? block = null) { if (block == null) { @@ -1948,9 +1893,8 @@ namespace Zilf.Compiler.Builtins } [Builtin("APPLY", "CALL", "ZAPPLY", HasSideEffect = true)] - [NotNull] public static IOperand CallValueOp(ValueCall c, - [Routine][NotNull] IOperand routine, [NotNull] params IOperand[] args) + [Routine] IOperand routine, params IOperand[] args) { if (args.Length > c.cc.Game.MaxCallArguments) { @@ -1965,7 +1909,7 @@ namespace Zilf.Compiler.Builtins [Builtin("APPLY", "CALL", MinVersion = 5, HasSideEffect = true)] public static void CallVoidOp(VoidCall c, - [Routine][NotNull] IOperand routine, [NotNull] params IOperand[] args) + [Routine] IOperand routine, params IOperand[] args) { if (args.Length > c.cc.Game.MaxCallArguments) { @@ -1985,7 +1929,7 @@ namespace Zilf.Compiler.Builtins [Builtin("INTBL?", MinVersion = 4, MaxVersion = 4)] [return: Table] public static void IntblValuePredOp_V4(ValuePredCall c, - [NotNull] IOperand value, [Table][NotNull] IOperand table, [NotNull] IOperand length) + IOperand value, [Table] IOperand table, IOperand length) { c.rb.EmitScanTable(value, table, length, null, c.resultStorage, c.label, c.polarity); } @@ -1993,12 +1937,12 @@ namespace Zilf.Compiler.Builtins [Builtin("INTBL?", MinVersion = 5)] [return: Table] public static void IntblValuePredOp_V5(ValuePredCall c, - [NotNull] IOperand value, [Table][NotNull] IOperand table, [NotNull] IOperand length, [CanBeNull] IOperand form = null) + IOperand value, [Table] IOperand table, IOperand length, IOperand? form = null) { c.rb.EmitScanTable(value, table, length, form, c.resultStorage, c.label, c.polarity); } - static bool TryGetLowCoreField([NotNull] string name, [NotNull] Context ctx, [NotNull] ISourceLine src, [NotNull] ZilObject fieldSpec, bool writing, + static bool TryGetLowCoreField(string name, Context ctx, ISourceLine src, ZilObject fieldSpec, bool writing, out int offset, out LowCoreFlags flags, out int minVersion) { offset = 0; @@ -2038,7 +1982,7 @@ namespace Zilf.Compiler.Builtins return false; } - atom = list.First as ZilAtom; + atom = (list.First as ZilAtom)!; if (atom == null) { ctx.HandleError(new CompilerError(src, CompilerMessages._0_First_List_Element_Must_Be_An_Atom, name)); @@ -2085,8 +2029,7 @@ namespace Zilf.Compiler.Builtins } [Builtin("LOWCORE")] - [NotNull] - public static IOperand LowCoreReadOp(ValueCall c, [NotNull] ZilObject fieldSpec) + public static IOperand LowCoreReadOp(ValueCall c, ZilObject fieldSpec) { if (!TryGetLowCoreField("LOWCORE", c.cc.Context, c.form.SourceLine, fieldSpec, false, out var offset, out var flags, out _)) return c.cc.Game.Zero; @@ -2108,7 +2051,7 @@ namespace Zilf.Compiler.Builtins } [Builtin("LOWCORE", HasSideEffect = true)] - public static void LowCoreWriteOp(VoidCall c, [NotNull] ZilObject fieldSpec, [NotNull] IOperand newValue) + public static void LowCoreWriteOp(VoidCall c, ZilObject fieldSpec, IOperand newValue) { if (!TryGetLowCoreField("LOWCORE", c.cc.Context, c.form.SourceLine, fieldSpec, true, out var offset, out var flags, out _)) return; @@ -2129,7 +2072,7 @@ namespace Zilf.Compiler.Builtins /// Local variables are not allowed here. [Builtin("LOWCORE-TABLE", HasSideEffect = true)] - public static void LowCoreTableOp(VoidCall c, [NotNull] ZilObject fieldSpec, int length, [NotNull] ZilAtom handler) + public static void LowCoreTableOp(VoidCall c, ZilObject fieldSpec, int length, ZilAtom handler) { if (!TryGetLowCoreField("LOWCORE-TABLE", c.cc.Context, c.form.SourceLine, fieldSpec, false, out var offset, out var flags, out _)) return; @@ -2159,11 +2102,10 @@ namespace Zilf.Compiler.Builtins } } - [NotNull] [Builtin("ITABLE")] [Builtin("TABLE", "PTABLE", "LTABLE", "PLTABLE")] [return: Table] - public static IOperand TableOp(ValueCall c, [NotNull] [ItemNotNull] params ZilObject[] args) + public static IOperand TableOp(ValueCall c, params ZilObject[] args) { var table = (ZilTable)c.form.Eval(c.cc.Context); var tableBuilder = c.cc.Game.DefineTable(table.Name, (table.Flags & TableFlags.Pure) != 0); @@ -2175,22 +2117,21 @@ namespace Zilf.Compiler.Builtins #region Logical & Loop Builtins - [NotNull] [Builtin("PROG", Data = StdAtom.PROG)] [Builtin("REPEAT", Data = StdAtom.REPEAT)] [Builtin("BIND", Data = StdAtom.BIND)] - public static IOperand ProgValueOp(ValueCall c, [Data] StdAtom mode, [NotNull] [ItemNotNull] params ZilObject[] args) + public static IOperand ProgValueOp(ValueCall c, [Data] StdAtom mode, params ZilObject[] args) { bool repeat = mode == StdAtom.REPEAT; bool catchy = mode != StdAtom.BIND; var (_, progBody) = c.form; - return c.cc.CompilePROG(c.rb, progBody, c.form.SourceLine, true, c.resultStorage, mode.ToString(), repeat, catchy); + return c.cc.CompilePROG(c.rb, progBody, c.form.SourceLine, true, c.resultStorage, mode.ToString(), repeat, catchy)!; } [Builtin("PROG", Data = StdAtom.PROG)] [Builtin("REPEAT", Data = StdAtom.REPEAT)] [Builtin("BIND", Data = StdAtom.BIND)] - public static void ProgVoidOp(VoidCall c, [Data] StdAtom mode, [NotNull] [ItemNotNull] params ZilObject[] args) + public static void ProgVoidOp(VoidCall c, [Data] StdAtom mode, params ZilObject[] args) { bool repeat = mode == StdAtom.REPEAT; bool catchy = mode != StdAtom.BIND; @@ -2198,11 +2139,10 @@ namespace Zilf.Compiler.Builtins c.cc.CompilePROG(c.rb, progBody, c.form.SourceLine, false, null, mode.ToString(), repeat, catchy); } - [NotNull] [Builtin("NOT", Data = false)] [Builtin("F?", Data = false)] [Builtin("T?", Data = true)] - public static IOperand TrueFalseValueOp(ValueCall c, [Data] bool polarity, [NotNull] ZilObject condition) + public static IOperand TrueFalseValueOp(ValueCall c, [Data] bool polarity, ZilObject condition) { var label1 = c.rb.DefineLabel(); var label2 = c.rb.DefineLabel(); @@ -2218,23 +2158,22 @@ namespace Zilf.Compiler.Builtins [Builtin("NOT", Data = false)] [Builtin("F?", Data = false)] [Builtin("T?", Data = true)] - public static void TrueFalsePredOp(PredCall c, [Data] bool polarity, [NotNull] ZilObject condition) + public static void TrueFalsePredOp(PredCall c, [Data] bool polarity, ZilObject condition) { c.cc.CompileCondition(c.rb, condition, c.form.SourceLine, c.label, polarity == c.polarity); } - [NotNull] [Builtin("OR", Data = false)] [Builtin("AND", Data = true)] - public static IOperand AndOrValueOp(ValueCall c, [Data] bool and, [NotNull] [ItemNotNull] params ZilObject[] args) + public static IOperand AndOrValueOp(ValueCall c, [Data] bool and, params ZilObject[] args) { Debug.Assert(c.form.Rest != null); - return c.cc.CompileBoolean(c.rb, c.form.Rest, c.form.SourceLine, and, true, c.resultStorage); + return c.cc.CompileBoolean(c.rb, c.form.Rest, c.form.SourceLine, and, true, c.resultStorage)!; } [Builtin("OR", Data = false)] [Builtin("AND", Data = true)] - public static void AndOrVoidOp(VoidCall c, [Data] bool and, [NotNull] [ItemNotNull] params ZilObject[] args) + public static void AndOrVoidOp(VoidCall c, [Data] bool and, params ZilObject[] args) { Debug.Assert(c.form.Rest != null); c.cc.CompileBoolean(c.rb, c.form.Rest, c.form.SourceLine, and, false, null); @@ -2242,96 +2181,90 @@ namespace Zilf.Compiler.Builtins [Builtin("OR", Data = false)] [Builtin("AND", Data = true)] - public static void AndOrPredOp(PredCall c, [Data] bool and, [NotNull] [ItemNotNull] params ZilObject[] args) + public static void AndOrPredOp(PredCall c, [Data] bool and, params ZilObject[] args) { c.cc.CompileBoolean(c.rb, args, c.form.SourceLine, and, c.label, c.polarity); } - [NotNull] [Builtin("DO")] - public static IOperand DoLoopValueOp(ValueCall c, [NotNull] [ItemNotNull] params ZilObject[] body) + public static IOperand DoLoopValueOp(ValueCall c, params ZilObject[] body) { Debug.Assert(c.form.Rest != null); return c.cc.CompileDO(c.rb, c.form.Rest, c.form.SourceLine, true, c.resultStorage); } [Builtin("DO")] - public static void DoLoopVoidOp(VoidCall c, [NotNull] [ItemNotNull] params ZilObject[] body) + public static void DoLoopVoidOp(VoidCall c, params ZilObject[] body) { Debug.Assert(c.form.Rest != null); c.cc.CompileDO(c.rb, c.form.Rest, c.form.SourceLine, false, null); } - [NotNull] [Builtin("MAP-CONTENTS")] - public static IOperand MapContentsValueOp(ValueCall c, [NotNull] [ItemNotNull] params ZilObject[] body) + public static IOperand MapContentsValueOp(ValueCall c, params ZilObject[] body) { Debug.Assert(c.form.Rest != null); return c.cc.CompileMAP_CONTENTS(c.rb, c.form.Rest, c.form.SourceLine, true, c.resultStorage); } [Builtin("MAP-CONTENTS")] - public static void MapContentsVoidOp(VoidCall c, [NotNull] [ItemNotNull] params ZilObject[] body) + public static void MapContentsVoidOp(VoidCall c, params ZilObject[] body) { Debug.Assert(c.form.Rest != null); c.cc.CompileMAP_CONTENTS(c.rb, c.form.Rest, c.form.SourceLine, false, null); } - [NotNull] [Builtin("MAP-DIRECTIONS")] - public static IOperand MapDirectionsValueOp(ValueCall c, [NotNull] [ItemNotNull] params ZilObject[] body) + public static IOperand MapDirectionsValueOp(ValueCall c, params ZilObject[] body) { Debug.Assert(c.form.Rest != null); return c.cc.CompileMAP_DIRECTIONS(c.rb, c.form.Rest, c.form.SourceLine, true, c.resultStorage); } [Builtin("MAP-DIRECTIONS")] - public static void MapDirectionsVoidOp(VoidCall c, [NotNull] [ItemNotNull] params ZilObject[] body) + public static void MapDirectionsVoidOp(VoidCall c, params ZilObject[] body) { Debug.Assert(c.form.Rest != null); c.cc.CompileMAP_DIRECTIONS(c.rb, c.form.Rest, c.form.SourceLine, false, null); } - [NotNull] [Builtin("COND")] - public static IOperand CondValueOp(ValueCall c, [NotNull] [ItemNotNull] params ZilObject[] clauses) + public static IOperand CondValueOp(ValueCall c, params ZilObject[] clauses) { Debug.Assert(c.form.Rest != null); - return c.cc.CompileCOND(c.rb, c.form.Rest, c.form.SourceLine, true, c.resultStorage); + return c.cc.CompileCOND(c.rb, c.form.Rest, c.form.SourceLine, true, c.resultStorage)!; } [Builtin("COND")] - public static void CondVoidOp(VoidCall c, [NotNull] [ItemNotNull] params ZilObject[] clauses) + public static void CondVoidOp(VoidCall c, params ZilObject[] clauses) { Debug.Assert(c.form.Rest != null); c.cc.CompileCOND(c.rb, c.form.Rest, c.form.SourceLine, false, null); } - [NotNull] [Builtin("VERSION?")] - public static IOperand IfVersionValueOp(ValueCall c, [NotNull] [ItemNotNull] params ZilObject[] clauses) + public static IOperand IfVersionValueOp(ValueCall c, params ZilObject[] clauses) { Debug.Assert(c.form.Rest != null); - return c.cc.CompileVERSION_P(c.rb, c.form.Rest, c.form.SourceLine, true, c.resultStorage); + return c.cc.CompileVERSION_P(c.rb, c.form.Rest, c.form.SourceLine, true, c.resultStorage)!; } [Builtin("VERSION?")] - public static void IfVersionVoidOp(VoidCall c, [NotNull] [ItemNotNull] params ZilObject[] clauses) + public static void IfVersionVoidOp(VoidCall c, params ZilObject[] clauses) { Debug.Assert(c.form.Rest != null); c.cc.CompileVERSION_P(c.rb, c.form.Rest, c.form.SourceLine, false, null); } - [NotNull] [Builtin("IFFLAG")] - public static IOperand IfFlagValueOp(ValueCall c, [NotNull] [ItemNotNull] params ZilObject[] clauses) + public static IOperand IfFlagValueOp(ValueCall c, params ZilObject[] clauses) { Debug.Assert(c.form.Rest != null); - return c.cc.CompileIFFLAG(c.rb, c.form.Rest, c.form.SourceLine, true, c.resultStorage); + return c.cc.CompileIFFLAG(c.rb, c.form.Rest, c.form.SourceLine, true, c.resultStorage)!; } [Builtin("IFFLAG")] - public static void IfFlagVoidOp(VoidCall c, [NotNull] [ItemNotNull] params ZilObject[] clauses) + public static void IfFlagVoidOp(VoidCall c, params ZilObject[] clauses) { Debug.Assert(c.form.Rest != null); c.cc.CompileIFFLAG(c.rb, c.form.Rest, c.form.SourceLine, false, null); @@ -2340,15 +2273,14 @@ namespace Zilf.Compiler.Builtins #endregion [Builtin("CHTYPE")] - [NotNull] - public static IOperand ChtypeValueOp(ValueCall c, [NotNull] IOperand value, [NotNull] ZilAtom type) + public static IOperand ChtypeValueOp(ValueCall c, IOperand value, ZilAtom type) { // TODO: check type? return value; } [Builtin("TELL")] - public static void TellVoidOp(VoidCall c, [NotNull] [ItemNotNull] params ZilObject[] args) + public static void TellVoidOp(VoidCall c, params ZilObject[] args) { c.cc.CompileTell(c.rb, c.form.SourceLine, args); } diff --git a/src/Zilf/Compiler/Compilation.Compile.cs b/src/Zilf/Compiler/Compilation.Compile.cs index e2ee14d..fb9bbe8 100644 --- a/src/Zilf/Compiler/Compilation.Compile.cs +++ b/src/Zilf/Compiler/Compilation.Compile.cs @@ -33,7 +33,7 @@ namespace Zilf.Compiler { partial class Compilation { - public static void Compile([NotNull] Context ctx, [NotNull] IGameBuilder gb) + public static void Compile(Context ctx, IGameBuilder gb) { var compilation = new Compilation(ctx, gb, gb.DebugFile != null && ctx.WantDebugInfo); compilation.Compile(); @@ -103,7 +103,7 @@ namespace Zilf.Compiler Game.Finish(); } - void HandleZValChangedWhileCompilingRoutine([NotNull] object sender, [NotNull] ZValEventArgs e) + void HandleZValChangedWhileCompilingRoutine(object? sender, ZValEventArgs e) { switch (e.NewValue) { @@ -128,7 +128,8 @@ namespace Zilf.Compiler } [ContractAnnotation("longWords: notnull => longWordTable: notnull")] - void BuildLongWordTable([CanBeNull] ITableBuilder longWordTable, [CanBeNull][ItemNotNull] Queue longWords) + [System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1308:Normalize strings to uppercase", Justification = "Z-machine requirement.")] + void BuildLongWordTable(ITableBuilder? longWordTable, Queue? longWords) { if (longWords == null) return; @@ -145,7 +146,7 @@ namespace Zilf.Compiler } } - void BuildVocabWords([CanBeNull] ITableBuilder longWordTable, [CanBeNull] out Queue longWords) + void BuildVocabWords(ITableBuilder? longWordTable, out Queue? longWords) { // build vocabulary longWords = longWordTable == null ? null : new Queue(); @@ -226,7 +227,7 @@ namespace Zilf.Compiler void GenerateRoutineCode() { // compile routines - IRoutineBuilder mainRoutine = null; + IRoutineBuilder? mainRoutine = null; foreach (var routine in Context.ZEnvironment.Routines) { @@ -306,7 +307,7 @@ namespace Zilf.Compiler } } - void PrepareReservedGlobalBuilders([ItemNotNull] [NotNull] string[] reservedGlobals) + void PrepareReservedGlobalBuilders(string[] reservedGlobals) { // implicitly defined globals // NOTE: the parameter to DoFunnyGlobals() above must match the number of globals implicitly defined here @@ -318,7 +319,7 @@ namespace Zilf.Compiler } } - void PrepareHardGlobalBuilders([ItemNotNull] [NotNull] Queue globalInitializers) + void PrepareHardGlobalBuilders(Queue globalInitializers) { // builders and values for globals (which may refer to constants) foreach (var global in Context.ZEnvironment.Globals) @@ -333,7 +334,7 @@ namespace Zilf.Compiler } } - static void PrepareGlobalDefaults([ItemNotNull] [NotNull] Queue globalInitializers) + static void PrepareGlobalDefaults(Queue globalInitializers) { while (globalInitializers.Count > 0) globalInitializers.Dequeue()?.Invoke(); @@ -344,7 +345,7 @@ namespace Zilf.Compiler Constants.Add(Context.GetStdAtom(StdAtom.VOCAB), Game.VocabularyTable); } - void PrepareLongWordTableBuilder([CanBeNull] out ITableBuilder longWordTable) + void PrepareLongWordTableBuilder(out ITableBuilder? longWordTable) { if (Context.GetCompilationFlagOption(StdAtom.LONG_WORDS)) { @@ -357,13 +358,13 @@ namespace Zilf.Compiler } } - void PrepareConstantBuilders([CanBeNull] ZilModelObject lastObject) + void PrepareConstantBuilders(ZilModelObject? lastObject) { // builders and values for constants (which may refer to vocabulary, // routines, tables, objects, properties, or flags) foreach (var constant in Context.ZEnvironment.Constants) { - IOperand value; + IOperand? value; if (constant.Name.StdAtom == StdAtom.LAST_OBJECT && lastObject != null) { value = Objects[lastObject.Name]; @@ -388,8 +389,8 @@ namespace Zilf.Compiler } } - void PrepareAndCheckGlobalStorage([NotNull] [ItemNotNull] Queue globalInitializers, - [ItemNotNull] [NotNull] out string[] reservedGlobals) + void PrepareAndCheckGlobalStorage(Queue globalInitializers, + out string[] reservedGlobals) { // FUNNY-GLOBALS? reservedGlobals = Context.ZEnvironment.VocabFormat.GetReservedGlobalNames(); @@ -405,11 +406,13 @@ namespace Zilf.Compiler g.StorageType = GlobalStorageType.Hard; if (Context.ZEnvironment.Globals.Count > 240 - reservedGlobals.Length) + { Context.HandleError(new CompilerError( CompilerMessages.Too_Many_0_1_Defined_Only_2_Allowed, "globals", Context.ZEnvironment.Globals.Count, 240 - reservedGlobals.Length)); + } } } @@ -417,19 +420,21 @@ namespace Zilf.Compiler { // enforce limit on number of flags if (UniqueFlags > Game.MaxFlags) + { Context.HandleError(new CompilerError( CompilerMessages.Too_Many_0_1_Defined_Only_2_Allowed, "flags", UniqueFlags, Game.MaxFlags)); + } } void PrepareFlagAliases() { // may as well do bit synonyms here too - foreach (var pair in Context.ZEnvironment.BitSynonyms) + foreach (var (alias, original) in Context.ZEnvironment.BitSynonyms) { - DefineFlagAlias(pair.Key, pair.Value); + DefineFlagAlias(alias, original); } } @@ -454,43 +459,44 @@ namespace Zilf.Compiler } } - void PerformVocabMerges([NotNull] Dictionary vocabMerges) + void PerformVocabMerges(Dictionary vocabMerges) { string[] wordConstantPrefixes = { "W?", "A?", "ACT?", "PR?" }; - foreach (var pair in vocabMerges) + foreach (var (dupWord, mainWord) in vocabMerges) { - IWord dupWord = pair.Key, mainWord = pair.Value; Vocabulary[dupWord] = Vocabulary[mainWord]; foreach (var prefix in wordConstantPrefixes) { var mainAtom = ZilAtom.Parse(prefix + mainWord.Atom.Text, Context); - if (Constants.TryGetValue(mainAtom, out var value)) - { - var dupAtom = ZilAtom.Parse(prefix + dupWord.Atom.Text, Context); - Constants[dupAtom] = value; - } + if (!Constants.TryGetValue(mainAtom, out var value)) + continue; + + var dupAtom = ZilAtom.Parse(prefix + dupWord.Atom.Text, Context); + Constants[dupAtom] = value; } } } - void PreparePunctuationAliasesAndPlanMerges([NotNull] Dictionary punctWords, - [NotNull] Dictionary vocabMerges) + void PreparePunctuationAliasesAndPlanMerges(Dictionary punctWords, + Dictionary vocabMerges) { - foreach (var pair in punctWords) + foreach (var (name, symbol) in punctWords) { - var nameAtom = ZilAtom.Parse(pair.Key, Context); - var symbolAtom = ZilAtom.Parse(pair.Value, Context); + var nameAtom = ZilAtom.Parse(name, Context); + var symbolAtom = ZilAtom.Parse(symbol, Context); - if (Context.ZEnvironment.Vocabulary.TryGetValue(symbolAtom, out var symbolWord) && - !Context.ZEnvironment.Vocabulary.ContainsKey(nameAtom)) + if (!Context.ZEnvironment.Vocabulary.TryGetValue(symbolAtom, out var symbolWord) || + Context.ZEnvironment.Vocabulary.ContainsKey(nameAtom)) { - var nameWord = Context.ZEnvironment.VocabFormat.CreateWord(nameAtom); - Context.ZEnvironment.VocabFormat.MakeSynonym(nameWord, symbolWord); - vocabMerges.Add(nameWord, symbolWord); + continue; } + + var nameWord = Context.ZEnvironment.VocabFormat.CreateWord(nameAtom); + Context.ZEnvironment.VocabFormat.MakeSynonym(nameWord, symbolWord); + vocabMerges.Add(nameWord, symbolWord); } } @@ -502,7 +508,7 @@ namespace Zilf.Compiler } } - void PlanVocabMerges([NotNull] out Dictionary vocabMerges) + void PlanVocabMerges(out Dictionary vocabMerges) { var merges = new Dictionary(); Context.ZEnvironment.MergeVocabulary((mainWord, duplicateWord) => @@ -521,7 +527,7 @@ namespace Zilf.Compiler } } - void PreparePunctuationWords([NotNull] out Dictionary punctWords) + void PreparePunctuationWords(out Dictionary punctWords) { // vocabulary for punctuation punctWords = new Dictionary @@ -542,19 +548,23 @@ namespace Zilf.Compiler void PrepareSelfInsertingBreaks() { // self-inserting breaks - if (Context.GetGlobalVal(Context.GetStdAtom(StdAtom.SIBREAKS)) is ZilString siBreaks) - { - Game.SelfInsertingBreaks.Clear(); - foreach (var c in siBreaks.Text) - Game.SelfInsertingBreaks.Add(c); - } + if (!(Context.GetGlobalVal(Context.GetStdAtom(StdAtom.SIBREAKS)) is ZilString siBreaks)) + return; + + Game.SelfInsertingBreaks.Clear(); + foreach (var c in siBreaks.Text) + Game.SelfInsertingBreaks.Add(c); } void PrepareTableBuilders() { // builders for tables - ITableBuilder firstPureTable = null; - int ParserTablesFirst(ZilTable t) => (t.Flags & TableFlags.ParserTable) != 0 ? 1 : 2; + ITableBuilder? firstPureTable = null; + + static int ParserTablesFirst(ZilTable t) + { + return (t.Flags & TableFlags.ParserTable) != 0 ? 1 : 2; + } foreach (var table in Context.ZEnvironment.Tables.OrderBy(ParserTablesFirst)) { @@ -572,13 +582,15 @@ namespace Zilf.Compiler } } - void PrepareObjectBuilders([CanBeNull] out ZilModelObject lastObject) + void PrepareObjectBuilders(out ZilModelObject? lastObject) { // builders for objects lastObject = null; - string GetGlobalSymbolType(ZilAtom atom) => - Game.IsGloballyDefined(atom.Text, out var type) ? type : null; + string? GetGlobalSymbolType(ZilAtom atom) + { + return Game.IsGloballyDefined(atom.Text, out var type) ? type : null; + } foreach (var obj in Context.ZEnvironment.ObjectsInDefinitionOrder(GetGlobalSymbolType)) { @@ -609,11 +621,13 @@ namespace Zilf.Compiler .ToList(); if (highestFlags.Count >= Game.MaxFlags) + { Context.HandleError(new CompilerError( CompilerMessages.Too_Many_0_1_Defined_Only_2_Allowed, "flags requiring high numbers", highestFlags.Count, Game.MaxFlags)); + } foreach (var flag in highestFlags) { diff --git a/src/Zilf/Compiler/Compilation.Conditions.cs b/src/Zilf/Compiler/Compilation.Conditions.cs index 7725e16..081f02b 100644 --- a/src/Zilf/Compiler/Compilation.Conditions.cs +++ b/src/Zilf/Compiler/Compilation.Conditions.cs @@ -16,6 +16,8 @@ * along with ZILF. If not, see . */ +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Zilf.Compiler.Builtins; using Zilf.Diagnostics; @@ -29,8 +31,8 @@ namespace Zilf.Compiler { partial class Compilation { - internal void CompileCondition([NotNull] IRoutineBuilder rb, [NotNull] ZilObject expr, [NotNull] ISourceLine src, - [NotNull] ILabel label, bool polarity) + internal void CompileCondition(IRoutineBuilder rb, ZilObject expr, ISourceLine? src, + ILabel label, bool polarity) { expr = expr.Unwrap(Context); var type = expr.StdTypeAtom; @@ -148,8 +150,8 @@ namespace Zilf.Compiler } } - internal void CompileBoolean([NotNull] IRoutineBuilder rb, [NotNull] ZilObject[] args, [NotNull] ISourceLine src, - bool and, [NotNull] ILabel label, bool polarity) + internal void CompileBoolean(IRoutineBuilder rb, ZilObject[] args, ISourceLine src, + bool and, ILabel label, bool polarity) { if (args.Length == 0) { @@ -172,7 +174,7 @@ namespace Zilf.Compiler * even though is false. We emulate this issue by compiling the * last element as a statement instead of a condition when it fits * this pattern. */ - var last = args[args.Length - 1]; + var last = args[^1]; if (and && last.IsSetToZeroForm()) { Context.HandleError(new CompilerError(last.SourceLine, CompilerMessages.Treating_SET_To_0_As_True_Here)); @@ -190,7 +192,7 @@ namespace Zilf.Compiler CompileCondition(rb, args[i], src, label, !and); /* QUIRK: Emulate the aforementioned SET issue. */ - var last = args[args.Length - 1]; + var last = args[^1]; if (and && last.IsSetToZeroForm()) { Context.HandleError(new CompilerError(last.SourceLine, CompilerMessages.Treating_SET_To_0_As_True_Here)); @@ -201,11 +203,10 @@ namespace Zilf.Compiler } } - [CanBeNull] [ContractAnnotation("wantResult: true => notnull")] [ContractAnnotation("wantResult: false => canbenull")] - internal IOperand CompileBoolean([NotNull] IRoutineBuilder rb, [NotNull] ZilListoidBase args, [NotNull] ISourceLine src, - bool and, bool wantResult, [CanBeNull] IVariable resultStorage) + internal IOperand? CompileBoolean(IRoutineBuilder rb, ZilListoidBase args, ISourceLine src, + bool and, bool wantResult, IVariable? resultStorage) { if (!args.IsCons(out var first, out var rest)) return and ? Game.One : Game.Zero; @@ -247,10 +248,10 @@ namespace Zilf.Compiler // hard path - need to preserve the values and return the last one evaluated var tempAtom = ZilAtom.Parse("?TMP", Context); lastLabel = rb.DefineLabel(); - IVariable tempVar = null; - ILabel trueLabel = null; + IVariable? tempVar = null; + ILabel? trueLabel = null; - resultStorage = resultStorage ?? rb.Stack; + resultStorage ??= rb.Stack; var nonStackResultStorage = resultStorage == rb.Stack ? null : resultStorage; IVariable TempVarProvider() @@ -265,7 +266,7 @@ namespace Zilf.Compiler ILabel TrueLabelProvider() { - return trueLabel ?? (trueLabel = rb.DefineLabel()); + return trueLabel ??= rb.DefineLabel(); } IOperand result; @@ -331,10 +332,9 @@ namespace Zilf.Compiler } // TODO: refactor COND-like control structures to share an implementation, a la CompileBoundedLoop - [CanBeNull] [ContractAnnotation("wantResult: true => notnull")] - internal IOperand CompileCOND([NotNull] IRoutineBuilder rb, [NotNull] ZilListoidBase clauses, [NotNull] ISourceLine src, - bool wantResult, [CanBeNull] IVariable resultStorage) + internal IOperand? CompileCOND(IRoutineBuilder rb, ZilListoidBase clauses, ISourceLine src, + bool wantResult, IVariable? resultStorage) { var nextLabel = rb.DefineLabel(); var endLabel = rb.DefineLabel(); @@ -398,7 +398,10 @@ namespace Zilf.Compiler // emit code for clause var clauseResult = CompileClauseBody(rb, body, wantResult, resultStorage); if (wantResult && clauseResult != resultStorage) + { + Debug.Assert(clauseResult != null); rb.EmitStore(resultStorage, clauseResult); + } // jump to end if (!clauses.IsEmpty || wantResult && !elsePart) @@ -426,15 +429,14 @@ namespace Zilf.Compiler return wantResult ? resultStorage : null; } - [CanBeNull] [ContractAnnotation("wantResult: true => notnull")] - IOperand CompileClauseBody([NotNull] IRoutineBuilder rb, [NotNull] ZilListoidBase clause, bool wantResult, - [CanBeNull] IVariable resultStorage) + IOperand? CompileClauseBody(IRoutineBuilder rb, ZilListoidBase clause, bool wantResult, + IVariable? resultStorage) { if (clause.IsEmpty) return Game.One; - IOperand result = null; + IOperand? result = null; do { @@ -486,12 +488,11 @@ namespace Zilf.Compiler return result; } - [CanBeNull] [ContractAnnotation("wantResult: true => notnull")] - internal IOperand CompileVERSION_P([NotNull] IRoutineBuilder rb, [NotNull] ZilListoidBase clauses, [NotNull] ISourceLine src, - bool wantResult, [CanBeNull] IVariable resultStorage) + internal IOperand? CompileVERSION_P(IRoutineBuilder rb, ZilListoidBase clauses, ISourceLine src, + bool wantResult, IVariable? resultStorage) { - resultStorage = resultStorage ?? rb.Stack; + resultStorage ??= rb.Stack; while (!clauses.IsEmpty) { ZilObject clause; @@ -564,12 +565,11 @@ namespace Zilf.Compiler return wantResult ? resultStorage : null; } - [CanBeNull] [ContractAnnotation("wantResult: true => notnull")] - internal IOperand CompileIFFLAG([NotNull] IRoutineBuilder rb, [NotNull] ZilListoidBase clauses, [NotNull] ISourceLine src, - bool wantResult, [CanBeNull] IVariable resultStorage) + internal IOperand? CompileIFFLAG(IRoutineBuilder rb, ZilListoidBase clauses, ISourceLine src, + bool wantResult, IVariable? resultStorage) { - resultStorage = resultStorage ?? rb.Stack; + resultStorage ??= rb.Stack; while (!clauses.IsEmpty) { @@ -582,14 +582,17 @@ namespace Zilf.Compiler var (flag, body) = list; - ZilObject value; bool match, isElse = false; - ZilAtom shadyElseAtom = null; + ZilAtom? shadyElseAtom = null; switch (flag) { - case ZilAtom atom when (value = Context.GetCompilationFlagValue(atom)) != null: - case ZilString str when (value = Context.GetCompilationFlagValue(str.Text)) != null: + case ZilAtom atom when Context.GetCompilationFlagValue(atom) is ZilObject value: + // name of a defined compilation flag + match = value.IsTrue; + break; + + case ZilString str when Context.GetCompilationFlagValue(str.Text) is ZilObject value: // name of a defined compilation flag match = value.IsTrue; break; diff --git a/src/Zilf/Compiler/Compilation.Expressions.cs b/src/Zilf/Compiler/Compilation.Expressions.cs index 40ed8b7..5bba331 100644 --- a/src/Zilf/Compiler/Compilation.Expressions.cs +++ b/src/Zilf/Compiler/Compilation.Expressions.cs @@ -47,9 +47,8 @@ namespace Zilf.Compiler /// The syntax is incorrect, or an error occurred while compiling a subexpression. [ContractAnnotation("wantResult: true => notnull")] [ContractAnnotation("wantResult: false => null")] - [CanBeNull] - internal IOperand CompileForm([NotNull] IRoutineBuilder rb, [NotNull] ZilForm form, bool wantResult, - IVariable resultStorage) + internal IOperand? CompileForm(IRoutineBuilder rb, ZilForm form, bool wantResult, + IVariable? resultStorage) { using (DiagnosticContext.Push(form.SourceLine)) { @@ -89,7 +88,7 @@ namespace Zilf.Compiler if (ZBuiltins.IsBuiltinValuePredCall(head.Text, zversion, argCount)) { var label1 = rb.DefineLabel(); - resultStorage = resultStorage ?? rb.Stack; + resultStorage ??= rb.Stack; ZBuiltins.CompileValuePredCall(head.Text, this, rb, form, resultStorage, label1, true); rb.MarkLabel(label1); return resultStorage; @@ -98,7 +97,7 @@ namespace Zilf.Compiler { var label1 = rb.DefineLabel(); var label2 = rb.DefineLabel(); - resultStorage = resultStorage ?? rb.Stack; + resultStorage ??= rb.Stack; ZBuiltins.CompilePredCall(head.Text, this, rb, form, label1, true); rb.EmitStore(resultStorage, Game.Zero); rb.Branch(label2); @@ -202,20 +201,18 @@ namespace Zilf.Compiler } /// The syntax is incorrect, or an error occurred while compiling a subexpression. - [NotNull] - public IOperand CompileAsOperand([NotNull] IRoutineBuilder rb, [NotNull] ZilObject expr, [NotNull] ISourceLine src, - [CanBeNull] IVariable suggestion = null) + public IOperand CompileAsOperand(IRoutineBuilder rb, ZilObject expr, ISourceLine? src, + IVariable? suggestion = null) { expr = expr.Unwrap(Context); - var constant = CompileConstant(expr, AmbiguousConstantMode.Pessimistic); - if (constant != null) + if (CompileConstant(expr, AmbiguousConstantMode.Pessimistic) is { } constant) return constant; switch (expr.StdTypeAtom) { case StdAtom.FORM: - return CompileForm(rb, (ZilForm)expr, true, suggestion ?? rb.Stack); + return CompileForm(rb, (ZilForm)expr, true, suggestion ?? rb.Stack)!; case StdAtom.ATOM: var atom = (ZilAtom)expr; @@ -269,15 +266,14 @@ namespace Zilf.Compiler /// it is non-null and the expression is valid. Otherwise, may be a constant, or the natural /// location of the expression, or a temporary variable from . /// The syntax is incorrect, or an error occurred while compiling a subexpression. - [NotNull] [ContractAnnotation("resultStorage: null => tempVarProvider: notnull")] [ContractAnnotation("tempVarProvider: null => resultStorage: notnull")] - internal IOperand CompileAsOperandWithBranch([NotNull] IRoutineBuilder rb, [NotNull] ZilObject expr, - [CanBeNull] IVariable resultStorage, - [NotNull] ILabel label, bool polarity, [CanBeNull] [InstantHandle] Func tempVarProvider = null) + internal IOperand CompileAsOperandWithBranch(IRoutineBuilder rb, ZilObject expr, + IVariable? resultStorage, + ILabel label, bool polarity, [InstantHandle] Func? tempVarProvider = null) { expr = expr.Unwrap(Context); - IOperand result = resultStorage; + IOperand result = resultStorage!; switch (expr) { @@ -438,7 +434,7 @@ namespace Zilf.Compiler } } - internal void CompileTell([NotNull] IRoutineBuilder rb, [NotNull] ISourceLine src, [NotNull] [ItemNotNull] ZilObject[] args) + internal void CompileTell(IRoutineBuilder rb, ISourceLine src, ZilObject[] args) { int index = 0; while (index < args.Length) @@ -448,13 +444,13 @@ namespace Zilf.Compiler foreach (var pattern in Context.ZEnvironment.TellPatterns) { var result = pattern.Match(args, index, Context, src); - if (result.Matched) - { - CompileForm(rb, result.Output, false, null); - index += pattern.Length; - handled = true; - break; - } + if (!result.Matched) + continue; + + CompileForm(rb, result.Output!, false, null); + index += pattern.Length; + handled = true; + break; } if (handled) diff --git a/src/Zilf/Compiler/Compilation.Globals.cs b/src/Zilf/Compiler/Compilation.Globals.cs index 4c5df6f..1c7084c 100644 --- a/src/Zilf/Compiler/Compilation.Globals.cs +++ b/src/Zilf/Compiler/Compilation.Globals.cs @@ -31,13 +31,12 @@ namespace Zilf.Compiler { partial class Compilation { - [CanBeNull] - IOperand GetGlobalDefaultValue([NotNull] ZilGlobal global) + IOperand? GetGlobalDefaultValue(ZilGlobal global) { if (global.Value == null) return null; - IOperand result = null; + IOperand? result = null; try { @@ -258,80 +257,92 @@ namespace Zilf.Compiler Pessimistic, } - [CanBeNull] - public IOperand CompileConstant([NotNull] ZilObject expr) + public IOperand? CompileConstant(ZilObject expr) { return CompileConstant(expr, AmbiguousConstantMode.Pessimistic); } // this method has a high complexity score because it has a big switch statement [SuppressMessage("ReSharper", "CyclomaticComplexity")] - [CanBeNull] - public IOperand CompileConstant([NotNull] ZilObject expr, AmbiguousConstantMode mode) + public IOperand? CompileConstant(ZilObject expr, AmbiguousConstantMode mode) { - switch (expr.Unwrap(Context)) + while (true) { - case ZilFix fix: - return Game.MakeOperand(fix.Value); + switch (expr.Unwrap(Context)) + { + case ZilFix fix: + return Game.MakeOperand(fix.Value); - case ZilHash hash when hash.StdTypeAtom == StdAtom.BYTE && hash.GetPrimitive(Context) is ZilFix fix: - return Game.MakeOperand(fix.Value); + case ZilHash hash when hash.StdTypeAtom == StdAtom.BYTE && hash.GetPrimitive(Context) is ZilFix fix: + return Game.MakeOperand(fix.Value); - case ZilWord word: - return CompileConstant(word.Value); + case ZilWord word: + return CompileConstant(word.Value); - case ZilString str: - return Game.MakeOperand(TranslateString(str, Context)); + case ZilString str: + return Game.MakeOperand(TranslateString(str, Context)); - case ZilChar ch: - return Game.MakeOperand((byte)ch.Char); + case ZilChar ch: + return Game.MakeOperand((byte)ch.Char); - case ZilAtom atom: - if (atom.StdAtom == StdAtom.T) - return Game.One; - if (Routines.TryGetValue(atom, out var routine)) - return routine; - if (Objects.TryGetValue(atom, out var obj)) - return obj; - if (Constants.TryGetValue(atom, out var operand)) - return operand; + case ZilAtom atom: + if (atom.StdAtom == StdAtom.T) + return Game.One; + if (Routines.TryGetValue(atom, out var routine)) + return routine; + if (Objects.TryGetValue(atom, out var obj)) + return obj; + if (Constants.TryGetValue(atom, out var operand)) + return operand; - if (mode == AmbiguousConstantMode.Optimistic && Globals.TryGetValue(atom, out var global)) - { - Context.HandleError(new CompilerError((ISourceLine)null, - CompilerMessages.Bare_Atom_0_Interpreted_As_Global_Variable_Index, atom)); - return global; - } - return null; + if (mode == AmbiguousConstantMode.Optimistic && Globals.TryGetValue(atom, out var global)) + { + Context.HandleError(new CompilerError((ISourceLine?)null, + CompilerMessages.Bare_Atom_0_Interpreted_As_Global_Variable_Index, + atom)); + return global; + } + + return null; - case ZilFalse _: - return Game.Zero; + case ZilFalse _: + return Game.Zero; - case ZilTable table: - if (Tables.TryGetValue(table, out var tb)) + case ZilTable table: + if (Tables.TryGetValue(table, out var tb)) + return tb; + + tb = Game.DefineTable(table.Name, true); + Tables.Add(table, tb); return tb; - tb = Game.DefineTable(table.Name, true); - Tables.Add(table, tb); - return tb; + case ZilConstant constant: + return CompileConstant(constant.Value); + + case ZilForm form: + if (form.IsGVAL(out var globalAtom)) + { + expr = globalAtom; + mode = AmbiguousConstantMode.Pessimistic; + continue; + } + + return null; - case ZilConstant constant: - return CompileConstant(constant.Value); + case ZilHash hash when hash.StdTypeAtom == StdAtom.VOC && hash.GetPrimitive(Context) is ZilAtom primAtom: + var wordAtom = ZilAtom.Parse("W?" + primAtom.Text, Context); + if (Constants.TryGetValue(wordAtom, out operand)) + return operand; - case ZilForm form: - return form.IsGVAL(out var globalAtom) ? CompileConstant(globalAtom, AmbiguousConstantMode.Pessimistic) : null; + return null; - case ZilHash hash when hash.StdTypeAtom == StdAtom.VOC && hash.GetPrimitive(Context) is ZilAtom primAtom: - var wordAtom = ZilAtom.Parse("W?" + primAtom.Text, Context); - if (Constants.TryGetValue(wordAtom, out operand)) - return operand; - return null; + default: + var primitive = expr.GetPrimitive(Context); + if (primitive != expr && primitive.GetTypeAtom(Context) != expr.GetTypeAtom(Context)) + return CompileConstant(primitive); - default: - var primitive = expr.GetPrimitive(Context); - if (primitive != expr && primitive.GetTypeAtom(Context) != expr.GetTypeAtom(Context)) - return CompileConstant(primitive); - return null; + return null; + } } } } diff --git a/src/Zilf/Compiler/Compilation.Loops.cs b/src/Zilf/Compiler/Compilation.Loops.cs index 397c624..8d463ee 100644 --- a/src/Zilf/Compiler/Compilation.Loops.cs +++ b/src/Zilf/Compiler/Compilation.Loops.cs @@ -35,23 +35,21 @@ namespace Zilf.Compiler /// The syntax is incorrect, or an error occurred while compiling a subexpression. [ContractAnnotation("wantResult: false => null")] [ContractAnnotation("wantResult: true => notnull")] - internal IOperand CompilePROG([NotNull] IRoutineBuilder rb, [NotNull] ZilListoidBase args, - [NotNull] ISourceLine src, - bool wantResult, [CanBeNull] IVariable resultStorage, [NotNull] string name, bool repeat, bool catchy) + internal IOperand? CompilePROG(IRoutineBuilder rb, ZilListoidBase args, + ISourceLine src, + bool wantResult, IVariable? resultStorage, string name, bool repeat, bool catchy) { if (!args.IsCons(out var first, out var rest)) { throw new CompilerError(CompilerMessages._0_Argument_1_2, name, 1, "argument must be an activation atom or binding list"); } - if (first is ZilAtom activationAtom) + var activationAtom = first as ZilAtom; + + if (activationAtom != null) { args = rest; } - else - { - activationAtom = null; - } if (!args.IsCons(out var bindings, out var body) || !(bindings is ZilList bindingList)) { @@ -119,11 +117,11 @@ namespace Zilf.Compiler case ZilList list when !list.HasLength(2): throw new CompilerError(CompilerMessages._0_Expected_1_Element1s_In_Binding_List, name, 2); - case ZilList list when list.Matches(out ZilAtom atom, out ZilObject value): + case ZilList list when list.Matches(out ZilAtom? atom, out ZilObject? value): AddLocalWithDefault(atom, value); break; - case ZilList list when list.Matches(out ZilAdecl adecl, out ZilObject value) && adecl.First is ZilAtom atom: + case ZilList list when list.Matches(out ZilAdecl? adecl, out ZilObject? value) && adecl.First is ZilAtom atom: AddLocalWithDefault(atom, value); break; @@ -158,7 +156,7 @@ namespace Zilf.Compiler try { // generate code for prog body - IOperand result; + IOperand? result; if (wantResult) { @@ -194,7 +192,7 @@ namespace Zilf.Compiler } else if (clauseResult != resultStorage && (block.Flags & BlockFlags.Returned) != 0) { - rb.EmitStore(resultStorage, clauseResult); + rb.EmitStore(resultStorage!, clauseResult!); result = resultStorage; } else @@ -226,7 +224,7 @@ namespace Zilf.Compiler } [SuppressMessage("ReSharper", "ImplicitlyCapturedClosure")] - static void TransformProgArgsIfImplementingDeferredReturn([NotNull] ref ZilList bindingList, [NotNull] ref ZilListoidBase body) + static void TransformProgArgsIfImplementingDeferredReturn(ref ZilList bindingList, ref ZilListoidBase body) { // ends with ? if (!(body.EnumerateNonRecursive().LastOrDefault() is ZilForm lastExpr) || !lastExpr.IsLVAL(out var atom)) @@ -249,7 +247,9 @@ namespace Zilf.Compiler // atom is not referenced anywhere else? if (!body.All(zo => ReferenceEquals(zo, setExpr) || ReferenceEquals(zo, lastExpr) || !RecursivelyContains(zo, atom))) + { return; + } // we got a winner! bindingList = new ZilList( @@ -258,19 +258,17 @@ namespace Zilf.Compiler body = new ZilList( body .Where(zo => !ReferenceEquals(zo, lastExpr)) - .Select(zo => ReferenceEquals(zo, setExpr) ? ((IStructure)zo)[2] : zo)); + .Select(zo => ReferenceEquals(zo, setExpr) ? ((IStructure)zo)[2]! : zo)); } - [NotNull] - static IEnumerable GetUninitializedAtomsFromBindingList([NotNull] ZilListBase bindingList) + static IEnumerable GetUninitializedAtomsFromBindingList(ZilListBase bindingList) { return bindingList.EnumerateNonRecursive() - .Select(GetUninitializedAtomFromBindingListItem) - .Where(a => a != null); + .Select(GetUninitializedAtomFromBindingListItem!) + .Where(a => a != null)!; } - [CanBeNull] - static ZilAtom GetUninitializedAtomFromBindingListItem([NotNull] ZilObject zo) + static ZilAtom? GetUninitializedAtomFromBindingListItem(ZilObject zo) { // ReSharper disable once SwitchStatementMissingSomeCases switch (zo.StdTypeAtom) @@ -286,7 +284,7 @@ namespace Zilf.Compiler } } - static bool RecursivelyContains([NotNull] ZilObject haystack, [NotNull] ZilObject needle) + static bool RecursivelyContains(ZilObject haystack, ZilObject needle) { if (haystack == needle) return true; @@ -300,7 +298,6 @@ namespace Zilf.Compiler /// /// The name of the loop statement, for use in diagnostics. /// - [NotNull] string Name { get; } /// @@ -309,7 +306,6 @@ namespace Zilf.Compiler /// /// /// The loop syntax was incorrect. - [NotNull] IBoundedLoop MakeLoop(BoundedLoopContext blc); } @@ -319,7 +315,7 @@ namespace Zilf.Compiler public readonly ZilList spec; public readonly ISourceLine src; - public BoundedLoopContext([NotNull] Compilation cc, [NotNull] ZilList spec, [NotNull] ISourceLine src) + public BoundedLoopContext(Compilation cc, ZilList spec, ISourceLine src) { this.cc = cc; this.spec = spec; @@ -338,7 +334,7 @@ namespace Zilf.Compiler /// /// This code should initialize the counter. /// - void BeforeBlock([NotNull] IRoutineBuilder rb, [NotNull] Block block, [NotNull] ILabel exhaustedLabel); + void BeforeBlock(IRoutineBuilder rb, Block block, ILabel exhaustedLabel); /// /// Emit code to be executed before the loop body on each iteration. @@ -382,18 +378,18 @@ namespace Zilf.Compiler // ReSharper restore InconsistentNaming #pragma warning restore IDE1006 // Naming Styles - IRoutineBuilder rb; - ILabel againLabel, exhaustedLabel; + IRoutineBuilder rb = null!; + ILabel againLabel = null!, exhaustedLabel = null!; public abstract void Dispose(); - protected abstract void EmitBeforeBlock([NotNull] IRoutineBuilder rb, [NotNull] ILabel exhaustedLabel); - protected abstract void EmitBeforeBody([NotNull] IRoutineBuilder rb, [NotNull] ILabel againLabel, [NotNull] ILabel exhaustedLabel); - protected abstract void EmitAfterBody([NotNull] IRoutineBuilder rb, [NotNull] ILabel againLabel); + protected abstract void EmitBeforeBlock(IRoutineBuilder rb, ILabel exhaustedLabel); + protected abstract void EmitBeforeBody(IRoutineBuilder rb, ILabel againLabel, ILabel exhaustedLabel); + protected abstract void EmitAfterBody(IRoutineBuilder rb, ILabel againLabel); public void BeforeBlock(IRoutineBuilder rb, Block block, ILabel exhaustedLabel) { this.rb = rb; - this.againLabel = block.AgainLabel; + this.againLabel = block.AgainLabel!; this.exhaustedLabel = exhaustedLabel; EmitBeforeBlock(rb, exhaustedLabel); @@ -410,13 +406,12 @@ namespace Zilf.Compiler } } - [CanBeNull] [ContractAnnotation("wantResult: true, resultStorage: notnull => notnull")] [ContractAnnotation("wantResult: false, resultStorage: null => canbenull")] - private IOperand CompileBoundedLoop( - [NotNull] IRoutineBuilder rb, [NotNull] IBoundedLoopBuilder builder, - [NotNull] ZilListoidBase args, [NotNull] ISourceLine src, - bool wantResult, [CanBeNull] IVariable resultStorage) + private IOperand? CompileBoundedLoop( + IRoutineBuilder rb, IBoundedLoopBuilder builder, + ZilListoidBase args, ISourceLine src, + bool wantResult, IVariable? resultStorage) { // extract loop spec ("binding list", although we don't care about the bindings here) // TODO: allow activation atoms in bounded loops? @@ -427,79 +422,75 @@ namespace Zilf.Compiler // instantiate the loop and let it check binding syntax var blc = new BoundedLoopContext(this, spec, src); + using var loop = builder.MakeLoop(blc); - using (var loop = builder.MakeLoop(blc)) + // look for the optional end statements + ZilListoidBase body; + if (rest.StartsWith(out ZilList? endStmts)) { - // look for the optional end statements - ZilListoidBase body; - if (rest.StartsWith(out ZilList endStmts)) - { - (_, body) = rest; - } - else - { - body = rest; - } + (_, body) = rest; + } + else + { + body = rest; + } - // create block - resultStorage = wantResult ? (resultStorage ?? rb.Stack) : null; + // create block + resultStorage = wantResult ? (resultStorage ?? rb.Stack) : null; - var block = new Block - { - AgainLabel = rb.DefineLabel(), - ResultStorage = resultStorage, - ReturnLabel = rb.DefineLabel(), - Flags = wantResult ? BlockFlags.WantResult : 0 - }; - - Blocks.Push(block); - try - { - var exhaustedLabel = rb.DefineLabel(); + var block = new Block + { + AgainLabel = rb.DefineLabel(), + ResultStorage = resultStorage, + ReturnLabel = rb.DefineLabel(), + Flags = wantResult ? BlockFlags.WantResult : 0 + }; - // let the loop initialize counters, etc. - loop.BeforeBlock(rb, block, exhaustedLabel); + Blocks.Push(block); + try + { + var exhaustedLabel = rb.DefineLabel(); - // mark the top of the block ("again" label) and let the loop add prechecks, etc. - rb.MarkLabel(block.AgainLabel); - loop.BeforeBody(); + // let the loop initialize counters, etc. + loop.BeforeBlock(rb, block, exhaustedLabel); - // compile the body - CompileClauseBody(rb, body, false, null); + // mark the top of the block ("again" label) and let the loop add prechecks, etc. + rb.MarkLabel(block.AgainLabel); + loop.BeforeBody(); - // let the loop add postchecks, etc., and mark the end of the block ("exhausted" label) - loop.AfterBody(); + // compile the body + CompileClauseBody(rb, body, false, null); - rb.MarkLabel(exhaustedLabel); + // let the loop add postchecks, etc., and mark the end of the block ("exhausted" label) + loop.AfterBody(); - // compile the end statements if present, and provide a return value if requested - if (endStmts != null) - CompileClauseBody(rb, endStmts, false, null); + rb.MarkLabel(exhaustedLabel); - if (wantResult) - rb.EmitStore(resultStorage, Game.One); + // compile the end statements if present, and provide a return value if requested + if (endStmts != null) + CompileClauseBody(rb, endStmts, false, null); - // if was used inside the loop, mark the return label - if ((block.Flags & BlockFlags.Returned) != 0) - rb.MarkLabel(block.ReturnLabel); - } - finally - { - Blocks.Pop(); - } + if (wantResult) + rb.EmitStore(resultStorage!, Game.One); - return wantResult ? resultStorage : null; + // if was used inside the loop, mark the return label + if ((block.Flags & BlockFlags.Returned) != 0) + rb.MarkLabel(block.ReturnLabel); + } + finally + { + Blocks.Pop(); } + + return wantResult ? resultStorage : null; } /// The syntax is incorrect, or an error occurred while compiling a subexpression. [ContractAnnotation("wantResult: false => null")] [ContractAnnotation("wantResult: true => notnull")] - internal IOperand CompileDO([NotNull] IRoutineBuilder rb, [NotNull] ZilListoidBase args, [NotNull] ISourceLine src, bool wantResult, - [CanBeNull] IVariable resultStorage) - { - return CompileBoundedLoop(rb, DoLoop.Builder, args, src, wantResult, resultStorage); - } + internal IOperand CompileDO(IRoutineBuilder rb, ZilListoidBase args, ISourceLine src, bool wantResult, + IVariable? resultStorage) => + CompileBoundedLoop(rb, DoLoop.Builder, args, src, wantResult, resultStorage)!; private class DoLoop : IBoundedLoopBuilder { @@ -522,7 +513,7 @@ namespace Zilf.Compiler new CountableString("3 or 4", true)); } - if (!blc.spec.Matches(out ZilAtom atom, out ZilObject start, out ZilObject end, out ZilObject inc) && + if (!blc.spec.Matches(out ZilAtom ?atom, out ZilObject? start, out ZilObject? end, out ZilObject? inc) && !blc.spec.Matches(out atom, out start, out end)) { throw new CompilerError( @@ -539,11 +530,12 @@ namespace Zilf.Compiler private class Loop : BoundedLoop { readonly ZilAtom atom; - readonly ZilObject start, end, inc; + readonly ZilObject start, end; + readonly ZilObject? inc; bool precheck; - ILocalBuilder counter; + ILocalBuilder counter = null!; // initialized in EmitBeforeBlock - public Loop(BoundedLoopContext blc, ZilAtom atom, ZilObject start, ZilObject end, ZilObject inc) + public Loop(BoundedLoopContext blc, ZilAtom atom, ZilObject start, ZilObject end, ZilObject? inc) : base(blc) { this.atom = atom; @@ -631,11 +623,9 @@ namespace Zilf.Compiler /// The syntax is incorrect, or an error occurred while compiling a subexpression. [ContractAnnotation("wantResult: false => null")] [ContractAnnotation("wantResult: true => notnull")] - internal IOperand CompileMAP_CONTENTS([NotNull] IRoutineBuilder rb, [NotNull] ZilListoidBase args, [NotNull] ISourceLine src, bool wantResult, - [CanBeNull] IVariable resultStorage) - { - return CompileBoundedLoop(rb, MapContentsLoop.Builder, args, src, wantResult, resultStorage); - } + internal IOperand CompileMAP_CONTENTS(IRoutineBuilder rb, ZilListoidBase args, ISourceLine src, bool wantResult, + IVariable? resultStorage) => + CompileBoundedLoop(rb, MapContentsLoop.Builder, args, src, wantResult, resultStorage)!; private class MapContentsLoop : IBoundedLoopBuilder { @@ -649,14 +639,14 @@ namespace Zilf.Compiler public IBoundedLoop MakeLoop(BoundedLoopContext blc) { - if (blc.spec.Matches(out ZilAtom atom, out ZilAtom nextAtom, out ZilObject container)) + if (blc.spec.Matches(out ZilAtom? atom, out ZilAtom? nextAtom, out ZilObject? container)) return new TwoVarLoop(blc, atom, nextAtom, container); if (blc.spec.Matches(out atom, out container)) return new OneVarLoop(blc, atom, container); // throw an appropriate error - var matched = blc.spec.Matches(out ZilObject atomObj, out ZilObject nextAtomObj, out container) || + var matched = blc.spec.Matches(out ZilObject? atomObj, out ZilObject? nextAtomObj, out container) || blc.spec.Matches(out atomObj, out container); if (!matched) @@ -679,15 +669,13 @@ namespace Zilf.Compiler abstract class LoopBase : BoundedLoop { - [NotNull] readonly ZilAtom atom; - [NotNull] readonly ZilObject container; - protected ILocalBuilder counter; + protected ILocalBuilder? counter; - protected LoopBase(BoundedLoopContext blc, [NotNull] ZilAtom atom, [NotNull] ZilObject container) + protected LoopBase(BoundedLoopContext blc, ZilAtom atom, ZilObject container) : base(blc) { this.atom = atom; @@ -711,7 +699,7 @@ namespace Zilf.Compiler private class OneVarLoop : LoopBase { - public OneVarLoop(BoundedLoopContext blc, [NotNull] ZilAtom atom, [NotNull] ZilObject container) + public OneVarLoop(BoundedLoopContext blc, ZilAtom atom, ZilObject container) : base(blc, atom, container) { } @@ -724,18 +712,17 @@ namespace Zilf.Compiler protected override void EmitAfterBody(IRoutineBuilder rb, ILabel againLabel) { // next object - rb.EmitGetSibling(counter, counter, againLabel, true); + rb.EmitGetSibling(counter!, counter!, againLabel, true); } } private class TwoVarLoop : LoopBase { - [NotNull] readonly ZilAtom nextAtom; - ILocalBuilder next; + ILocalBuilder? next; - public TwoVarLoop(BoundedLoopContext blc, [NotNull] ZilAtom atom, [NotNull] ZilAtom nextAtom, [NotNull] ZilObject container) + public TwoVarLoop(BoundedLoopContext blc, ZilAtom atom, ZilAtom nextAtom, ZilObject container) : base(blc, atom, container) { this.nextAtom = nextAtom; @@ -754,14 +741,14 @@ namespace Zilf.Compiler // initialize next next = cc.PushInnerLocal(rb, nextAtom, LocalBindingType.LoopState, src); var tempLabel = rb.DefineLabel(); - rb.EmitGetSibling(counter, next, tempLabel, true); + rb.EmitGetSibling(counter!, next, tempLabel, true); rb.MarkLabel(tempLabel); } protected override void EmitAfterBody(IRoutineBuilder rb, ILabel againLabel) { - rb.EmitStore(counter, next); - rb.BranchIfZero(counter, againLabel, false); + rb.EmitStore(counter!, next!); + rb.BranchIfZero(counter!, againLabel, false); } } } @@ -769,11 +756,9 @@ namespace Zilf.Compiler /// The syntax is incorrect, or an error occurred while compiling a subexpression. [ContractAnnotation("wantResult: false => null")] [ContractAnnotation("wantResult: true => notnull")] - internal IOperand CompileMAP_DIRECTIONS([NotNull] IRoutineBuilder rb, [NotNull] ZilListoidBase args, [NotNull] ISourceLine src, bool wantResult, - [CanBeNull] IVariable resultStorage) - { - return CompileBoundedLoop(rb, MapDirectionsLoop.Builder, args, src, wantResult, resultStorage); - } + internal IOperand CompileMAP_DIRECTIONS(IRoutineBuilder rb, ZilListoidBase args, ISourceLine src, bool wantResult, + IVariable? resultStorage) => + CompileBoundedLoop(rb, MapDirectionsLoop.Builder, args, src, wantResult, resultStorage)!; private class MapDirectionsLoop : IBoundedLoopBuilder { @@ -787,16 +772,14 @@ namespace Zilf.Compiler public IBoundedLoop MakeLoop(BoundedLoopContext blc) { - if (blc.spec.Matches(out ZilAtom dirAtom, out ZilAtom ptAtom, out ZilObject room) && + if (blc.spec.Matches(out ZilAtom? dirAtom, out ZilAtom? ptAtom, out ZilObject? room) && (room.IsLVAL(out _) || room.IsGVAL(out _))) { return new Loop(blc, dirAtom, ptAtom, room); } // throw an appropriate error - var matched = blc.spec.Matches(out ZilObject dirObj, out ZilObject ptObj, out room); - - if (!matched) + if (!blc.spec.Matches(out ZilObject? dirObj, out ZilObject? ptObj, out room)) throw new CompilerError(CompilerMessages._0_Expected_1_Element1s_In_Binding_List, Name, 3); if (!(dirObj is ZilAtom)) @@ -819,10 +802,10 @@ namespace Zilf.Compiler { readonly ZilAtom dirAtom, ptAtom; readonly ZilObject room; - ILocalBuilder counter; + ILocalBuilder? counter; - public Loop(BoundedLoopContext blc, [NotNull] ZilAtom dirAtom, [NotNull] ZilAtom ptAtom, - [NotNull] ZilObject room) + public Loop(BoundedLoopContext blc, ZilAtom dirAtom, ZilAtom ptAtom, + ZilObject room) : base(blc) { this.dirAtom = dirAtom; @@ -852,7 +835,7 @@ namespace Zilf.Compiler // get next prop table var propTable = cc.PushInnerLocal(rb, ptAtom, LocalBindingType.LoopState, src); var roomOperand = cc.CompileAsOperand(rb, room, src); - rb.EmitBinary(BinaryOp.GetPropAddress, roomOperand, counter, propTable); + rb.EmitBinary(BinaryOp.GetPropAddress, roomOperand, counter!, propTable); rb.BranchIfZero(propTable, againLabel, true); } diff --git a/src/Zilf/Compiler/Compilation.Objects.cs b/src/Zilf/Compiler/Compilation.Objects.cs index 7b33c0c..a5272c7 100644 --- a/src/Zilf/Compiler/Compilation.Objects.cs +++ b/src/Zilf/Compiler/Compilation.Objects.cs @@ -17,6 +17,8 @@ */ using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using JetBrains.Annotations; using Zilf.Diagnostics; @@ -33,7 +35,8 @@ namespace Zilf.Compiler partial class Compilation { [ContractAnnotation("null => null; notnull => notnull")] - IFlagBuilder GetFlag(ZilAtom flag) + [return: NotNullIfNotNull("flag")] + IFlagBuilder? GetFlag(ZilAtom? flag) { if (flag == null) return null; @@ -47,7 +50,7 @@ namespace Zilf.Compiler return Flags[flag]; } - void DefineProperty([NotNull] ZilAtom prop) + void DefineProperty(ZilAtom prop) { if (!Properties.ContainsKey(prop)) { @@ -62,7 +65,7 @@ namespace Zilf.Compiler } } - void DefineFlag([NotNull] ZilAtom flag) + void DefineFlag(ZilAtom flag) { if (!Flags.ContainsKey(flag)) { @@ -76,7 +79,7 @@ namespace Zilf.Compiler } } - void DefineFlagAlias([NotNull] ZilAtom alias, [NotNull] ZilAtom original) + void DefineFlagAlias(ZilAtom alias, ZilAtom original) { if (!Flags.ContainsKey(alias)) { @@ -110,8 +113,10 @@ namespace Zilf.Compiler /// whatever the handler returned. /// /// The object to examine. - void PreBuildObject([NotNull] ZilModelObject model) + void PreBuildObject(ZilModelObject model) { + // TODO: split up PreBuildObject method + var globalsByName = Context.ZEnvironment.Globals.ToDictionary(g => g.Name); var propertiesSoFar = new HashSet(); @@ -179,12 +184,12 @@ namespace Zilf.Compiler continue; } - ZilAtom uniquePropertyName; + ZilAtom? uniquePropertyName; // exclude phony built-in properties bool phony; bool? isSynonym = null; - Synonym synonym = null; + Synonym? synonym = null; /* We also detect direction properties here, which are tricky for a few reasons: * - They can be implicitly defined by a property spec that looks sufficiently direction-like. @@ -224,8 +229,9 @@ namespace Zilf.Compiler { isSynonym = false; Context.ZEnvironment.Directions.Add(atom); - Context.ZEnvironment.GetVocabDirection(atom, prop.SourceLine); - Context.SetPropDef(atom, directionPattern); + Context.ZEnvironment.GetVocabDirection(atom, prop.SourceLine ?? SourceLines.Unknown); + if (directionPattern != null) + Context.SetPropDef(atom, directionPattern); uniquePropertyName = atom; } else @@ -293,10 +299,12 @@ namespace Zilf.Compiler isSynonym = (synonym != null); } - if ((bool)isSynonym) + if (isSynonym.Value) { + Debug.Assert(synonym != null); + var origAtom = synonym.OriginalWord.Atom; - if (Properties.TryGetValue(origAtom, out var origPb) == false) + if (!Properties.TryGetValue(origAtom, out var origPb)) { DefineProperty(origAtom); origPb = Properties[origAtom]; @@ -334,7 +342,7 @@ namespace Zilf.Compiler var specOutput = (ZilObject)form.Eval(Context); if (specOutput is ZilListoidBase list && list.StdTypeAtom == StdAtom.LIST && - list.Rest is var customBody && !customBody.IsEmpty) + list.Rest is { IsEmpty: false } customBody) { // replace the property body with the propspec's output prop.Rest = customBody; @@ -356,7 +364,7 @@ namespace Zilf.Compiler { try { - Context.ZEnvironment.GetVocabNoun(word, prop.SourceLine); + Context.ZEnvironment.GetVocabNoun(word, prop.SourceLine ?? SourceLines.Unknown); } catch (ZilError ex) { @@ -370,7 +378,7 @@ namespace Zilf.Compiler { try { - Context.ZEnvironment.GetVocabAdjective(word, prop.SourceLine); + Context.ZEnvironment.GetVocabAdjective(word, prop.SourceLine ?? SourceLines.Unknown); } catch (ZilError ex) { @@ -384,7 +392,7 @@ namespace Zilf.Compiler { try { - Context.ZEnvironment.GetVocabNoun(ZilAtom.Parse(word.Text, Context), prop.SourceLine); + Context.ZEnvironment.GetVocabNoun(ZilAtom.Parse(word.Text, Context), prop.SourceLine ?? SourceLines.Unknown); } catch (ZilError ex) { @@ -425,7 +433,7 @@ namespace Zilf.Compiler /// definitions by calling PROPSPEC functions. What's left is compiling the constant values in /// those definitions and putting them in the object/property tables. /// - void BuildObject([NotNull] ZilModelObject model, [NotNull] IObjectBuilder ob) + void BuildObject(ZilModelObject model, IObjectBuilder ob) { var elementConverters = new ComplexPropDef.ElementConverters { @@ -487,6 +495,7 @@ namespace Zilf.Compiler { ITableBuilder tb; int length = 0; + var src = prop.SourceLine ?? SourceLines.Unknown; bool noSpecialCases = false; @@ -501,14 +510,14 @@ namespace Zilf.Compiler var value = propBody.First; var valueAtom = value as ZilAtom; if (propName.StdAtom == StdAtom.LOC || - propName.StdAtom == StdAtom.IN && ((IStructure)propBody).GetLength(1) == 1 && valueAtom != null) + (propName.StdAtom == StdAtom.IN && propBody.GetLength(1) == 1 && valueAtom != null)) { if (valueAtom == null) { Context.HandleError(new CompilerError(model, CompilerMessages.Values_For_0_Property_Must_Be_1, propName, "atoms")); continue; } - if (Objects.TryGetValue(valueAtom, out var parent) == false) + if (!Objects.TryGetValue(valueAtom, out var parent)) { Context.HandleError(new CompilerError( model, @@ -598,7 +607,7 @@ namespace Zilf.Compiler break; } - var word = Context.ZEnvironment.GetVocabNoun(atom, prop.SourceLine); + var word = Context.ZEnvironment.GetVocabNoun(atom, src); var wb = Vocabulary[word]; tb.AddShort(wb); length += 2; @@ -616,7 +625,7 @@ namespace Zilf.Compiler break; } - var word = Context.ZEnvironment.GetVocabAdjective(atom, prop.SourceLine); + var word = Context.ZEnvironment.GetVocabAdjective(atom, src); var wb = Vocabulary[word]; if (Context.ZEnvironment.ZVersion == 3) { @@ -638,13 +647,13 @@ namespace Zilf.Compiler { if (obj is ZilString str) { - var word = Context.ZEnvironment.GetVocabNoun(ZilAtom.Parse(str.Text, Context), prop.SourceLine); + var word = Context.ZEnvironment.GetVocabNoun(ZilAtom.Parse(str.Text, Context), src); var wb = Vocabulary[word]; tb.AddShort(wb); } else { - tb.AddShort(CompileConstant(obj)); + tb.AddShort(CompileConstant(obj)!); } length += 2; } @@ -663,7 +672,7 @@ namespace Zilf.Compiler break; } - if (Objects.TryGetValue(atom, out var ob2) == false) + if (!Objects.TryGetValue(atom, out var ob2)) { Context.HandleError(new CompilerError(model, CompilerMessages.No_Such_Object_0, atom)); break; @@ -681,7 +690,7 @@ namespace Zilf.Compiler { // nothing special, just one or more words var pb = Properties[propName]; - if (propBody.Rest.IsEmpty) + if (propBody.Rest?.IsEmpty != false) { var word = CompileConstant(value); if (word == null) @@ -721,16 +730,18 @@ namespace Zilf.Compiler // check property length if (length > Game.MaxPropertyLength) + { Context.HandleError(new CompilerError( prop, CompilerMessages.Property_0_Is_Too_Long_Max_1_Byte1s, propName.ToStringContext(Context, true), Game.MaxPropertyLength)); + } } //XXX debug line refs for objects if (WantDebugInfo) - Game.DebugFile.MarkObject(ob, new DebugLineRef(), new DebugLineRef()); + Game.DebugFile!.MarkObject(ob, new DebugLineRef(), new DebugLineRef()); } } } diff --git a/src/Zilf/Compiler/Compilation.Operands.cs b/src/Zilf/Compiler/Compilation.Operands.cs index 518d0da..6f4a8d2 100644 --- a/src/Zilf/Compiler/Compilation.Operands.cs +++ b/src/Zilf/Compiler/Compilation.Operands.cs @@ -29,8 +29,7 @@ namespace Zilf.Compiler partial class Compilation { /// Local variables are not allowed here, or an error occurred while compiling a subexpression. - [NotNull] - public IOperands CompileOperands([NotNull] IRoutineBuilder rb, [NotNull] ISourceLine src, [NotNull] params ZilObject[] exprs) + public IOperands CompileOperands(IRoutineBuilder rb, ISourceLine src, params ZilObject[] exprs) { int length = exprs.Length; var values = new IOperand[length]; @@ -119,7 +118,7 @@ namespace Zilf.Compiler } [System.Diagnostics.Contracts.Pure] - static bool LocalIsLaterModified([ItemNotNull] [NotNull] ZilObject[] exprs, int localIdx) + static bool LocalIsLaterModified(ZilObject[] exprs, int localIdx) { if (!(exprs[localIdx] is ZilForm form)) throw new ArgumentException("not a FORM"); @@ -142,7 +141,7 @@ namespace Zilf.Compiler return false; } - bool GlobalCouldBeLaterModified([ItemNotNull] [NotNull] ZilObject[] exprs, int localIdx) + bool GlobalCouldBeLaterModified(ZilObject[] exprs, int localIdx) { if (!(exprs[localIdx] is ZilForm form)) throw new ArgumentException("not a FORM"); @@ -165,7 +164,7 @@ namespace Zilf.Compiler return false; } - bool CouldModifyGlobal([NotNull] ZilObject expr, [NotNull] ZilAtom globalAtom) + bool CouldModifyGlobal(ZilObject expr, ZilAtom globalAtom) { if (!(expr is ZilListBase list)) return false; @@ -201,7 +200,7 @@ namespace Zilf.Compiler readonly bool[] temps; readonly ZilAtom tempAtom; - public Operands([NotNull] Compilation compilation, [NotNull] IOperand[] values, [NotNull] bool[] temps, [NotNull] ZilAtom tempAtom) + public Operands(Compilation compilation, IOperand[] values, bool[] temps, ZilAtom tempAtom) { this.compilation = compilation; this.values = values; @@ -224,7 +223,6 @@ namespace Zilf.Compiler public IOperand this[int index] => values[index]; - [NotNull] public IOperand[] AsArray() => values; } } diff --git a/src/Zilf/Compiler/Compilation.Routines.cs b/src/Zilf/Compiler/Compilation.Routines.cs index edef633..b0b2707 100644 --- a/src/Zilf/Compiler/Compilation.Routines.cs +++ b/src/Zilf/Compiler/Compilation.Routines.cs @@ -34,8 +34,7 @@ namespace Zilf.Compiler { partial class Compilation { - [NotNull] - static ZilRoutine MaybeRewriteRoutine([NotNull] Context ctx, [NotNull] ZilRoutine origRoutine) + static ZilRoutine MaybeRewriteRoutine(Context ctx, ZilRoutine origRoutine) { const string SExpectedResultType = "a list (with an arg spec and body) or FALSE"; @@ -71,7 +70,7 @@ namespace Zilf.Compiler OuterLocals.Clear(); } - void BuildRoutine([NotNull] ZilRoutine routine, [NotNull] IRoutineBuilder rb, bool entryPoint, bool traceRoutines) + void BuildRoutine(ZilRoutine routine, IRoutineBuilder rb, bool entryPoint, bool traceRoutines) { // give the user a chance to rewrite the routine routine = MaybeRewriteRoutine(Context, routine); @@ -204,7 +203,7 @@ namespace Zilf.Compiler if (lb.DefaultValue != null) return; - ILabel nextLabel = null; + ILabel? nextLabel = null; // ReSharper disable once SwitchStatementMissingSomeCases switch (arg.Type) @@ -251,7 +250,7 @@ namespace Zilf.Compiler } // TODO: replace CompileStmt with CompileForm and (in loops) CompileClauseBody - void CompileStmt([NotNull] IRoutineBuilder rb, [NotNull] ZilObject stmt, bool wantResult) + void CompileStmt(IRoutineBuilder rb, ZilObject stmt, bool wantResult) { stmt = stmt.Unwrap(Context); @@ -263,7 +262,7 @@ namespace Zilf.Compiler var result = CompileForm(rb, form, wantResult, null); if (wantResult) - rb.Return(result); + rb.Return(result!); break; case ZilList _: @@ -293,7 +292,7 @@ namespace Zilf.Compiler } } - void MarkSequencePoint([NotNull] IRoutineBuilder rb, [NotNull] IProvideSourceLine node) + void MarkSequencePoint(IRoutineBuilder rb, IProvideSourceLine node) { if (!WantDebugInfo || !(node.SourceLine is FileSourceLine fileSourceLine)) return; @@ -304,22 +303,22 @@ namespace Zilf.Compiler } /// - /// + /// Creates a new binding for a local variable, saving the old one on a stack if needed. /// /// /// /// /// /// + /// /// Local variables are not allowed here. - [NotNull] - public ILocalBuilder PushInnerLocal([NotNull] IRoutineBuilder rb, [NotNull] ZilAtom atom, + public ILocalBuilder PushInnerLocal(IRoutineBuilder rb, ZilAtom atom, LocalBindingType reason, ISourceLine src) { if (Locals.TryGetValue(atom, out var prev)) { // save the old binding - if (OuterLocals.TryGetValue(atom, out var stk) == false) + if (!OuterLocals.TryGetValue(atom, out var stk)) { stk = new Stack(); OuterLocals.Add(atom, stk); @@ -356,8 +355,7 @@ namespace Zilf.Compiler return result; } - [NotNull] - ZilAtom MakeUniqueVariableName([NotNull] ZilAtom atom) + ZilAtom MakeUniqueVariableName(ZilAtom atom) { if (!VariableNameInUse(atom)) return atom; @@ -374,14 +372,14 @@ namespace Zilf.Compiler return newAtom; } - bool VariableNameInUse([NotNull] ZilAtom atom) + bool VariableNameInUse(ZilAtom atom) { return Locals.ContainsKey(atom) || TempLocalNames.Contains(atom) || Globals.ContainsKey(atom) || SoftGlobals.ContainsKey(atom) || Constants.ContainsKey(atom) || Objects.ContainsKey(atom) || Routines.ContainsKey(atom); } - public void PopInnerLocal([NotNull] ZilAtom atom) + public void PopInnerLocal(ZilAtom atom) { SpareLocals.Push(Locals[atom].LocalBuilder); @@ -392,7 +390,9 @@ namespace Zilf.Compiler OuterLocals.Remove(atom); } else + { Locals.Remove(atom); + } } void FindAndMarkVariable(IVariable var, Action markAction) @@ -404,19 +404,19 @@ namespace Zilf.Compiler markAction(lbr); } - public void MarkVariableAsRead([NotNull] LocalBindingRecord lbr) => + public static void MarkVariableAsRead(LocalBindingRecord lbr) => lbr.IsEverRead = true; public void MarkVariableAsRead(IVariable var) => FindAndMarkVariable(var, MarkVariableAsRead); - public void MarkVariableAsWritten([NotNull] LocalBindingRecord lbr) => + public static void MarkVariableAsWritten(LocalBindingRecord lbr) => lbr.IsEverWritten = true; public void MarkVariableAsWritten(IVariable var) => FindAndMarkVariable(var, MarkVariableAsWritten); - public void MarkVariableAsReadAndWritten([NotNull] LocalBindingRecord lbr) => + public static void MarkVariableAsReadAndWritten(LocalBindingRecord lbr) => lbr.IsEverRead = lbr.IsEverWritten = true; public void MarkVariableAsReadAndWritten(IVariable var) => diff --git a/src/Zilf/Compiler/Compilation.Strings.cs b/src/Zilf/Compiler/Compilation.Strings.cs index 5cdfbf5..ae81e65 100644 --- a/src/Zilf/Compiler/Compilation.Strings.cs +++ b/src/Zilf/Compiler/Compilation.Strings.cs @@ -45,8 +45,7 @@ namespace Zilf.Compiler CollapseWithSentenceSpace, } - [NotNull] - public static string TranslateString([NotNull] ZilString zstr, [NotNull] Context ctx) + public static string TranslateString(ZilString zstr, Context ctx) { var crlfChar = ctx.GetGlobalVal(ctx.GetStdAtom(StdAtom.CRLF_CHARACTER)) as ZilChar; return TranslateString( @@ -57,7 +56,7 @@ namespace Zilf.Compiler } [SuppressMessage("ReSharper", "ConvertIfStatementToReturnStatement")] - static StringSpacesMode GetSpacesMode([NotNull] Context ctx) + static StringSpacesMode GetSpacesMode(Context ctx) { if (ctx.GetGlobalOption(StdAtom.PRESERVE_SPACES_P)) return StringSpacesMode.Preserve; @@ -70,8 +69,7 @@ namespace Zilf.Compiler const char SentenceSpaceChar = '\u000b'; - [NotNull] - static string TranslateString([NotNull] ZilString zstr, [NotNull] Context ctx, char crlfChar, StringSpacesMode spacesMode) + static string TranslateString(ZilString zstr, Context ctx, char crlfChar, StringSpacesMode spacesMode) { // strip CR/LF and ensure 1 space afterward, translate crlfChar to LF, // and collapse two spaces after '.' or crlfChar into one @@ -81,25 +79,18 @@ namespace Zilf.Compiler var zversion = ctx.ZEnvironment.ZVersion; - string DescribeChar(byte zscii) + static string? DescribeChar(byte zscii) { - switch (zscii) + return zscii switch { - case 8: - return "backspace"; - case 9: - return "tab"; - case 11: - return "sentence space"; - case 27: - return "escape"; - case var _ when zscii < 32: - return "^" + (char)(zscii + 64); - case var _ when zscii < 127: - return "'" + (char)zscii + "'"; - default: - return null; - } + 8 => "backspace", + 9 => "tab", + 11 => "sentence space", + 27 => "escape", + _ when zscii < 32 => ("^" + (char)(zscii + 64)), + _ when zscii < 127 => ("'" + (char)zscii + "'"), + _ => null + }; } for (int i = 0; i < sb.Length; i++) @@ -112,7 +103,7 @@ namespace Zilf.Compiler var warning = new CompilerError(zstr, CompilerMessages.ZSCII_0_1_Cannot_Be_Safely_Printed_In_Zmachine_Version_2, b, - DescribeChar(b), + DescribeChar(b) ?? "", zversion); ctx.HandleError(warning); diff --git a/src/Zilf/Compiler/Compilation.Syntax.cs b/src/Zilf/Compiler/Compilation.Syntax.cs index cc19660..fd5b316 100644 --- a/src/Zilf/Compiler/Compilation.Syntax.cs +++ b/src/Zilf/Compiler/Compilation.Syntax.cs @@ -45,7 +45,7 @@ namespace Zilf.Compiler Constants.Add(Context.RootObList[pair.Key], pair.Value); } - void BuildOldFormatSyntaxTables([NotNull] IDictionary tables) + void BuildOldFormatSyntaxTables(IDictionary tables) { // TODO: emit VTBL as the first impure table, followed by syntax lines, which is what ztools expects? var verbTable = Game.DefineTable("VTBL", true); @@ -86,7 +86,7 @@ namespace Zilf.Compiler foreach (var line in verb.Reverse()) { - if (actions.TryGetValue(line.ActionName, out var act) == false) + if (!actions.TryGetValue(line.ActionName, out var act)) { // this can happen if an exception (e.g. undefined action routine) stops us from adding the action during the first pass. continue; @@ -111,7 +111,7 @@ namespace Zilf.Compiler if (line.NumObjects > 0) { - stbl.AddByte((IOperand)GetFlag(line.FindFlag1) ?? Game.Zero); + stbl.AddByte((IOperand?)GetFlag(line.FindFlag1) ?? Game.Zero); stbl.AddByte(line.Options1); if (line.NumObjects > 1) @@ -126,7 +126,7 @@ namespace Zilf.Compiler stbl.AddByte(0); } - stbl.AddByte((IOperand)GetFlag(line.FindFlag2) ?? Game.Zero); + stbl.AddByte((IOperand?)GetFlag(line.FindFlag2) ?? Game.Zero); stbl.AddByte(line.Options2); } } @@ -136,8 +136,8 @@ namespace Zilf.Compiler stbl.AddByte((byte)line.NumObjects); stbl.AddByte(GetPreposition(line.Preposition1) ?? Game.Zero); stbl.AddByte(GetPreposition(line.Preposition2) ?? Game.Zero); - stbl.AddByte((IOperand)GetFlag(line.FindFlag1) ?? Game.Zero); - stbl.AddByte((IOperand)GetFlag(line.FindFlag2) ?? Game.Zero); + stbl.AddByte((IOperand?)GetFlag(line.FindFlag1) ?? Game.Zero); + stbl.AddByte((IOperand?)GetFlag(line.FindFlag2) ?? Game.Zero); stbl.AddByte(line.Options1); stbl.AddByte(line.Options2); stbl.AddByte(act.Constant); @@ -158,11 +158,11 @@ namespace Zilf.Compiler foreach (var act in actquery) { actionTable.AddShort(act.Routine); - preactionTable.AddShort((IOperand)act.PreRoutine ?? Game.Zero); + preactionTable.AddShort((IOperand?)act.PreRoutine ?? Game.Zero); } } - void BuildNewFormatSyntaxTables([NotNull] IDictionary tables) + void BuildNewFormatSyntaxTables(IDictionary tables) { var actionTable = Game.DefineTable("ATBL", true); var preactionTable = Game.DefineTable("PATBL", true); @@ -217,7 +217,7 @@ namespace Zilf.Compiler utbl.AddShort(act?.Constant ?? Game.Zero); utbl.AddShort(line.Preposition1 == null ? (IOperand)Game.Zero : Vocabulary[line.Preposition1]); - utbl.AddByte((IOperand)GetFlag(line.FindFlag1) ?? Game.Zero); + utbl.AddByte((IOperand?)GetFlag(line.FindFlag1) ?? Game.Zero); utbl.AddByte(line.Options1); } @@ -240,11 +240,11 @@ namespace Zilf.Compiler btbl.AddShort(act?.Constant ?? Game.Zero); btbl.AddShort(line.Preposition1 == null ? (IOperand)Game.Zero : Vocabulary[line.Preposition1]); - btbl.AddByte((IOperand)GetFlag(line.FindFlag1) ?? Game.Zero); + btbl.AddByte((IOperand?)GetFlag(line.FindFlag1) ?? Game.Zero); btbl.AddByte(line.Options1); btbl.AddShort(line.Preposition2 == null ? (IOperand)Game.Zero : Vocabulary[line.Preposition2]); - btbl.AddByte((IOperand)GetFlag(line.FindFlag2) ?? Game.Zero); + btbl.AddByte((IOperand?)GetFlag(line.FindFlag2) ?? Game.Zero); btbl.AddByte(line.Options2); } @@ -263,7 +263,7 @@ namespace Zilf.Compiler foreach (var act in actquery) { actionTable.AddShort(act.Routine); - preactionTable.AddShort((IOperand)act.PreRoutine ?? Game.Zero); + preactionTable.AddShort((IOperand?)act.PreRoutine ?? Game.Zero); } } @@ -279,21 +279,20 @@ namespace Zilf.Compiler Context.ZEnvironment.VocabFormat.BuildLateSyntaxTables(helpers); } - [CanBeNull] - Action ValidateAction([NotNull] Dictionary actions, [NotNull] Syntax line) + Action? ValidateAction(Dictionary actions, Syntax line) { try { using (DiagnosticContext.Push(line.SourceLine)) { - if (actions.TryGetValue(line.ActionName, out var act) == false) + if (!actions.TryGetValue(line.ActionName, out var act)) { - if (Routines.TryGetValue(line.Action, out var routine) == false) + if (!Routines.TryGetValue(line.Action, out var routine)) throw new CompilerError(CompilerMessages.Undefined_0_1, "action routine", line.Action); - IRoutineBuilder preRoutine = null; + IRoutineBuilder? preRoutine = null; if (line.Preaction != null && - Routines.TryGetValue(line.Preaction, out preRoutine) == false) + !Routines.TryGetValue(line.Preaction, out preRoutine)) throw new CompilerError(CompilerMessages.Undefined_0_1, "preaction routine", line.Preaction); var actionName = line.ActionName; @@ -333,15 +332,17 @@ namespace Zilf.Compiler } } - void WarnIfActionRoutineDiffers([NotNull] Syntax line, [NotNull] string description, - [CanBeNull] ZilAtom thisRoutineName, [CanBeNull] ZilAtom lastRoutineName) + void WarnIfActionRoutineDiffers(Syntax line, string description, + ZilAtom? thisRoutineName, ZilAtom? lastRoutineName) { if (thisRoutineName != lastRoutineName) + { Context.HandleError(new CompilerError(line.SourceLine, CompilerMessages._0_Mismatch_For_1_Using_2_As_Before, description, line.ActionName, lastRoutineName?.ToString() ?? "no " + description)); + } } /// @@ -350,14 +351,14 @@ namespace Zilf.Compiler /// /// The Word. /// - void DefineWord([NotNull] IWord word) + void DefineWord(IWord word) { string rawWord = word.Atom.Text; if (!Vocabulary.ContainsKey(word)) { var wAtom = ZilAtom.Parse("W?" + rawWord, Context); - if (Constants.TryGetValue(wAtom, out var constantValue) == false) + if (!Constants.TryGetValue(wAtom, out var constantValue)) { var wb = Game.DefineVocabularyWord(rawWord); Vocabulary.Add(word, wb); @@ -386,9 +387,8 @@ namespace Zilf.Compiler } } - [CanBeNull] [ContractAnnotation("notnull => notnull")] - IOperand GetPreposition([CanBeNull] IWord word) + IOperand? GetPreposition(IWord? word) { if (word == null) return null; diff --git a/src/Zilf/Compiler/Compilation.Tables.cs b/src/Zilf/Compiler/Compilation.Tables.cs index fa5ec79..dbd57a5 100644 --- a/src/Zilf/Compiler/Compilation.Tables.cs +++ b/src/Zilf/Compiler/Compilation.Tables.cs @@ -52,18 +52,17 @@ namespace Zilf.Compiler struct TableElementOperand { - [NotNull] public readonly IOperand Operand; public readonly bool? IsWord; - public TableElementOperand([NotNull] IOperand operand, bool? isWord) + public TableElementOperand(IOperand operand, bool? isWord) { Operand = operand; IsWord = isWord; } } - void BuildTable([NotNull] ZilTable zt, [NotNull] ITableBuilder tb) + void BuildTable(ZilTable zt, ITableBuilder tb) { if ((zt.Flags & TableFlags.Lexv) != 0) { @@ -104,18 +103,18 @@ namespace Zilf.Compiler for (int i = 0; i < values.Length; i++) { - if (values[i] == null) - { - var rawElements = new ZilObject[zt.ElementCount]; - zt.CopyTo(rawElements, (zo, isWord) => zo, null, Context); - Context.HandleError(new CompilerError( - zt.SourceLine, - CompilerMessages.Nonconstant_Initializer_For_0_1_2, - "table element", - i, - rawElements[i])); - values[i] = defaultFiller; - } + if (values[i] != null) + continue; + + var rawElements = new ZilObject?[zt.ElementCount]; + zt.CopyTo(rawElements, (zo, isWord) => zo, null, Context); + Context.HandleError(new CompilerError( + zt.SourceLine, + CompilerMessages.Nonconstant_Initializer_For_0_1_2, + "table element", + i, + rawElements[i]?.ToString() ?? "")); + values[i] = defaultFiller; } bool defaultWord = (zt.Flags & TableFlags.Byte) == 0; @@ -124,13 +123,13 @@ namespace Zilf.Compiler { Debug.Assert(values[i] != null); - if (values[i].Value.IsWord ?? defaultWord) + if (values[i]!.Value.IsWord ?? defaultWord) { - tb.AddShort(values[i].Value.Operand); + tb.AddShort(values[i]!.Value.Operand); } else { - tb.AddByte(values[i].Value.Operand); + tb.AddByte(values[i]!.Value.Operand); } } } diff --git a/src/Zilf/Compiler/Compilation.cs b/src/Zilf/Compiler/Compilation.cs index a3c772e..cb88289 100644 --- a/src/Zilf/Compiler/Compilation.cs +++ b/src/Zilf/Compiler/Compilation.cs @@ -27,18 +27,16 @@ using Zilf.ZModel.Vocab; namespace Zilf.Compiler { - partial class Compilation + sealed partial class Compilation { /// /// The ZIL context that resulted from loading the source code. /// [ProvidesContext] - [NotNull] public Context Context { get; } /// /// The game being built. /// - [NotNull] public IGameBuilder Game { get; } /// /// True if debug information should be generated (i.e. if the user @@ -46,7 +44,7 @@ namespace Zilf.Compiler /// public bool WantDebugInfo { get; } - Compilation([NotNull] Context ctx, [NotNull] IGameBuilder game, bool wantDebugInfo) + Compilation(Context ctx, IGameBuilder game, bool wantDebugInfo) { Context = ctx; Game = game; @@ -64,41 +62,25 @@ namespace Zilf.Compiler } // TODO: helper class for managing local variables - [NotNull] public readonly Dictionary Locals = new Dictionary(); - [NotNull] public readonly List AllLocalBindingRecords = new List(); - [NotNull] public readonly HashSet TempLocalNames = new HashSet(); - [NotNull] public readonly Stack SpareLocals = new Stack(); - [NotNull] public readonly Dictionary> OuterLocals = new Dictionary>(); - [NotNull] public readonly Stack Blocks = new Stack(); - [NotNull] public readonly Dictionary Globals; - [NotNull] public readonly Dictionary Constants; - [NotNull] public readonly Dictionary Routines; - [NotNull] public readonly Dictionary Objects; - [NotNull] public readonly Dictionary Tables = new Dictionary(); - [NotNull] public readonly Dictionary Vocabulary = new Dictionary(); - [NotNull] public readonly Dictionary Properties; - [NotNull] public readonly Dictionary Flags; - [NotNull] public readonly Dictionary SoftGlobals; - [CanBeNull] - public IOperand SoftGlobalsTable; + public IOperand? SoftGlobalsTable; public int UniqueFlags { get; set; } } diff --git a/src/Zilf/Compiler/CompilationExtensions.cs b/src/Zilf/Compiler/CompilationExtensions.cs index fb9bcdb..4b71be0 100644 --- a/src/Zilf/Compiler/CompilationExtensions.cs +++ b/src/Zilf/Compiler/CompilationExtensions.cs @@ -46,7 +46,7 @@ namespace Zilf.Compiler } } - public static void WalkRoutineForms([NotNull] this ZilRoutine routine, [NotNull] Action action) + public static void WalkRoutineForms(this ZilRoutine routine, Action action) { var children = routine.ArgSpec.Select(ai => ai.DefaultValue) @@ -75,7 +75,7 @@ namespace Zilf.Compiler first.StdAtom != StdAtom.GVAL && first.StdAtom != StdAtom.LVAL; } - public static bool IsVariableRef([NotNull] this ZilObject expr) + public static bool IsVariableRef(this ZilObject expr) { if (expr is ZilForm form && form.First is ZilAtom atom && @@ -94,7 +94,7 @@ namespace Zilf.Compiler return false; } - public static bool IsLocalVariableRef([NotNull] this ZilObject expr) + public static bool IsLocalVariableRef(this ZilObject expr) { return expr is ZilForm form && form.First is ZilAtom atom && @@ -102,7 +102,7 @@ namespace Zilf.Compiler (atom.StdAtom == StdAtom.LVAL || atom.StdAtom == StdAtom.SET); } - public static bool IsGlobalVariableRef([NotNull] this ZilObject expr) + public static bool IsGlobalVariableRef(this ZilObject expr) { return expr is ZilForm form && form.First is ZilAtom atom && @@ -110,7 +110,7 @@ namespace Zilf.Compiler (atom.StdAtom == StdAtom.GVAL || atom.StdAtom == StdAtom.SETG); } - public static bool ModifiesLocal([NotNull] this ZilObject expr, [NotNull] ZilAtom localAtom) + public static bool ModifiesLocal(this ZilObject expr, ZilAtom localAtom) { if (!(expr is ZilListBase list)) return false; @@ -126,7 +126,7 @@ namespace Zilf.Compiler return list.Any(zo => ModifiesLocal(zo, localAtom)); } - public static bool IsPredicate([NotNull] this ZilObject zo, int zversion) + public static bool IsPredicate(this ZilObject zo, int zversion) { if (!(zo is ZilForm form) || !(form.First is ZilAtom head)) return false; @@ -152,8 +152,7 @@ namespace Zilf.Compiler /// The expression. /// The context. /// The unwrapped expression. If macro expansion resulted in a SPLICE, this will be a call to BIND. - [NotNull] - public static ZilObject Unwrap([NotNull] this ZilObject zo, [NotNull] Context ctx) + public static ZilObject Unwrap(this ZilObject zo, Context ctx) { var src = zo.SourceLine; @@ -192,8 +191,7 @@ namespace Zilf.Compiler } } - [ItemNotNull] - static IEnumerable ReconstructSequence([NotNull] T first, [NotNull] IEnumerator enumerator) + static IEnumerable ReconstructSequence(T first, IEnumerator enumerator) { yield return first; @@ -205,11 +203,9 @@ namespace Zilf.Compiler } while (enumerator.MoveNext()); } - [NotNull] - public delegate T SequenceCombiner([ItemNotNull] [NotNull] IEnumerable sequence); + public delegate T SequenceCombiner(IEnumerable sequence); - [NotNull] - public static T FirstOrCombine([ItemNotNull] [NotNull] this IEnumerable sequence, [NotNull] SequenceCombiner combiner) + public static T FirstOrCombine(this IEnumerable sequence, SequenceCombiner combiner) { using (var tor = sequence.GetEnumerator()) { diff --git a/src/Zilf/Compiler/FrontEnd.cs b/src/Zilf/Compiler/FrontEnd.cs index b93e77d..0981a25 100644 --- a/src/Zilf/Compiler/FrontEnd.cs +++ b/src/Zilf/Compiler/FrontEnd.cs @@ -38,7 +38,7 @@ namespace Zilf.Compiler public string FileName { get; } public bool Writing { get; } - public Stream Stream { get; set; } + public Stream? Stream { get; set; } } public class CheckingFilePresenceEventArgs : EventArgs @@ -79,13 +79,12 @@ namespace Zilf.Compiler IncludePaths = new List(); } - public event EventHandler OpeningFile; - public event EventHandler CheckingFilePresence; - internal event EventHandler InitializeContext; + public event EventHandler? OpeningFile; + public event EventHandler? CheckingFilePresence; + internal event EventHandler? InitializeContext; public IList IncludePaths { get; } - [NotNull] Stream OpenFile(string path, bool writing) { var handler = OpeningFile; @@ -105,7 +104,7 @@ namespace Zilf.Compiler writing ? FileAccess.Write : FileAccess.Read); } - bool CheckFileExists([NotNull] string path) + bool CheckFileExists(string path) { if (path == null) throw new ArgumentNullException(nameof(path)); @@ -126,19 +125,14 @@ namespace Zilf.Compiler class ZapStreamFactory : IZapStreamFactory { - [NotNull] readonly FrontEnd owner; - [NotNull] readonly string mainFile; - [NotNull] readonly string fwordsFile; - [NotNull] readonly string dataFile; - [NotNull] readonly string stringFile; const string FrequentWordsSuffix1 = "_freq"; @@ -147,7 +141,7 @@ namespace Zilf.Compiler const string StringSuffix = "_str"; /// mainFile is not a file name. - public ZapStreamFactory([NotNull] FrontEnd owner, [NotNull] string mainFile) + public ZapStreamFactory(FrontEnd owner, string mainFile) { this.owner = owner; this.mainFile = mainFile; @@ -173,7 +167,7 @@ namespace Zilf.Compiler Try(FrequentWordsSuffix2, @".xzap", out _) ?? defaultPath; - string Try(string suffix, string myExt, out string path) + string? Try(string suffix, string myExt, out string path) { path = Path.Combine(dir, baseName + suffix + myExt); return owner.CheckFileExists(path) ? path : null; @@ -219,7 +213,6 @@ namespace Zilf.Compiler #endregion } - [NotNull] Context NewContext(RunMode runMode, bool wantDebugInfo) { var result = new Context { RunMode = runMode, WantDebugInfo = wantDebugInfo }; @@ -229,27 +222,27 @@ namespace Zilf.Compiler return result; } - internal FrontEndResult Interpret([NotNull] Context ctx, [NotNull] string inputFileName) + internal FrontEndResult Interpret(Context ctx, string inputFileName) { var f = InterpretOrCompile(ctx, inputFileName, null, false, false); return f; } - public FrontEndResult Compile([NotNull] string inputFileName, [NotNull] string outputFileName, bool wantDebugInfo = false) + public FrontEndResult Compile(string inputFileName, string outputFileName, bool wantDebugInfo = false) { var ctx = NewContext(RunMode.Compiler, wantDebugInfo); return Compile(ctx, inputFileName, outputFileName, ctx.WantDebugInfo); } - internal FrontEndResult Compile([NotNull] Context ctx, [NotNull] string inputFileName, - [NotNull] string outputFileName, bool wantDebugInfo = false) => + internal FrontEndResult Compile(Context ctx, string inputFileName, + string outputFileName, bool wantDebugInfo = false) => InterpretOrCompile(ctx, inputFileName, outputFileName, true, wantDebugInfo); // FIXME: not supported by R#, sadly... //[ContractAnnotation("wantCompile: true => outputFileName: notnull")] //[ContractAnnotation("wantCompile: false => outputFileName: null")] - FrontEndResult InterpretOrCompile([NotNull] [ProvidesContext] Context ctx, [NotNull] string inputFileName, - [CanBeNull] string outputFileName, bool wantCompile, bool wantDebugInfo) + FrontEndResult InterpretOrCompile([ProvidesContext] Context ctx, string inputFileName, + string? outputFileName, bool wantCompile, bool wantDebugInfo) { var result = new FrontEndResult(); @@ -276,6 +269,8 @@ namespace Zilf.Compiler // compile, if there were no evaluation errors if (wantCompile && ctx.ErrorCount == 0) { + Debug.Assert(outputFileName != null); + ctx.RunHook("PRE-COMPILE"); ctx.SetDefaultConstants(); @@ -285,10 +280,8 @@ namespace Zilf.Compiler var streamFactory = new ZapStreamFactory(this, outputFileName); var options = MakeGameOptions(ctx); - using (var gameBuilder = new GameBuilder(zversion, streamFactory, wantDebugInfo, options)) - { - Compilation.Compile(ctx, gameBuilder); - } + using var gameBuilder = new GameBuilder(zversion, streamFactory, wantDebugInfo, options); + Compilation.Compile(ctx, gameBuilder); } catch (ZilErrorBase ex) // catch fatals too { @@ -306,8 +299,7 @@ namespace Zilf.Compiler } } - [NotNull] - static GameOptions MakeGameOptions([NotNull] Context ctx) + static GameOptions MakeGameOptions(Context ctx) { var zenv = ctx.ZEnvironment; @@ -339,7 +331,7 @@ namespace Zilf.Compiler V5Plus: var defaultLang = ZModel.Language.Default; - + var doCharset = zenv.Charset0 != defaultLang.Charset0 || zenv.Charset1 != defaultLang.Charset1 || diff --git a/src/Zilf/Compiler/LocalBindingRecord.cs b/src/Zilf/Compiler/LocalBindingRecord.cs index 4535a42..1661c9c 100644 --- a/src/Zilf/Compiler/LocalBindingRecord.cs +++ b/src/Zilf/Compiler/LocalBindingRecord.cs @@ -72,24 +72,22 @@ namespace Zilf.Compiler sealed class LocalBindingRecord { public LocalBindingType Type { get; } - [NotNull] public ILocalBuilder LocalBuilder { get; } - [NotNull] public string BoundName { get; } - [NotNull] - public ISourceLine Definition { get; } + public ISourceLine? Definition { get; } /// /// Gets or sets a flag indicating whether the local variable was used as an operand. /// public bool IsEverRead { get; set; } + /// /// Gets or sets a flag indicating whether a value was assigned to the local variable. /// public bool IsEverWritten { get; set; } - public LocalBindingRecord(LocalBindingType type, [NotNull] ISourceLine definition, [NotNull] string boundName, - [NotNull] ILocalBuilder storage) + public LocalBindingRecord(LocalBindingType type, ISourceLine? definition, string boundName, + ILocalBuilder storage) { Type = type; Definition = definition; diff --git a/src/Zilf/Compiler/VariableRef.cs b/src/Zilf/Compiler/VariableRef.cs index a0500e9..8bb1053 100644 --- a/src/Zilf/Compiler/VariableRef.cs +++ b/src/Zilf/Compiler/VariableRef.cs @@ -23,18 +23,16 @@ namespace Zilf.Compiler { struct VariableRef { - [CanBeNull] - public readonly IVariable Hard; - [CanBeNull] - public readonly SoftGlobal Soft; + public readonly IVariable? Hard; + public readonly SoftGlobal? Soft; - public VariableRef([NotNull] IVariable hard) + public VariableRef(IVariable hard) { Hard = hard; Soft = null; } - public VariableRef([NotNull] SoftGlobal soft) + public VariableRef(SoftGlobal soft) { Soft = soft; Hard = null; diff --git a/src/Zilf/Completer.cs b/src/Zilf/Completer.cs index 19905d7..7ad338a 100644 --- a/src/Zilf/Completer.cs +++ b/src/Zilf/Completer.cs @@ -10,17 +10,15 @@ namespace Zilf { class Completer : IAutoCompleteHandler, IDisposable { - [NotNull] readonly Context ctx; bool attached; - public Completer([NotNull] Context ctx) + public Completer(Context ctx) { this.ctx = ctx; } - [NotNull] public Completer Attach() { ReadLine.AutoCompletionHandler = this; @@ -39,8 +37,7 @@ namespace Zilf public char[] Separators { get; set; } = { '<', '>', '[', ']', '(', ')', '{', '}', ':', ',', '.', '#', }; - [NotNull, ItemNotNull] - public string[] GetSuggestions([NotNull] string text, int pos) + public string[] GetSuggestions(string text, int pos) { // find a completable expression var (start, end) = FindExpression(text, pos); @@ -76,11 +73,10 @@ namespace Zilf string prefix; if (start >= 0 && end <= text.Length && start <= end) - prefix = text.Substring(start, end - start); + prefix = text[start..end]; else prefix = ""; - return completions .Where(c => c.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) .ToArray(); @@ -88,7 +84,7 @@ namespace Zilf private readonly char[] delimiters = { '"', '<', '>', '(', ')', '[', ']', ';', ',', '.' }; - private (int start, int end) FindExpression([NotNull] string text, int pos) + private (int start, int end) FindExpression(string text, int pos) { var start = text.LastIndexOfAny(delimiters, Math.Min(pos, text.Length - 1)); @@ -103,7 +99,6 @@ namespace Zilf return (start, end); } - [NotNull, ItemNotNull] private IEnumerable GetLvalNames() { return from a in ctx.LocalEnvironment.GetVisibleAtoms() @@ -111,23 +106,21 @@ namespace Zilf select a.Text; } - [NotNull, ItemNotNull] private IEnumerable GetGvalNames() { return GetGlobalNames((name, zo) => (IsFunction(zo) ? 2 : 0) + - (name.Contains("!-") ? 1 : 0)); + (name.Contains("!-", StringComparison.Ordinal) ? 1 : 0)); } - [NotNull, ItemNotNull] private IEnumerable GetFunctionNames() { return GetGlobalNames((name, zo) => IsFunction(zo) - ? (name.Contains("!-") ? 1 : 0) + ? (name.Contains("!-", StringComparison.Ordinal) ? 1 : 0) : (int?)null); } - static bool IsFunction([NotNull] ZilObject zo) + static bool IsFunction(ZilObject zo) { switch (zo.StdTypeAtom) { @@ -143,16 +136,14 @@ namespace Zilf } } - [NotNull, ItemNotNull, LinqTunnel] - IEnumerable GetGlobalNames([NotNull] Func grouper) - { - return from b in ctx.GetGlobalBindings() - where b.Value.Value != null - let name = b.Key.ToStringContext(ctx, false, true) - let groupNum = grouper(name, b.Value.Value) - where groupNum != null - orderby groupNum, name - select name; - } + [LinqTunnel] + IEnumerable GetGlobalNames(Func grouper) => + from b in ctx.GetGlobalBindings() + where b.Value.Value != null + let name = b.Key.ToStringContext(ctx, false, true) + let groupNum = grouper(name, b.Value.Value!) + where groupNum != null + orderby groupNum, name + select name; } } \ No newline at end of file diff --git a/src/Zilf/Diagnostics/ArgCountHelpers.cs b/src/Zilf/Diagnostics/ArgCountHelpers.cs index d2e79b1..f6884bb 100644 --- a/src/Zilf/Diagnostics/ArgCountHelpers.cs +++ b/src/Zilf/Diagnostics/ArgCountHelpers.cs @@ -29,7 +29,7 @@ namespace Zilf.Diagnostics public readonly string Text; public readonly bool Plural; - public CountableString([NotNull] string text, bool plural) + public CountableString(string text, bool plural) { Text = text; Plural = plural; @@ -43,8 +43,8 @@ namespace Zilf.Diagnostics static class ArgCountHelpers { - public static IEnumerable Collapse([NotNull] IEnumerable sequence, - [NotNull] Func match, [NotNull] Func combine) + public static IEnumerable Collapse(IEnumerable sequence, + Func match, Func combine) { //Contract.Ensures(Contract.Result>() != null); @@ -74,8 +74,7 @@ namespace Zilf.Diagnostics } } - [NotNull] - static string EnglishJoin([NotNull] IEnumerable sequence, [NotNull] string conjunction) + static string EnglishJoin(IEnumerable sequence, string conjunction) { var items = sequence.ToArray(); @@ -94,15 +93,14 @@ namespace Zilf.Diagnostics } } - [NotNull] - public static string FormatArgCount([NotNull] IEnumerable ranges) + public static string FormatArgCount(IEnumerable ranges) { FormatArgCount(ranges, out var cs); return string.Format(CultureInfo.CurrentCulture, "{0} argument{1}", cs.Text, cs.Plural ? "s" : ""); } /// No ranges provided - public static void FormatArgCount([NotNull] IEnumerable ranges, out CountableString result) + public static void FormatArgCount(IEnumerable ranges, out CountableString result) { var allCounts = new List(); bool uncapped = false; diff --git a/src/Zilf/Diagnostics/DefaultDiagnosticFormatter.cs b/src/Zilf/Diagnostics/DefaultDiagnosticFormatter.cs index adba620..71c5eea 100644 --- a/src/Zilf/Diagnostics/DefaultDiagnosticFormatter.cs +++ b/src/Zilf/Diagnostics/DefaultDiagnosticFormatter.cs @@ -23,6 +23,7 @@ namespace Zilf.Diagnostics public class DefaultDiagnosticFormatter : IDiagnosticFormatter { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1308:Normalize strings to uppercase", Justification = "Not normalizing.")] public string Format(Diagnostic diagnostic) { var sb = new StringBuilder(80); diff --git a/src/Zilf/Diagnostics/Diagnostic.cs b/src/Zilf/Diagnostics/Diagnostic.cs index a888809..c558dee 100644 --- a/src/Zilf/Diagnostics/Diagnostic.cs +++ b/src/Zilf/Diagnostics/Diagnostic.cs @@ -21,7 +21,6 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Reflection; using Zilf.Language; -using JetBrains.Annotations; namespace Zilf.Diagnostics { @@ -35,37 +34,29 @@ namespace Zilf.Diagnostics public sealed class Diagnostic { - [NotNull] public ISourceLine Location { get; } public Severity Severity { get; } - [NotNull] public string CodePrefix { get; } public int CodeNumber { get; } public bool Noisy { get; } - [NotNull] - public static string FormatCode([NotNull] string prefix, int number) => $"{prefix}{number:0000}"; + public static string FormatCode(string prefix, int number) => $"{prefix}{number:0000}"; - [NotNull] public string Code => FormatCode(CodePrefix, CodeNumber); - [CanBeNull] - public string StackTrace { get; } - [NotNull] + public string? StackTrace { get; } public IReadOnlyList SubDiagnostics { get; } - [NotNull] string MessageFormat { get; } - [NotNull] object[] MessageArgs { get; } - static readonly object[] NoArguments = new object[0]; - static readonly Diagnostic[] NoDiagnostics = new Diagnostic[0]; + static readonly object[] NoArguments = Array.Empty(); + static readonly Diagnostic[] NoDiagnostics = Array.Empty(); - public Diagnostic([NotNull] ISourceLine location, Severity severity, - [NotNull] string codePrefix, int codeNumber, - [NotNull] string messageFormat, [ItemNotNull] [CanBeNull] object[] messageArgs, - [CanBeNull] string stackTrace, [ItemNotNull] [CanBeNull] IReadOnlyList subDiagnostics, + public Diagnostic(ISourceLine location, Severity severity, + string codePrefix, int codeNumber, + string messageFormat, object[]? messageArgs, + string? stackTrace, IReadOnlyList? subDiagnostics, bool noisy) { Location = location; @@ -79,8 +70,7 @@ namespace Zilf.Diagnostics Noisy = noisy; } - [NotNull] - public Diagnostic WithSubDiagnostics([ItemNotNull] [NotNull] params Diagnostic[] newSubDiagnostics) + public Diagnostic WithSubDiagnostics(params Diagnostic[] newSubDiagnostics) { return new Diagnostic( Location, @@ -94,7 +84,6 @@ namespace Zilf.Diagnostics Noisy); } - [NotNull] public Diagnostic WithSeverity(Severity newSeverity) { return new Diagnostic( @@ -109,11 +98,12 @@ namespace Zilf.Diagnostics Noisy); } - [NotNull] [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] public string GetFormattedMessage() => string.Format(CustomFormatter.Instance, MessageFormat, MessageArgs); + [SuppressMessage("Globalization", "CA1308:Normalize strings to uppercase")] + [SuppressMessage("Globalization", "CA1305:Specify IFormatProvider")] public override string ToString() { // ReSharper disable once UseStringInterpolation @@ -134,19 +124,13 @@ namespace Zilf.Diagnostics { } - // ReSharper disable once AnnotationRedundancyInHierarchy (cross-platform conflict) - [CanBeNull] - public object GetFormat(Type formatType) - { - return formatType == typeof(ICustomFormatter) ? this : null; - } + public object? GetFormat(Type? formatType) => formatType == typeof(ICustomFormatter) ? this : null; - [NotNull] static readonly char[] Delimiter = { '|' }; /// - /// The "s" format was used with a instead of a . - public string Format([CanBeNull] string format, [CanBeNull] object arg, [CanBeNull] IFormatProvider formatProvider) + /// The "s" format was used with a instead of a . + public string Format(string? format, object? arg, IFormatProvider? formatProvider) { if (format == null || format != "s" && !format.StartsWith("s|", StringComparison.Ordinal)) return HandleOther(format, arg); @@ -179,8 +163,7 @@ namespace Zilf.Diagnostics } - [NotNull] - static string HandleOther([CanBeNull] string format, [CanBeNull] object arg) + static string HandleOther(string? format, object? arg) { if (arg is IFormattable formattable) return formattable.ToString(format, System.Globalization.CultureInfo.CurrentCulture); @@ -191,23 +174,21 @@ namespace Zilf.Diagnostics } public interface IDiagnosticFactory { - [NotNull] - Diagnostic GetDiagnostic([NotNull] ISourceLine location, int code, object[] messageArgs, - string stackTrace, Diagnostic[] subDiagnostics); + Diagnostic GetDiagnostic(ISourceLine location, int code, object[]? messageArgs, + string? stackTrace, Diagnostic[]? subDiagnostics); } public static class DiagnosticFactoryExtensions { [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] - [NotNull] - public static Diagnostic GetDiagnostic([NotNull] this IDiagnosticFactory fac, [NotNull] ISourceLine location, int code, object[] messageArgs) + public static Diagnostic GetDiagnostic(this IDiagnosticFactory fac, ISourceLine location, int code, object[] messageArgs) { return fac.GetDiagnostic(location, code, messageArgs, null, null); } [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] - [NotNull] - public static Diagnostic GetDiagnostic([NotNull] this IDiagnosticFactory fac, [NotNull] ISourceLine location, int code, object[] messageArgs, string stackTrace) + public static Diagnostic GetDiagnostic(this IDiagnosticFactory fac, ISourceLine location, int code, + object[]? messageArgs, string? stackTrace) { return fac.GetDiagnostic(location, code, messageArgs, stackTrace, null); } @@ -234,7 +215,7 @@ namespace Zilf.Diagnostics { if (field.FieldType == typeof(int) && field.IsLiteral) { - var code = (int)field.GetValue(null); + var code = (int)field.GetValue(null)!; var msgAttrs = field.GetCustomAttributes(typeof(MessageAttribute), false); messages.Add(code, (MessageAttribute)msgAttrs[0]); @@ -242,9 +223,8 @@ namespace Zilf.Diagnostics } } - [NotNull] - public Diagnostic GetDiagnostic(ISourceLine location, int code, object[] messageArgs, - string stackTrace, Diagnostic[] subDiagnostics) + public Diagnostic GetDiagnostic(ISourceLine location, int code, object[]? messageArgs, + string? stackTrace, Diagnostic[]? subDiagnostics) { var attr = messages[code]; return new Diagnostic( @@ -277,7 +257,7 @@ namespace Zilf.Diagnostics public string Format { get; } public Severity Severity { get; } - public MessageAttribute(string format, Severity severity) + protected MessageAttribute(string format, Severity severity) { Format = format; Severity = severity; diff --git a/src/Zilf/Diagnostics/DiagnosticContext.cs b/src/Zilf/Diagnostics/DiagnosticContext.cs index 8cba33d..eb4dbfc 100644 --- a/src/Zilf/Diagnostics/DiagnosticContext.cs +++ b/src/Zilf/Diagnostics/DiagnosticContext.cs @@ -18,7 +18,6 @@ using System; using System.Diagnostics; -using JetBrains.Annotations; using Zilf.Interpreter; using Zilf.Language; @@ -26,31 +25,28 @@ namespace Zilf.Diagnostics { sealed class DiagnosticContext { - [NotNull] public static DiagnosticContext Current { - get => threadLocalCurrent ?? (threadLocalCurrent = new DiagnosticContext()); + get => threadLocalCurrent ??= new DiagnosticContext(); private set => threadLocalCurrent = value; } [ThreadStatic] - static DiagnosticContext threadLocalCurrent; + static DiagnosticContext? threadLocalCurrent; class Disposer : IDisposable { - [CanBeNull] - DiagnosticContext oldContext; - [CanBeNull] - DiagnosticContext newContext; + DiagnosticContext? oldContext; + DiagnosticContext? newContext; - public Disposer([NotNull] DiagnosticContext oldContext, [NotNull] DiagnosticContext newContext) + public Disposer(DiagnosticContext oldContext, DiagnosticContext newContext) { this.oldContext = oldContext; this.newContext = newContext; } /// - /// This contract is no longer on top of the stack + /// This contract is no longer on top of the stack public void Dispose() { if (newContext == null) @@ -70,8 +66,7 @@ namespace Zilf.Diagnostics } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")] - [NotNull] - public static IDisposable Push([CanBeNull] ISourceLine sourceLine = null, [CanBeNull] Frame frame = null) + public static IDisposable Push(ISourceLine? sourceLine = null, Frame? frame = null) { var oldContext = Current; @@ -89,15 +84,13 @@ namespace Zilf.Diagnostics { } - DiagnosticContext([NotNull] ISourceLine sourceLine, [CanBeNull] Frame frame) + DiagnosticContext(ISourceLine sourceLine, Frame? frame) { SourceLine = sourceLine; Frame = frame; } - [NotNull] public ISourceLine SourceLine { get; } - [CanBeNull] - public Frame Frame { get; } + public Frame? Frame { get; } } } diff --git a/src/Zilf/Diagnostics/DiagnosticManager.cs b/src/Zilf/Diagnostics/DiagnosticManager.cs index aaaafe7..597f487 100644 --- a/src/Zilf/Diagnostics/DiagnosticManager.cs +++ b/src/Zilf/Diagnostics/DiagnosticManager.cs @@ -28,18 +28,14 @@ namespace Zilf.Diagnostics { const int MaxErrorCount = 100; - [NotNull] readonly List diagnostics = new List(); - [NotNull] readonly List suppressedDiagnostics = new List(); - [NotNull] readonly HashSet suppressions = new HashSet(); bool suppressAllTheThings = false; - [NotNull] public IReadOnlyCollection Diagnostics => diagnostics; public int ErrorCount => Diagnostics.Count(d => d.Severity == Severity.Error || d.Severity == Severity.Fatal); public int WarningCount => Diagnostics.Count(d => d.Severity == Severity.Warning); @@ -48,26 +44,24 @@ namespace Zilf.Diagnostics public bool WarningsAsErrors { get; set; } public bool SuppressNoisyWarnings { get; set; } - [NotNull] public IDiagnosticFormatter Formatter { get; } - [NotNull] public TextWriter OutputWriter { get; } - public event EventHandler TooManyErrors; + public event EventHandler? TooManyErrors; - public DiagnosticManager([CanBeNull] IDiagnosticFormatter formatter = null, [CanBeNull] TextWriter outputWriter = null) + public DiagnosticManager(IDiagnosticFormatter? formatter = null, TextWriter? outputWriter = null) { Formatter = formatter ?? new DefaultDiagnosticFormatter(); OutputWriter = outputWriter ?? Console.Error; } - public void Suppress([NotNull] string code) + public void Suppress(string code) { if (!suppressAllTheThings) suppressions.Add(code); } - public void Suppress([NotNull, ItemNotNull] IEnumerable codes) + public void Suppress(IEnumerable codes) { if (!suppressAllTheThings) suppressions.UnionWith(codes); @@ -85,7 +79,7 @@ namespace Zilf.Diagnostics suppressions.Clear(); } - public void Handle([NotNull] Diagnostic diag) + public void Handle(Diagnostic diag) { if (WarningsAsErrors && diag.Severity == Severity.Warning) { @@ -109,7 +103,7 @@ namespace Zilf.Diagnostics } } - private bool IsSuppressed([NotNull] Diagnostic diag) + private bool IsSuppressed(Diagnostic diag) { if (diag.Severity >= Severity.Error) return false; diff --git a/src/Zilf/Diagnostics/IDiagnosticFormatter.cs b/src/Zilf/Diagnostics/IDiagnosticFormatter.cs index 6721780..7f6a55f 100644 --- a/src/Zilf/Diagnostics/IDiagnosticFormatter.cs +++ b/src/Zilf/Diagnostics/IDiagnosticFormatter.cs @@ -22,7 +22,6 @@ namespace Zilf.Diagnostics { public interface IDiagnosticFormatter { - [NotNull] - string Format([NotNull] Diagnostic diagnostic); + string Format(Diagnostic diagnostic); } } diff --git a/src/Zilf/Diagnostics/InterpreterMessages.cs b/src/Zilf/Diagnostics/InterpreterMessages.cs index a062a43..950df9b 100644 --- a/src/Zilf/Diagnostics/InterpreterMessages.cs +++ b/src/Zilf/Diagnostics/InterpreterMessages.cs @@ -22,6 +22,7 @@ namespace Zilf.Diagnostics { [MessageSet("MDL")] [SuppressMessage("ReSharper", "InconsistentNaming")] + [SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Message constants")] public abstract class InterpreterMessages { InterpreterMessages() diff --git a/src/Zilf/Interpreter/ApplicableExtensions.cs b/src/Zilf/Interpreter/ApplicableExtensions.cs index ab617a2..371cd31 100644 --- a/src/Zilf/Interpreter/ApplicableExtensions.cs +++ b/src/Zilf/Interpreter/ApplicableExtensions.cs @@ -16,6 +16,9 @@ * along with ZILF. If not, see . */ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Security; using JetBrains.Annotations; using Zilf.Interpreter.Values; @@ -23,9 +26,9 @@ namespace Zilf.Interpreter { static class ApplicableExtensions { - [CanBeNull] [ContractAnnotation("zo: null => null")] - public static IApplicable AsApplicable([CanBeNull] this ZilObject zo, [NotNull] Context ctx) + [Obsolete("Use IsApplicable(this ZilObject, Context, out IApplicable?) instead.")] + public static IApplicable? AsApplicable(this ZilObject? zo, Context ctx) { if (zo == null) return null; @@ -39,7 +42,7 @@ namespace Zilf.Interpreter } [ContractAnnotation("zo: null => false")] - public static bool IsApplicable([CanBeNull] this ZilObject zo, [NotNull] Context ctx) + public static bool IsApplicable([NotNullWhen(true)] this ZilObject? zo, Context ctx) { if (zo == null) return false; @@ -47,6 +50,33 @@ namespace Zilf.Interpreter return zo is IApplicable || ctx.GetApplyTypeDelegate(zo.GetTypeAtom(ctx)) != null; } + public static bool IsApplicable([NotNullWhen(true)] this ZilObject? zo, Context ctx, + [NotNullWhen(true)] out IApplicable? asApplicable) + { + if (zo == null) + { + asApplicable = null; + return false; + } + + var del = ctx.GetApplyTypeDelegate(zo.GetTypeAtom(ctx)); + + if (del != null) + { + asApplicable = new ApplicableWrapper(zo, del); + return true; + } + + if (zo is IApplicable applicable) + { + asApplicable = applicable; + return true; + } + + asApplicable = null; + return false; + } + sealed class ApplicableWrapper : IApplicable { readonly ZilObject zo; @@ -58,17 +88,12 @@ namespace Zilf.Interpreter this.del = del; } - public ZilResult Apply(Context ctx, ZilObject[] args) - { - return ZilObject.EvalSequence(ctx, args).TryToZilObjectArray(out args, out var zr) + public ZilResult Apply(Context ctx, ZilObject[] args) => + ZilObject.EvalSequence(ctx, args).TryToZilObjectArray(out args!, out var zr) ? del(zo, args) : zr; - } - public ZilResult ApplyNoEval(Context ctx, ZilObject[] args) - { - return del(zo, args); - } + public ZilResult ApplyNoEval(Context ctx, ZilObject[] args) => del(zo, args); } } } diff --git a/src/Zilf/Interpreter/ArgDecoder.cs b/src/Zilf/Interpreter/ArgDecoder.cs index cec49f6..3739c4e 100644 --- a/src/Zilf/Interpreter/ArgDecoder.cs +++ b/src/Zilf/Interpreter/ArgDecoder.cs @@ -38,42 +38,73 @@ namespace Zilf.Interpreter [Serializable] abstract class ArgumentDecodingError : InterpreterError { - protected ArgumentDecodingError([NotNull] Diagnostic diagnostic) + protected ArgumentDecodingError(Diagnostic diagnostic) : base(diagnostic) { } - protected ArgumentDecodingError([NotNull] SerializationInfo si, StreamingContext sc) + protected ArgumentDecodingError(SerializationInfo si, StreamingContext sc) : base(si, sc) { } + + protected ArgumentDecodingError() + { + } + + protected ArgumentDecodingError(int code) : base(code) + { + } + + protected ArgumentDecodingError(int code, params object[] messageArgs) : base(code, messageArgs) + { + } + + protected ArgumentDecodingError(ISourceLine sourceLine, int code) : base(sourceLine, code) + { + } + + protected ArgumentDecodingError(ISourceLine sourceLine, int code, params object[] messageArgs) : base(sourceLine, code, messageArgs) + { + } + + protected ArgumentDecodingError(IProvideSourceLine sourceLine, int code) : base(sourceLine, code) + { + } + + protected ArgumentDecodingError(IProvideSourceLine node, int code, params object[] messageArgs) : base(node, code, messageArgs) + { + } + + protected ArgumentDecodingError(string message) : base(message) + { + } + + protected ArgumentDecodingError(string message, Exception innerException) : base(message, innerException) + { + } + + protected ArgumentDecodingError(ISourceLine src, string message) : base(src, message) + { + } } abstract class CallSite { - protected CallSite([NotNull] string name) + protected CallSite(string name) { Name = name; } - [NotNull] protected string Name { get; } - [NotNull] public abstract string ChildName { get; } - public sealed override string ToString() - { - return Name; - } + public sealed override string ToString() => Name; - [NotNull] - public string DescribeArgument(int childIndex) - { - return $"{Name}: {ChildName} {childIndex + 1}"; - } + public string DescribeArgument(int childIndex) => $"{Name}: {ChildName} {childIndex + 1}"; } sealed class FunctionCallSite : CallSite { - public FunctionCallSite([NotNull] string name) + public FunctionCallSite(string name) : base(name) { } @@ -83,7 +114,7 @@ namespace Zilf.Interpreter sealed class StructuredArgumentCallSite : CallSite { - public StructuredArgumentCallSite([NotNull] CallSite parent, int argIndex) + public StructuredArgumentCallSite(CallSite parent, int argIndex) : base(parent.DescribeArgument(argIndex)) { } @@ -94,18 +125,17 @@ namespace Zilf.Interpreter [Serializable] sealed class ArgumentCountError : ArgumentDecodingError { - ArgumentCountError([NotNull] Diagnostic diagnostic) + ArgumentCountError(Diagnostic diagnostic) : base(diagnostic) { } - ArgumentCountError([NotNull] SerializationInfo si, StreamingContext sc) + ArgumentCountError(SerializationInfo si, StreamingContext sc) : base(si, sc) { } - [NotNull] - public static ArgumentCountError WrongCount([NotNull] CallSite site, int lowerBound, int? upperBound, bool morePrefix = false) + public static ArgumentCountError WrongCount(CallSite site, int lowerBound, int? upperBound, bool morePrefix = false) { const int PlainMessageCode = InterpreterMessages._0_Requires_1_21s; const int MessageCodeWithMore = InterpreterMessages._0_Requires_1_Additional_21s; @@ -122,10 +152,9 @@ namespace Zilf.Interpreter return new ArgumentCountError(diag); } - [NotNull] - public static ArgumentCountError TooMany([NotNull] CallSite site, int firstUnexpectedIndex, int? suspiciousTypeIndex) + public static ArgumentCountError TooMany(CallSite site, int firstUnexpectedIndex, int? suspiciousTypeIndex) { - Diagnostic info; + Diagnostic? info; var sourceLine = DiagnosticContext.Current.SourceLine; if (suspiciousTypeIndex != null) @@ -149,12 +178,52 @@ namespace Zilf.Interpreter return new ArgumentCountError(diag); } + + public ArgumentCountError(string message, Exception innerException) : base(message, innerException) + { + } + + private ArgumentCountError() : base() + { + } + + private ArgumentCountError(int code) : base(code) + { + } + + private ArgumentCountError(int code, params object[] messageArgs) : base(code, messageArgs) + { + } + + private ArgumentCountError(ISourceLine sourceLine, int code) : base(sourceLine, code) + { + } + + private ArgumentCountError(ISourceLine sourceLine, int code, params object[] messageArgs) : base(sourceLine, code, messageArgs) + { + } + + private ArgumentCountError(IProvideSourceLine sourceLine, int code) : base(sourceLine, code) + { + } + + private ArgumentCountError(IProvideSourceLine node, int code, params object[] messageArgs) : base(node, code, messageArgs) + { + } + + private ArgumentCountError(string message) : base(message) + { + } + + private ArgumentCountError(ISourceLine src, string message) : base(src, message) + { + } } [Serializable] sealed class ArgumentTypeError : ArgumentDecodingError { - public ArgumentTypeError([NotNull] CallSite site, int index, [NotNull] string constraintDesc) + public ArgumentTypeError(CallSite site, int index, string constraintDesc) : base(MakeDiagnostic( null, InterpreterMessages._0_Expected_1, @@ -162,21 +231,64 @@ namespace Zilf.Interpreter { } - ArgumentTypeError([NotNull] SerializationInfo si, StreamingContext sc) + ArgumentTypeError(SerializationInfo si, StreamingContext sc) : base(si, sc) { } + + public ArgumentTypeError(string message) : base(message) + { + } + + private ArgumentTypeError(Diagnostic diagnostic) : base(diagnostic) + { + } + + private ArgumentTypeError() : base() + { + } + + private ArgumentTypeError(int code) : base(code) + { + } + + private ArgumentTypeError(int code, params object[] messageArgs) : base(code, messageArgs) + { + } + + private ArgumentTypeError(ISourceLine sourceLine, int code) : base(sourceLine, code) + { + } + + private ArgumentTypeError(ISourceLine sourceLine, int code, params object[] messageArgs) : base(sourceLine, code, messageArgs) + { + } + + private ArgumentTypeError(IProvideSourceLine sourceLine, int code) : base(sourceLine, code) + { + } + + private ArgumentTypeError(IProvideSourceLine node, int code, params object[] messageArgs) : base(node, code, messageArgs) + { + } + + private ArgumentTypeError(string message, Exception innerException) : base(message, innerException) + { + } + + private ArgumentTypeError(ISourceLine src, string message) : base(src, message) + { + } } [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter)] sealed class DeclAttribute : Attribute { - public DeclAttribute([NotNull] string pattern) + public DeclAttribute(string pattern) { Pattern = pattern; } - [NotNull] public string Pattern { get; } } @@ -202,20 +314,19 @@ namespace Zilf.Interpreter [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter)] sealed class ZilOptionalAttribute : Attribute { - public object Default { get; set; } + public object? Default { get; set; } } [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter)] sealed class EitherAttribute : Attribute { - public EitherAttribute([NotNull] [ItemNotNull] params Type[] types) + public EitherAttribute(params Type[] types) { Types = types; } - [NotNull] public Type[] Types { get; } - public string DefaultParamDesc { get; set; } + public string? DefaultParamDesc { get; set; } } [AttributeUsage(AttributeTargets.Struct)] @@ -231,12 +342,11 @@ namespace Zilf.Interpreter AttributeTargets.Parameter | AttributeTargets.Field)] sealed class ParamDescAttribute : Attribute { - public ParamDescAttribute([NotNull] string name) + public ParamDescAttribute(string name) { Description = name; } - [NotNull] public string Description { get; } } @@ -257,7 +367,7 @@ namespace Zilf.Interpreter /// that was not processed. This may point past the end of /// if the step consumed all input arguments, or it may be equal to /// if the step consumed none. - delegate int DecodingStep([ItemNotNull] [NotNull] ZilObject[] arguments, int index, DecodingStepCallbacks cb); + delegate int DecodingStep(ZilObject[] arguments, int index, DecodingStepCallbacks cb); delegate void ErrorCallback(int? index = null); @@ -265,7 +375,7 @@ namespace Zilf.Interpreter { public Context Context; public CallSite Site; - public Action Ready; + public Action Ready; public ErrorCallback Error; public Action Missing; } @@ -289,7 +399,7 @@ namespace Zilf.Interpreter int LowerBound { get; } int? UpperBound { get; } - ArgDecoder([NotNull] [ProvidesContext] Context ctx, [ItemNotNull] [NotNull] ParameterInfo[] parameters) + ArgDecoder([ProvidesContext] Context ctx, ParameterInfo[] parameters) { StepInfos = new DecodingStepInfo[parameters.Length - 1]; LowerBound = 0; @@ -315,12 +425,12 @@ namespace Zilf.Interpreter } [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "IsOptional")] - static DecodingStepInfo PrepareOne([NotNull] [ProvidesContext] Context ctx, [NotNull] ParameterInfo pi) + static DecodingStepInfo PrepareOne([ProvidesContext] Context ctx, ParameterInfo pi) { var zilOptAttr = pi.GetCustomAttribute(); bool isOptional; - object defaultValue; + object? defaultValue; if (zilOptAttr != null) { @@ -336,23 +446,21 @@ namespace Zilf.Interpreter defaultValue = pi.HasDefaultValue ? pi.DefaultValue : null; } - var result = PrepareOne( + return PrepareOne( ctx, pi.ParameterType, - Hyphenate(pi.Name), + Hyphenate(pi.Name!), pi.GetCustomAttributes(false), isOptional, defaultValue); - - return result; } - static DecodingStepInfo PrepareOne([NotNull] [ProvidesContext] Context ctx, [NotNull] FieldInfo fi) + static DecodingStepInfo PrepareOne([ProvidesContext] Context ctx, FieldInfo fi) { var zilOptAttr = fi.GetCustomAttribute(); bool isOptional; - object defaultValue; + object? defaultValue; if (zilOptAttr != null) { @@ -365,19 +473,16 @@ namespace Zilf.Interpreter defaultValue = null; } - var result = PrepareOne( + return PrepareOne( ctx, fi.FieldType, Hyphenate(fi.Name), fi.GetCustomAttributes(false), isOptional, defaultValue); - - return result; } - [CanBeNull] - static SignaturePart OverrideParamDesc([NotNull] FieldInfo fi) + static SignaturePart? OverrideParamDesc(FieldInfo fi) { var attr = fi.GetCustomAttribute(); @@ -396,8 +501,7 @@ namespace Zilf.Interpreter return OverrideParamDesc(fi.FieldType); } - [CanBeNull] - static SignaturePart OverrideParamDesc([NotNull] Type t) + static SignaturePart? OverrideParamDesc(Type t) { var typeAttr = t.GetCustomAttribute(); @@ -430,8 +534,7 @@ namespace Zilf.Interpreter return second != null ? SignatureBuilder.Quote(second) : null; } - [NotNull] - static string Hyphenate([NotNull] string s) + static string Hyphenate(string s) { var sb = new StringBuilder(s.Length); sb.Append(char.ToLowerInvariant(s[0])); @@ -455,12 +558,12 @@ namespace Zilf.Interpreter [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "LocalEnvironment")] [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "BuiltinTypeAttribute")] - static DecodingStepInfo PrepareOne([NotNull] [ProvidesContext] Context ctx, [NotNull] Type paramType, - [NotNull] string name, [ItemNotNull] [NotNull] object[] customAttributes, - bool isOptional, object defaultValueWhenOptional) + static DecodingStepInfo PrepareOne([ProvidesContext] Context ctx, Type paramType, + string name, object[] customAttributes, + bool isOptional, object? defaultValueWhenOptional) { DecodingStepInfo result; - object defaultValue = null; + object? defaultValue = null; EitherAttribute eitherAttr; var isRequired = customAttributes.OfType().Any(); @@ -481,26 +584,22 @@ namespace Zilf.Interpreter var innerStepInfo = PrepareOneEither(ctx, eitherAttr.DefaultParamDesc ?? name, eitherAttr.Types); result = PrepareOneArrayFromInnerStep(elemType, innerStepInfo, isRequired, out defaultValue); } - else if (paramType.IsValueType && - paramType.GetCustomAttribute() != null) + else if (paramType.IsValueType && paramType.GetCustomAttribute() != null) { result = PrepareOneStructured(ctx, paramType); } - else if (paramType.IsArray && - paramType.GetElementType()?.GetCustomAttribute() != null) + else if (paramType.IsArray && paramType.GetElementType()?.GetCustomAttribute() != null) { var elemType = paramType.GetElementType(); Debug.Assert(elemType != null); var innerStepInfo = PrepareOneStructured(ctx, elemType); result = PrepareOneArrayFromInnerStep(elemType, innerStepInfo, isRequired, out defaultValue); } - else if (paramType.IsValueType && - paramType.GetCustomAttribute() != null) + else if (paramType.IsValueType && paramType.GetCustomAttribute() != null) { result = PrepareOneSequence(ctx, paramType); } - else if (paramType.IsArray && - paramType.GetElementType()?.GetCustomAttribute() != null) + else if (paramType.IsArray && paramType.GetElementType()?.GetCustomAttribute() != null) { var elemType = paramType.GetElementType(); Debug.Assert(elemType != null); @@ -568,14 +667,15 @@ namespace Zilf.Interpreter c.Missing(); } - var ap = a[i].AsApplicable(c.Context); - - if (ap == null) + if (a[i].IsApplicable(c.Context, out var ap)) + { + c.Ready(ap); + } + else { c.Error(); } - c.Ready(ap); return i + 1; }, LowerBound = 1, @@ -602,7 +702,7 @@ namespace Zilf.Interpreter result = PrepareOneNullableConversion(null, zo => zo.IsTrue, paramType, out defaultValue); } - else if (paramType.IsArray && IsZilObjectType(paramType.GetElementType())) + else if (paramType.IsArray && IsZilObjectType(paramType.GetElementType()!)) { // decode as an array containing all remaining args var eltype = paramType.GetElementType(); @@ -645,7 +745,7 @@ namespace Zilf.Interpreter else if (paramType == typeof(IApplicable[])) { // decode as an array containing all remaining args - defaultValue = new IApplicable[0]; + defaultValue = Array.Empty(); result = new DecodingStepInfo { @@ -666,11 +766,10 @@ namespace Zilf.Interpreter for (int j = i; j < a.Length; j++) { - var ap = a[j].AsApplicable(c.Context); - - if (ap == null) + if (!a[j].IsApplicable(c.Context, out var ap)) { c.Error(); + ap = null!; } array[j - i] = ap; @@ -759,7 +858,7 @@ namespace Zilf.Interpreter c.Missing(); } - if (!Decl.Check(c.Context, a[i], decl)) + if (!Decl.Check(c.Context, a[i]!, decl)) { c.Error(); } @@ -776,11 +875,11 @@ namespace Zilf.Interpreter var prevStep = result.Step; var constraint = result.Constraint; - defaultValueWhenOptional = defaultValueWhenOptional ?? defaultValue; + defaultValueWhenOptional ??= defaultValue; result.Step = (a, i, c) => { - if (i < a.Length && constraint.Allows(c.Context, a[i])) + if (i < a.Length && constraint.Allows(c.Context, a[i]!)) { return prevStep(a, i, c); } @@ -792,8 +891,7 @@ namespace Zilf.Interpreter return result; } - [NotNull] - static Constraint ZilObjectTypeToConstraint([NotNull] Type paramType) + static Constraint ZilObjectTypeToConstraint(Type paramType) { if (paramType == typeof(IStructure)) return Constraint.Structured; @@ -814,8 +912,8 @@ namespace Zilf.Interpreter } static DecodingStepInfo PrepareOneArrayFromInnerStep( - [NotNull] Type elemType, DecodingStepInfo innerStepInfo, bool isRequired, - [NotNull] out object defaultValue) + Type elemType, DecodingStepInfo innerStepInfo, bool isRequired, + out object defaultValue) { var result = new DecodingStepInfo { @@ -831,7 +929,7 @@ namespace Zilf.Interpreter * the possibility that the inner step will consume multiple * arguments. */ - var output = new List(a.Length - i); + var output = new List(a.Length - i); var outerReady = c.Ready; c.Ready = obj => output.Add(obj); @@ -867,8 +965,9 @@ namespace Zilf.Interpreter } static DecodingStepInfo PrepareOneConversion( - StdAtom? typeAtom, [NotNull] Func convert, [CanBeNull] out object defaultValue) + StdAtom? typeAtom, Func convert, out object? defaultValue) where TZil : ZilObject + where TValue : class { var constraint = (typeAtom != null) ? Constraint.OfType(typeAtom.Value) : Constraint.AnyObject; @@ -900,8 +999,8 @@ namespace Zilf.Interpreter } static DecodingStepInfo PrepareOneNullableConversion( - StdAtom? typeAtom, [NotNull] Func convert, [NotNull] Type paramType, - [CanBeNull] out object defaultValue) + StdAtom? typeAtom, Func convert, Type paramType, + out object? defaultValue) where TZil : ZilObject where TValue : struct { @@ -947,13 +1046,13 @@ namespace Zilf.Interpreter } static DecodingStepInfo PrepareOneArrayConversion( - StdAtom? typeAtom, [NotNull] Func convert, bool isRequired, - [NotNull] out object defaultValue) + StdAtom? typeAtom, Func convert, bool isRequired, + out object defaultValue) where TZil : ZilObject { var constraint = (typeAtom != null) ? Constraint.OfType(typeAtom.Value) : Constraint.AnyObject; - defaultValue = new int[0]; + defaultValue = Array.Empty(); var result = new DecodingStepInfo { Constraint = constraint, @@ -991,13 +1090,13 @@ namespace Zilf.Interpreter } // TODO: cache the result - static DecodingStepInfo PrepareOneStructured(Context ctx, [NotNull] Type structType) + static DecodingStepInfo PrepareOneStructured(Context ctx, Type structType) { - var typeAtom = structType.GetCustomAttribute().TypeAtom; + var typeAtom = structType.GetCustomAttribute()!.TypeAtom; var stepInfos = PrepareStepsFromStruct(ctx, structType, out var fields, out var lowerBound, out var upperBound); - var result = new DecodingStepInfo + return new DecodingStepInfo { LowerBound = 1, UpperBound = 1, @@ -1010,12 +1109,12 @@ namespace Zilf.Interpreter c.Missing(); } - if (a[i].StdTypeAtom != typeAtom) + if (a[i]!.StdTypeAtom != typeAtom) { c.Error(); } - var input = (IStructure)a[i]; + var input = (IStructure)a[i]!; var innerSite = new StructuredArgumentCallSite(c.Site, i); if ((lowerBound >= 1 && input.GetLength(lowerBound - 1) < lowerBound) || @@ -1025,11 +1124,11 @@ namespace Zilf.Interpreter } var inputLength = input.GetLength(); - var output = Activator.CreateInstance(structType); + var output = Activator.CreateInstance(structType)!; var elements = new ZilObject[inputLength]; for (int j = 0; j < elements.Length; j++) - elements[j] = input[j]; + elements[j] = input[j]!; var elemIndex = 0; var stepIndex = 0; @@ -1051,8 +1150,7 @@ namespace Zilf.Interpreter c.Ready = obj => fields[enclosedStepIndex].SetValue(output, obj); var step = stepInfos[stepIndex].Step; - var next = step(elements, elemIndex, c); - elemIndex = next; + elemIndex = step(elements, elemIndex, c); remainingLowerBound -= stepInfos[stepIndex].LowerBound; remainingUpperBound -= stepInfos[stepIndex].UpperBound; } @@ -1067,13 +1165,10 @@ namespace Zilf.Interpreter return i + 1; } }; - - return result; } - [NotNull] - static DecodingStepInfo[] PrepareStepsFromStruct(Context ctx, [NotNull] Type structType, - [ItemNotNull] [NotNull] out FieldInfo[] fields, out int lowerBound, out int? upperBound) + static DecodingStepInfo[] PrepareStepsFromStruct(Context ctx, Type structType, + out FieldInfo[] fields, out int lowerBound, out int? upperBound) { fields = GetStructFieldsInOrder(structType); var stepInfos = new DecodingStepInfo[fields.Length]; @@ -1099,9 +1194,7 @@ namespace Zilf.Interpreter return stepInfos; } - [ItemNotNull] - [NotNull] - static FieldInfo[] GetStructFieldsInOrder([NotNull] Type structType) + static FieldInfo[] GetStructFieldsInOrder(Type structType) { return structType.GetFields() .OrderBy(f => f.MetadataToken) @@ -1109,7 +1202,7 @@ namespace Zilf.Interpreter } // TODO: cache the result? - static DecodingStepInfo PrepareOneEither([NotNull] Context ctx, [NotNull] string name, [ItemNotNull] [NotNull] Type[] inputTypes) + static DecodingStepInfo PrepareOneEither(Context ctx, string name, Type[] inputTypes) { var choices = new DecodingStep[inputTypes.Length]; var choiceConstraints = new Constraint[inputTypes.Length]; @@ -1117,7 +1210,7 @@ namespace Zilf.Interpreter int? upperBound = 0; var constraint = Constraint.Forbidden; - var noAttributes = new object[0]; + var noAttributes = Array.Empty(); for (int i = 0; i < inputTypes.Length; i++) { var stepInfo = PrepareOne(ctx, inputTypes[i], name, noAttributes, false, null); @@ -1138,7 +1231,7 @@ namespace Zilf.Interpreter Debug.Assert(lowerBound != null); - var result = new DecodingStepInfo + return new DecodingStepInfo { LowerBound = (int)lowerBound, UpperBound = upperBound, @@ -1148,12 +1241,12 @@ namespace Zilf.Interpreter Step = (a, i, c) => { var outerError = c.Error; - ArgumentDecodingError exception = null; + ArgumentDecodingError? exception = null; int choiceIndex = 0; for (; choiceIndex < choices.Length; choiceIndex++) { - if (i < a.Length && !choiceConstraints[choiceIndex].Allows(c.Context, a[i])) + if (i < a.Length && !choiceConstraints[choiceIndex].Allows(c.Context, a[i]!)) { // doesn't pass constraint, don't try continue; @@ -1186,16 +1279,14 @@ namespace Zilf.Interpreter throw new UnreachableCodeException(); } }; - - return result; } // TODO: cache the result? - static DecodingStepInfo PrepareOneSequence(Context ctx, [NotNull] Type seqType) + static DecodingStepInfo PrepareOneSequence(Context ctx, Type seqType) { var stepInfos = PrepareStepsFromStruct(ctx, seqType, out var fields, out var lowerBound, out var upperBound); - var result = new DecodingStepInfo + return new DecodingStepInfo { LowerBound = lowerBound, UpperBound = upperBound, @@ -1209,7 +1300,7 @@ namespace Zilf.Interpreter throw ArgumentCountError.WrongCount(c.Site, lowerBound - remainingArgs, upperBound - remainingArgs, true); } - var output = Activator.CreateInstance(seqType); + var output = Activator.CreateInstance(seqType)!; var stepIndex = 0; @@ -1223,16 +1314,13 @@ namespace Zilf.Interpreter c.Error = j => throw new ArgumentTypeError(c.Site, j ?? enclosedI, stepInfos[enclosedStepIndex].Constraint.ToString()); var step = stepInfos[stepIndex].Step; - var next = step(a, i, c); - i = next; + i = step(a, i, c); } outerReady(output); return i; } }; - - return result; } /// @@ -1250,25 +1338,23 @@ namespace Zilf.Interpreter /// Arguments must be converted to with /// instead. /// - static bool IsZilObjectType(Type t) - { - return typeof(ZilObject).IsAssignableFrom(t) || t == typeof(IStructure); - } + static bool IsZilObjectType(Type t) => typeof(ZilObject).IsAssignableFrom(t) || t == typeof(IStructure); /// /// Method return type is not assignable to or ; /// or first parameter type is not /// /// is - [NotNull] - public static ArgDecoder FromMethodInfo([NotNull] MethodInfo methodInfo, [NotNull] [ProvidesContext] Context ctx) + public static ArgDecoder FromMethodInfo(MethodInfo methodInfo, [ProvidesContext] Context ctx) { if (methodInfo == null) throw new ArgumentNullException(nameof(methodInfo)); if (!typeof(ZilObject).IsAssignableFrom(methodInfo.ReturnType) && !typeof(ZilResult).IsAssignableFrom(methodInfo.ReturnType)) + { throw new ArgumentException("Method return type is not assignable to ZilObject or ZilResult"); + } var parameters = methodInfo.GetParameters(); @@ -1278,15 +1364,11 @@ namespace Zilf.Interpreter return new ArgDecoder(ctx, parameters); } - [NotNull] - public static SubrDelegate WrapMethod([NotNull] MethodInfo methodInfo, [NotNull] [ProvidesContext] Context ctx) - { - return WrapMethod(methodInfo, ctx, null); - } + public static SubrDelegate WrapMethod(MethodInfo methodInfo, [ProvidesContext] Context ctx) => + WrapMethod(methodInfo, ctx, null); - [NotNull] - static SubrDelegate WrapMethod([NotNull] MethodInfo methodInfo, [NotNull] [ProvidesContext] Context ctx, - [CanBeNull] Dictionary alreadyDone) + static SubrDelegate WrapMethod(MethodInfo methodInfo, [ProvidesContext] Context ctx, + Dictionary? alreadyDone) { var parameters = methodInfo.GetParameters(); @@ -1307,14 +1389,17 @@ namespace Zilf.Interpreter try { var result = methodInfo.Invoke(null, decoder.Decode(name, c, args)); - if (result is ZilResult zr) - return zr; - return (ZilObject)result; + return result switch + { + ZilResult zr => zr, + null => throw new InvalidOperationException("wrapped SUBR returned null"), + _ => (ZilObject)result + }; } catch (TargetInvocationException ex) { - ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); + ExceptionDispatchInfo.Capture(ex.InnerException!).Throw(); throw new UnreachableCodeException(ex); } }; @@ -1329,10 +1414,10 @@ namespace Zilf.Interpreter if (targetMethodInfo == null) throw new InvalidOperationException("Can't find redirect target " + redirectAttr.Target); - alreadyDone = alreadyDone ?? new Dictionary(); + alreadyDone ??= new Dictionary(); alreadyDone.Add(methodInfo, del); - if (alreadyDone.TryGetValue(targetMethodInfo, out var targetDel) == false) + if (!alreadyDone.TryGetValue(targetMethodInfo, out var targetDel)) { targetDel = WrapMethod(targetMethodInfo, ctx, alreadyDone); if (!alreadyDone.ContainsKey(targetMethodInfo)) @@ -1359,9 +1444,7 @@ namespace Zilf.Interpreter /// The wrong number of arguments were provided. /// A provided argument was of the wrong type. - [ItemNotNull] - [NotNull] - public object[] Decode([NotNull] string name, [NotNull] [ProvidesContext] Context ctx, [ItemNotNull] [NotNull] ZilObject[] args) + public object?[] Decode(string name, [ProvidesContext] Context ctx, ZilObject[] args) { var site = new FunctionCallSite(name); @@ -1370,10 +1453,10 @@ namespace Zilf.Interpreter throw ArgumentCountError.WrongCount(site, LowerBound, UpperBound); } - var result = new List(1 + args.Length) { ctx }; + var result = new List(1 + args.Length) { ctx }; var argIndex = 0; - Constraint savedConstraint = null; + Constraint? savedConstraint = null; var remainingLowerBound = LowerBound; var remainingUpperBound = UpperBound; int? lastUnderachievingStepArgIndex = null; diff --git a/src/Zilf/Interpreter/ArgItem.cs b/src/Zilf/Interpreter/ArgItem.cs index 6174b8f..98f82f5 100644 --- a/src/Zilf/Interpreter/ArgItem.cs +++ b/src/Zilf/Interpreter/ArgItem.cs @@ -26,10 +26,10 @@ namespace Zilf.Interpreter public readonly ZilAtom Atom; public readonly bool Quoted; - public readonly ZilObject DefaultValue; + public readonly ZilObject? DefaultValue; public readonly ArgType Type; - public ArgItem(ZilAtom atom, bool quoted, ZilObject defaultValue, ArgType type) + public ArgItem(ZilAtom atom, bool quoted, ZilObject? defaultValue, ArgType type) { Atom = atom; Quoted = quoted; diff --git a/src/Zilf/Interpreter/ArgSpec.cs b/src/Zilf/Interpreter/ArgSpec.cs index 38c33a9..59d0687 100644 --- a/src/Zilf/Interpreter/ArgSpec.cs +++ b/src/Zilf/Interpreter/ArgSpec.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using Zilf.Interpreter.Values; @@ -31,56 +32,41 @@ namespace Zilf.Interpreter class ArgSpec : IEnumerable { // name of the function to which this spec belongs - [CanBeNull] - readonly ZilAtom name; // reference to the "QUOTE" atom used for any quoted args - [CanBeNull] - readonly ZilAtom quoteAtom; + readonly ZilAtom? quoteAtom; // "BIND" - [CanBeNull] - readonly ZilAtom environmentAtom; // regular args, "OPT", and "AUX" - [NotNull] readonly ZilAtom[] argAtoms; - [NotNull] - readonly ZilObject[] argDecls; - [NotNull] + readonly ZilObject?[] argDecls; readonly bool[] argQuoted; - [NotNull] - readonly ZilObject[] argDefaults; + readonly ZilObject?[] argDefaults; readonly int optArgsStart, auxArgsStart; // "ARGS" or "TUPLE" - [CanBeNull] - readonly ZilAtom varargsAtom; - [CanBeNull] - readonly ZilObject varargsDecl; + readonly ZilObject? varargsDecl; readonly bool varargsQuoted; // "NAME"/"ACT" - [CanBeNull] - readonly ZilAtom activationAtom; // "VALUE" - [CanBeNull] - readonly ZilObject valueDecl; - - ArgSpec([CanBeNull] ZilAtom name, [CanBeNull] ZilAtom activationAtom, int optArgsStart, int auxArgsStart, - [CanBeNull] ZilAtom varargsAtom, bool varargsQuoted, [CanBeNull] ZilObject varargsDecl, - [CanBeNull] ZilAtom environmentAtom, [CanBeNull] ZilObject valueDecl, [CanBeNull] ZilAtom quoteAtom, - [NotNull] ZilAtom[] argAtoms, - [NotNull] ZilObject[] argDecls, [NotNull] bool[] argQuoted, [NotNull] ZilObject[] argDefaults) + readonly ZilObject? valueDecl; + + ArgSpec(ZilAtom? name, ZilAtom? activationAtom, int optArgsStart, int auxArgsStart, + ZilAtom? varargsAtom, bool varargsQuoted, ZilObject? varargsDecl, + ZilAtom? environmentAtom, ZilObject? valueDecl, ZilAtom? quoteAtom, + ZilAtom[] argAtoms, + ZilObject?[] argDecls, bool[] argQuoted, ZilObject?[] argDefaults) { - this.name = name; - this.activationAtom = activationAtom; + this.Name = name; + this.ActivationAtom = activationAtom; this.optArgsStart = optArgsStart; this.auxArgsStart = auxArgsStart; - this.varargsAtom = varargsAtom; + this.VarargsAtom = varargsAtom; this.varargsQuoted = varargsQuoted; this.varargsDecl = varargsDecl; - this.environmentAtom = environmentAtom; + this.EnvironmentAtom = environmentAtom; this.valueDecl = valueDecl; this.quoteAtom = quoteAtom; this.argAtoms = argAtoms; @@ -90,22 +76,21 @@ namespace Zilf.Interpreter } /// The argument specification is invalid. - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] - [NotNull] - public static ArgSpec Parse([NotNull] string caller, [CanBeNull] ZilAtom targetName, [CanBeNull] ZilAtom activationAtom, - [NotNull] IEnumerable argspec, [CanBeNull] ZilDecl bodyDecl = null) + [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] + public static ArgSpec Parse(string caller, ZilAtom? targetName, ZilAtom? activationAtom, + IEnumerable argspec, ZilDecl? bodyDecl = null) { var optArgsStart = -1; var auxArgsStart = -1; - ZilAtom varargsAtom = null, environmentAtom = null, quoteAtom = null; + ZilAtom? varargsAtom = null, environmentAtom = null, quoteAtom = null; bool varargsQuoted = false; - ZilObject varargsDecl = null, valueDecl = null; + ZilObject? varargsDecl = null, valueDecl = null; var argAtoms = new List(); - var argDecls = new List(); + var argDecls = new List(); var argQuoted = new List(); - var argDefaults = new List(); + var argDefaults = new List(); const int OO_None = 0; const int OO_Varargs = 1; @@ -115,7 +100,7 @@ namespace Zilf.Interpreter int cur = 0; int oneOffMode = OO_None; - ZilObject oneOffTag = null; + ZilObject? oneOffTag = null; foreach (var arg in argspec) { @@ -191,7 +176,7 @@ namespace Zilf.Interpreter break; default: - throw new InterpreterError(InterpreterMessages._0_Expected_1_After_2, caller, "an atom", oneOffTag); + throw new InterpreterError(InterpreterMessages._0_Expected_1_After_2, caller, "an atom", oneOffTag!); } oneOffMode = OO_None; @@ -200,7 +185,7 @@ namespace Zilf.Interpreter case OO_Activation: activationAtom = arg as ZilAtom; if (activationAtom == null) - throw new InterpreterError(InterpreterMessages._0_Expected_1_After_2, caller, "an atom", oneOffTag); + throw new InterpreterError(InterpreterMessages._0_Expected_1_After_2, caller, "an atom", oneOffTag!); oneOffMode = OO_None; continue; @@ -208,7 +193,7 @@ namespace Zilf.Interpreter case OO_Environment: environmentAtom = arg as ZilAtom; if (environmentAtom == null) - throw new InterpreterError(InterpreterMessages._0_Expected_1_After_2, caller, "an atom", oneOffTag); + throw new InterpreterError(InterpreterMessages._0_Expected_1_After_2, caller, "an atom", oneOffTag!); oneOffMode = OO_None; continue; @@ -223,7 +208,8 @@ namespace Zilf.Interpreter cur++; bool quoted = false; - ZilObject argName, argValue, argDecl; + ZilObject argName; + ZilObject? argValue, argDecl; // could be an atom or a list: (atom defaultValue) if (arg is ZilList al && !(arg is ZilForm)) @@ -232,8 +218,8 @@ namespace Zilf.Interpreter throw new InterpreterError(InterpreterMessages._0_Empty_List_In_Arg_Spec, caller); // TODO: report error if length != 2, or if in required args section - argName = al.First; - argValue = al.Rest.First; + argName = al.First!; + argValue = al.Rest!.First!; } else { @@ -255,12 +241,11 @@ namespace Zilf.Interpreter // could be quoted if (argName is ZilForm af) { - if (af.First is ZilAtom head && head.StdAtom == StdAtom.QUOTE && - !af.Rest.IsEmpty) + if (af is (ZilAtom { StdAtom: StdAtom.QUOTE } head, ({ } name, _))) { quoted = true; quoteAtom = head; - argName = af.Rest.First; + argName = name; } else throw new InterpreterError(InterpreterMessages._0_Unexpected_FORM_In_Arg_Spec_1, caller, argName.ToString()); @@ -292,7 +277,7 @@ namespace Zilf.Interpreter { var atom = pair.Key; var decl = pair.Value; - ZilObject prev; + ZilObject? prev; if (atom.StdAtom == StdAtom.VALUE) { @@ -310,7 +295,7 @@ namespace Zilf.Interpreter foreach (var i in argIndex[atom]) { - prev = prev ?? argDecls[i]; + prev ??= argDecls[i]; argDecls[i] = decl; } } @@ -333,7 +318,7 @@ namespace Zilf.Interpreter public int MinArgCount => optArgsStart; - public int? MaxArgCount => varargsAtom != null ? null : (int?)auxArgsStart; + public int? MaxArgCount => VarargsAtom != null ? null : (int?)auxArgsStart; public IEnumerator GetEnumerator() { @@ -355,8 +340,7 @@ namespace Zilf.Interpreter return GetEnumerator(); } - [NotNull] - public string ToString([NotNull] Func convert) + public string ToString(Func convert) { var sb = new StringBuilder(); sb.Append('('); @@ -381,7 +365,7 @@ namespace Zilf.Interpreter return ToString(zo => zo.ToString()); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (!(obj is ArgSpec other)) return false; @@ -390,20 +374,26 @@ namespace Zilf.Interpreter if (other.argAtoms.Length != numArgs || other.optArgsStart != optArgsStart || other.auxArgsStart != auxArgsStart || - other.varargsAtom != varargsAtom || + other.VarargsAtom != VarargsAtom || other.varargsQuoted != varargsQuoted) + { return false; + } for (int i = 0; i < numArgs; i++) { if (other.argAtoms[i] != argAtoms[i]) return false; + if (other.argQuoted[i] != argQuoted[i]) return false; + if (other.argDefaults[i] == null ? argDefaults[i] != null - : !other.argDefaults[i].StructurallyEquals(argDefaults[i])) + : !other.argDefaults[i]!.StructurallyEquals(argDefaults[i])) + { return false; + } } return true; @@ -413,8 +403,8 @@ namespace Zilf.Interpreter { int result = (argAtoms.Length << 1) ^ (optArgsStart << 2) ^ (auxArgsStart << 3); - if (varargsAtom != null) - result ^= varargsAtom.GetHashCode(); + if (VarargsAtom != null) + result ^= VarargsAtom.GetHashCode(); result ^= varargsQuoted.GetHashCode(); @@ -423,12 +413,12 @@ namespace Zilf.Interpreter result ^= argAtoms[i].GetHashCode(); if (argDecls[i] != null) - result ^= argDecls[i].GetHashCode(); + result ^= argDecls[i]!.GetHashCode(); result ^= argQuoted[i].GetHashCode(); if (argDefaults[i] != null) - result ^= argDefaults[i].GetHashCode(); + result ^= argDefaults[i]!.GetHashCode(); } return result; @@ -438,11 +428,11 @@ namespace Zilf.Interpreter { public Context Context { get; } public ZilResult? EarlyResult { get; } - public ZilActivation Activation { get; } - public LocalEnvironment Environment { get; } + public ZilActivation? Activation { get; } + public LocalEnvironment? Environment { get; } public bool WasTopLevel { get; } - public Application(Context ctx, ZilActivation act, LocalEnvironment env, bool wasTopLevel) + public Application(Context ctx, ZilActivation? act, LocalEnvironment? env, bool wasTopLevel) { Context = ctx; Activation = act; @@ -462,7 +452,7 @@ namespace Zilf.Interpreter GC.SuppressFinalize(this); Activation?.Dispose(); - ((IDisposable)Environment)?.Dispose(); + ((IDisposable?)Environment)?.Dispose(); Context.AtTopLevel = WasTopLevel; } @@ -477,11 +467,11 @@ namespace Zilf.Interpreter readonly Context ctx; readonly LocalEnvironment env; readonly Action throwWrongCount; - IEnumerator enumerator; - IEnumerator expansion; + IEnumerator? enumerator; + IEnumerator? expansion; - public ArgEvaluator([NotNull] Context ctx, [NotNull] LocalEnvironment env, [NotNull] IEnumerable rawArgs, - [NotNull] Action throwWrongCount) + public ArgEvaluator(Context ctx, LocalEnvironment env, IEnumerable rawArgs, + Action throwWrongCount) { this.ctx = ctx; this.env = env; @@ -506,6 +496,7 @@ namespace Zilf.Interpreter /// The wrong number of arguments were provided. [ContractAnnotation("=> halt")] + [DoesNotReturn] void DoThrowWrongCount() { throwWrongCount(); @@ -513,7 +504,7 @@ namespace Zilf.Interpreter /// Too few arguments were provided. [ContractAnnotation("=> src: notnull")] - public ZilResult GetOne(bool eval, out IProvideSourceLine src) + public ZilResult GetOne(bool eval, [System.Diagnostics.CodeAnalysis.NotNull] out IProvideSourceLine? src) { var result = GetOneOptional(eval, out src); @@ -525,7 +516,8 @@ namespace Zilf.Interpreter } /// The wrong number or types of arguments were provided. - public ZilResult? GetOneOptional(bool eval, [CanBeNull] out IProvideSourceLine src) + [return: NotNullIfNotNull("src")] + public ZilResult? GetOneOptional(bool eval, out IProvideSourceLine? src) { while (true) { @@ -615,10 +607,9 @@ namespace Zilf.Interpreter /// In the case of an exception, the new local environment will not be pushed. /// Make sure to call on the returned object! /// - [NotNull] [MustUseReturnValue] - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")] - public Application BeginApply([NotNull] [ProvidesContext] Context ctx, [ItemNotNull] [NotNull] ZilObject[] args, bool eval) + [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")] + public Application BeginApply([ProvidesContext] Context ctx, ZilObject[] args, bool eval) { var outerEnv = ctx.LocalEnvironment; var innerEnv = ctx.PushEnvironment(); @@ -626,21 +617,26 @@ namespace Zilf.Interpreter var wasTopLevel = ctx.AtTopLevel; ctx.AtTopLevel = false; - void ThrowWrongCount() => throw ArgumentCountError.WrongCount( - new FunctionCallSite(name?.ToString() ?? "user-defined function"), optArgsStart, auxArgsStart); + void ThrowWrongCount() + { + throw ArgumentCountError.WrongCount( + new FunctionCallSite(Name?.ToString() ?? "user-defined function"), + optArgsStart, + auxArgsStart); + } try { using (var evaluator = new ArgEvaluator(ctx, outerEnv, args, ThrowWrongCount)) { - if (environmentAtom != null) + if (EnvironmentAtom != null) { - innerEnv.Rebind(environmentAtom, - new ZilEnvironment(outerEnv, environmentAtom), + innerEnv.Rebind(EnvironmentAtom, + new ZilEnvironment(outerEnv, EnvironmentAtom), ctx.GetStdAtom(StdAtom.ENVIRONMENT)); } - IProvideSourceLine src; + IProvideSourceLine? src; for (int i = 0; i < optArgsStart; i++) { @@ -659,7 +655,7 @@ namespace Zilf.Interpreter if (zr.Value.ShouldPass()) return new Application(ctx, zr.Value, wasTopLevel); - ctx.MaybeCheckDecl(src, (ZilObject)zr.Value, argDecls[i], "argument {0}", argAtoms[i]); + ctx.MaybeCheckDecl(src!, (ZilObject)zr.Value, argDecls[i], "argument {0}", argAtoms[i]); innerEnv.Rebind(argAtoms[i], (ZilObject)zr.Value, argDecls[i]); } else @@ -670,7 +666,7 @@ namespace Zilf.Interpreter if (init.Value.ShouldPass()) return new Application(ctx, init.Value, wasTopLevel); - ctx.MaybeCheckDecl(argDefaults[i], (ZilObject)init.Value, argDecls[i], "default for argument {0}", argAtoms[i]); + ctx.MaybeCheckDecl(argDefaults[i]!, (ZilObject)init.Value, argDecls[i], "default for argument {0}", argAtoms[i]); } innerEnv.Rebind(argAtoms[i], init == null ? null : (ZilObject)init.Value, argDecls[i]); } @@ -684,30 +680,30 @@ namespace Zilf.Interpreter if (zr.Value.ShouldPass()) return new Application(ctx, zr.Value, wasTopLevel); - ctx.MaybeCheckDecl(argDefaults[i], (ZilObject)zr.Value, argDecls[i], "default for argument {0}", argAtoms[i]); + ctx.MaybeCheckDecl(argDefaults[i]!, (ZilObject)zr.Value, argDecls[i], "default for argument {0}", argAtoms[i]); } innerEnv.Rebind(argAtoms[i], zr == null ? null : (ZilObject)zr.Value, argDecls[i]); } - if (varargsAtom != null) + if (VarargsAtom != null) { var result = evaluator.GetRest(eval && !varargsQuoted).ToZilListResult(null); if (result.ShouldPass()) return new Application(ctx, result, wasTopLevel); var value = (ZilObject)result; - ctx.MaybeCheckDecl(value, varargsDecl, "argument {0}", varargsAtom); - innerEnv.Rebind(varargsAtom, value, varargsDecl); + ctx.MaybeCheckDecl(value, varargsDecl, "argument {0}", VarargsAtom); + innerEnv.Rebind(VarargsAtom, value, varargsDecl); } evaluator.NoMoreArguments(); } - ZilActivation activation; - if (activationAtom != null) + ZilActivation? activation; + if (ActivationAtom != null) { - activation = new ZilActivation(activationAtom); - innerEnv.Rebind(activationAtom, activation, ctx.GetStdAtom(StdAtom.ACTIVATION)); + activation = new ZilActivation(ActivationAtom); + innerEnv.Rebind(ActivationAtom, activation, ctx.GetStdAtom(StdAtom.ACTIVATION)); } else { @@ -742,42 +738,40 @@ namespace Zilf.Interpreter /// did not match the required pattern, and /// . is . - public void ValidateResult([NotNull] [ProvidesContext] Context ctx, [NotNull] ZilObject result) + public void ValidateResult([ProvidesContext] Context ctx, ZilObject result) { - ctx.MaybeCheckDecl(result, valueDecl, "return value of {0}", (object)name ?? "user-defined function"); + ctx.MaybeCheckDecl(result, valueDecl, "return value of {0}", (object?)Name ?? "user-defined function"); } - [NotNull] public ZilList ToZilList() { return new ZilList(AsZilListBody()); } - [ItemNotNull] public IEnumerable AsZilListBody() { bool emittedVarargs = false; - if (environmentAtom != null) + if (EnvironmentAtom != null) { yield return ZilString.FromString("BIND"); - yield return environmentAtom; + yield return EnvironmentAtom; } for (int i = 0; i < argAtoms.Length; i++) { if (i == auxArgsStart) { - if (varargsAtom != null) + if (VarargsAtom != null) { yield return ZilString.FromString(varargsQuoted ? "ARGS" : "TUPLE"); if (varargsDecl == null) { - yield return varargsAtom; + yield return VarargsAtom; } else { - yield return new ZilAdecl(varargsAtom, varargsDecl); + yield return new ZilAdecl(VarargsAtom, varargsDecl); } emittedVarargs = true; } @@ -793,12 +787,12 @@ namespace Zilf.Interpreter if (argQuoted[i]) { - arg = new ZilForm(new[] { quoteAtom, arg }); + arg = new ZilForm(new[] { quoteAtom!, arg }); } if (argDecls[i] != null) { - arg = new ZilAdecl(arg, argDecls[i]); + arg = new ZilAdecl(arg, argDecls[i]!); } if (argDefaults[i] != null) @@ -811,23 +805,23 @@ namespace Zilf.Interpreter yield return arg; } - if (varargsAtom != null && !emittedVarargs) + if (VarargsAtom != null && !emittedVarargs) { yield return ZilString.FromString(varargsQuoted ? "ARGS" : "TUPLE"); if (varargsDecl == null) { - yield return varargsAtom; + yield return VarargsAtom; } else { - yield return new ZilAdecl(varargsAtom, varargsDecl); + yield return new ZilAdecl(VarargsAtom, varargsDecl); } } - if (activationAtom != null) + if (ActivationAtom != null) { yield return ZilString.FromString("NAME"); - yield return activationAtom; + yield return ActivationAtom; } if (valueDecl != null) @@ -837,16 +831,12 @@ namespace Zilf.Interpreter } } - [CanBeNull] - public ZilAtom Name => name; + public ZilAtom? Name { get; } - [CanBeNull] - public ZilAtom ActivationAtom => activationAtom; + public ZilAtom? ActivationAtom { get; } - [CanBeNull] - public ZilAtom EnvironmentAtom => environmentAtom; + public ZilAtom? EnvironmentAtom { get; } - [CanBeNull] - public ZilAtom VarargsAtom => varargsAtom; + public ZilAtom? VarargsAtom { get; } } } \ No newline at end of file diff --git a/src/Zilf/Interpreter/AssociationTable.cs b/src/Zilf/Interpreter/AssociationTable.cs index d5e4c67..bc239b5 100644 --- a/src/Zilf/Interpreter/AssociationTable.cs +++ b/src/Zilf/Interpreter/AssociationTable.cs @@ -38,7 +38,7 @@ namespace Zilf.Interpreter /// The second object in the pair. /// The associated value, or null if no value is associated with the pair. [System.Diagnostics.Contracts.Pure] - public ZilObject GetProp([NotNull] ZilObject first, [NotNull] ZilObject second) + public ZilObject? GetProp(ZilObject first, ZilObject second) { if (associations.TryGetValue(first, out var innerTable) && innerTable.TryGetValue(second, out var result)) return result; @@ -53,7 +53,7 @@ namespace Zilf.Interpreter /// The second object in the pair. /// The value to be associated with the pair, or /// null to clear the association. - public void PutProp([NotNull] ZilObject first, [NotNull] ZilObject second, [CanBeNull] ZilObject value) + public void PutProp(ZilObject first, ZilObject second, ZilObject? value) { if (value == null) { @@ -90,7 +90,6 @@ namespace Zilf.Interpreter } } - [NotNull] public AsocResult[] ToArray() { var result = new List(); diff --git a/src/Zilf/Interpreter/Binding.cs b/src/Zilf/Interpreter/Binding.cs index 2744fa2..37993cb 100644 --- a/src/Zilf/Interpreter/Binding.cs +++ b/src/Zilf/Interpreter/Binding.cs @@ -22,10 +22,10 @@ namespace Zilf.Interpreter { class Binding { - public ZilObject Value; - public ZilObject Decl; + public ZilObject? Value; + public ZilObject? Decl; - public Binding(ZilObject value) + public Binding(ZilObject? value) { Value = value; } diff --git a/src/Zilf/Interpreter/CallFrame.cs b/src/Zilf/Interpreter/CallFrame.cs index 7db612e..5c901e3 100644 --- a/src/Zilf/Interpreter/CallFrame.cs +++ b/src/Zilf/Interpreter/CallFrame.cs @@ -17,19 +17,16 @@ */ using Zilf.Interpreter.Values; -using JetBrains.Annotations; namespace Zilf.Interpreter { sealed class CallFrame : Frame { - [NotNull] public ZilForm CallingForm { get; } - [CanBeNull] - public override string Description => CallingForm.First?.ToString(); + public override string? Description => CallingForm.First?.ToString(); - public CallFrame([NotNull] Context ctx, [NotNull] ZilForm callingForm) + public CallFrame(Context ctx, ZilForm callingForm) : base(ctx, callingForm.SourceLine) { CallingForm = callingForm; diff --git a/src/Zilf/Interpreter/Context.cs b/src/Zilf/Interpreter/Context.cs index 3c27a9f..55fabc4 100644 --- a/src/Zilf/Interpreter/Context.cs +++ b/src/Zilf/Interpreter/Context.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; @@ -45,12 +46,10 @@ namespace Zilf.Interpreter [PublicAPI] class ZValEventArgs : EventArgs { - [NotNull] public ZilAtom Name { get; } - [CanBeNull] - public ZilObject NewValue { get; } + public ZilObject? NewValue { get; } - public ZValEventArgs([NotNull] ZilAtom name, [CanBeNull] ZilObject newValue) + public ZValEventArgs(ZilAtom name, ZilObject? newValue) { Name = name; NewValue = newValue; @@ -65,19 +64,20 @@ namespace Zilf.Interpreter abstract class TypeMapEntry { - public Type BuiltinType { get; set; } + public Type? BuiltinType { get; set; } public bool IsBuiltin => BuiltinType != null; public PrimType PrimType { get; set; } - public ChtypeDelegate ChtypeMethod { get; set; } + [System.Diagnostics.CodeAnalysis.NotNull] + public ChtypeDelegate? ChtypeMethod { get; set; } - public ZilObject PrintType { get; set; } - public PrintTypeDelegate PrintTypeDelegate { get; set; } + public ZilObject? PrintType { get; set; } + public PrintTypeDelegate? PrintTypeDelegate { get; set; } - public ZilObject EvalType { get; set; } - public EvalTypeDelegate EvalTypeDelegate { get; set; } + public ZilObject? EvalType { get; set; } + public EvalTypeDelegate? EvalTypeDelegate { get; set; } - public ZilObject ApplyType { get; set; } - public ApplyTypeDelegate ApplyTypeDelegate { get; set; } + public ZilObject? ApplyType { get; set; } + public ApplyTypeDelegate? ApplyTypeDelegate { get; set; } } sealed class CustomTypeMapEntry : TypeMapEntry @@ -94,42 +94,25 @@ namespace Zilf.Interpreter interface IStaticTypeMapEntry { - [NotNull] - Type BuiltinType { get; } + Type? BuiltinType { get; } PrimType PrimType { get; } - [NotNull] TypeMapEntry Clone(); } - [NotNull] public DiagnosticManager DiagnosticManager { get; } - readonly bool ignoreCase; - [NotNull] - readonly List includePaths; - - [NotNull] - readonly ObList rootObList, compilationFlagsObList, hooksObList; - [NotNull] + readonly ObList compilationFlagsObList, hooksObList; readonly Stack previousObPaths; - [NotNull] LocalEnvironment localEnvironment; - [NotNull] readonly Dictionary globalValues; - [NotNull] readonly AssociationTable associations; - [NotNull] readonly Dictionary typeMap; - [NotNull] readonly Dictionary subrDelegates; - [NotNull] - readonly ZEnvironment zenv; /// /// Gets a value representing truth (the atom T). /// - [NotNull] public ZilObject TRUE { get; } /// /// Gets a value representing falsehood (a FALSE object with an empty list). @@ -141,7 +124,7 @@ namespace Zilf.Interpreter /// public Frame TopFrame { get; private set; } - public event EventHandler ZValChanged; + public event EventHandler? ZValChanged; readonly ZilAtom[] stdAtoms; @@ -152,7 +135,7 @@ namespace Zilf.Interpreter public Context(bool ignoreCase) { - this.ignoreCase = ignoreCase; + this.IgnoreCase = ignoreCase; this.DiagnosticManager = new DiagnosticManager(); this.DiagnosticManager.TooManyErrors += (sender, args) => @@ -167,11 +150,11 @@ namespace Zilf.Interpreter CurrentFile = new FileContext(this, ""); // set up the ROOT oblist manually - rootObList = new ObList(ignoreCase); + RootObList = new ObList(ignoreCase); stdAtoms = InitStdAtoms(); associations = new AssociationTable(); - PutProp(rootObList, GetStdAtom(StdAtom.OBLIST), GetStdAtom(StdAtom.ROOT)); - PutProp(GetStdAtom(StdAtom.ROOT), GetStdAtom(StdAtom.OBLIST), rootObList); + PutProp(RootObList, GetStdAtom(StdAtom.OBLIST), GetStdAtom(StdAtom.ROOT)); + PutProp(GetStdAtom(StdAtom.ROOT), GetStdAtom(StdAtom.OBLIST), RootObList); // now we can use MakeObList PackageObList = MakeObList(GetStdAtom(StdAtom.PACKAGE)); @@ -183,9 +166,9 @@ namespace Zilf.Interpreter typeMap = new Dictionary(); subrDelegates = new Dictionary(); - zenv = new ZEnvironment(this); + ZEnvironment = new ZEnvironment(this); - includePaths = new List(); + IncludePaths = new List(); InitTypeMap(); @@ -199,7 +182,7 @@ namespace Zilf.Interpreter // initialize OBLIST path: only the root oblist for now var olatom = GetStdAtom(StdAtom.OBLIST); - var olpath = new ZilList(new ZilObject[] { rootObList }); + var olpath = new ZilList(new ZilObject[] { RootObList }); localEnvironment.Rebind(olatom, olpath); // InitSubrs uses ArgDecoder, which parses DECLs and needs the OBLIST path @@ -224,20 +207,17 @@ namespace Zilf.Interpreter localEnvironment.Rebind(olatom, new ZilList(userObList, olpath)); } - [NotNull] - public ObList RootObList => rootObList; + public ObList RootObList { get; } - [NotNull] public ObList PackageObList { get; } public bool CheckDecls { get; set; } public RunMode RunMode { get; set; } - public bool IgnoreCase => ignoreCase; + public bool IgnoreCase { get; } - [NotNull] - public List IncludePaths => includePaths; + public List IncludePaths { get; } public bool Quiet { get; set; } @@ -247,12 +227,14 @@ namespace Zilf.Interpreter public bool WarningsAsErrors { + // ReSharper disable once UnusedMember.Global get => DiagnosticManager.WarningsAsErrors; set => DiagnosticManager.WarningsAsErrors = value; } public bool SuppressNoisyWarnings { + // ReSharper disable once UnusedMember.Global get => DiagnosticManager.SuppressNoisyWarnings; set => DiagnosticManager.SuppressNoisyWarnings = value; } @@ -263,11 +245,9 @@ namespace Zilf.Interpreter public int SuppressedWarningCount => DiagnosticManager.SuppressedWarningCount; - [NotNull] public IReadOnlyCollection Diagnostics => DiagnosticManager.Diagnostics; - [NotNull] - public ZEnvironment ZEnvironment => zenv; + public ZEnvironment ZEnvironment { get; } public FileContext CurrentFile { get; set; } @@ -276,10 +256,10 @@ namespace Zilf.Interpreter // TODO: merge AtTopLevel into Frame public bool AtTopLevel { get; set; } - public OpenFileDelegate InterceptOpenFile; - public FileExistsDelegate InterceptFileExists; + public OpenFileDelegate? InterceptOpenFile; + public FileExistsDelegate? InterceptFileExists; - public Stream OpenFile([NotNull] string filename, bool writing) + public Stream OpenFile(string filename, bool writing) { var intercept = InterceptOpenFile; if (intercept != null) @@ -291,44 +271,41 @@ namespace Zilf.Interpreter writing ? FileAccess.ReadWrite : FileAccess.Read); } - public bool FileExists([NotNull] string filename) + public bool FileExists(string filename) { return InterceptFileExists?.Invoke(filename) ?? File.Exists(filename); } - [ItemNotNull] - [NotNull] ZilAtom[] InitStdAtoms() { var ids = (StdAtom[])Enum.GetValues(typeof(StdAtom)); - var max = ids[ids.Length - 1]; + var max = ids[^1]; var newStdAtoms = new ZilAtom[(int)max + 1]; foreach (var sa in ids) { - if (sa != StdAtom.None) - { - var pname = Enum.GetName(typeof(StdAtom), sa); - Debug.Assert(pname != null, nameof(pname) + " != null"); - - var attrs = typeof(StdAtom).GetField(pname).GetCustomAttributes( - typeof(AtomAttribute), false); - if (attrs.Length > 0) - pname = ((AtomAttribute)attrs[0]).Name; - - var atom = new ZilAtom(pname, rootObList, sa); - rootObList[pname] = atom; - newStdAtoms[(int)sa] = atom; - } + if (sa == StdAtom.None) + continue; + + var pname = Enum.GetName(typeof(StdAtom), sa); + Debug.Assert(pname != null, nameof(pname) + " != null"); + + var attrs = typeof(StdAtom).GetField(pname)!.GetCustomAttributes( + typeof(AtomAttribute), false); + if (attrs.Length > 0) + pname = ((AtomAttribute)attrs[0]).Name; + + var atom = new ZilAtom(pname, RootObList, sa); + RootObList[pname] = atom; + newStdAtoms[(int)sa] = atom; } return newStdAtoms; } - [NotNull] - public ObList MakeObList([NotNull] ZilAtom name) + public ObList MakeObList(ZilAtom name) { - var result = new ObList(ignoreCase); + var result = new ObList(IgnoreCase); var oblistAtom = GetStdAtom(StdAtom.OBLIST); PutProp(name, oblistAtom, result); @@ -376,14 +353,12 @@ namespace Zilf.Interpreter } } - [CanBeNull] - public SubrDelegate GetSubrDelegate([NotNull] string name) + public SubrDelegate? GetSubrDelegate(string name) { subrDelegates.TryGetValue(name, out var result); return result.del; } - [NotNull] public IEnumerable<(string name, MethodInfo methodInfo, bool isFSubr)> GetSubrDefinitions() { return subrDelegates.Select(pair => (pair.Key, pair.Value.mi, pair.Value.isFSubr)); @@ -396,7 +371,7 @@ namespace Zilf.Interpreter SetGlobalVal(GetStdAtom(StdAtom.ZILF), TRUE); SetGlobalVal(GetStdAtom(StdAtom.ZIL_VERSION), ZilString.FromString(Program.GetBanner())); SetGlobalVal(GetStdAtom(StdAtom.PREDGEN), TRUE); - SetGlobalVal(GetStdAtom(StdAtom.PLUS_MODE), zenv.ZVersion > 3 ? TRUE : FALSE); + SetGlobalVal(GetStdAtom(StdAtom.PLUS_MODE), ZEnvironment.ZVersion > 3 ? TRUE : FALSE); SetGlobalVal(GetStdAtom(StdAtom.SIBREAKS), ZilString.FromString(",.\"")); // runtime constants @@ -422,7 +397,7 @@ namespace Zilf.Interpreter foreach (var (name, value) in parts) { - AddZConstant(rootObList[name], new ZilFix((int)value)); + AddZConstant(RootObList[name], new ZilFix((int)value)); } } @@ -444,23 +419,22 @@ namespace Zilf.Interpreter } catch (DeclCheckError) { - Debug.Assert(false, "default constant value doesn't match decl"); + Debug.Fail("default constant value doesn't match decl"); } } } /// value does not match the DECL for atom. - [NotNull] - public ZilConstant AddZConstant([NotNull] ZilAtom atom, [NotNull] ZilObject value) + public ZilConstant AddZConstant(ZilAtom atom, ZilObject value) { if (GetZVal(atom) != null) Redefine(atom); var constant = new ZilConstant(atom, value); - zenv.Constants.Add(constant); + ZEnvironment.Constants.Add(constant); SetZVal(atom, constant); SetGlobalVal(atom, value); - zenv.InternGlobalName(atom); + ZEnvironment.InternGlobalName(atom); return constant; } @@ -470,16 +444,9 @@ namespace Zilf.Interpreter /// /// The identifier of the standard atom. /// The atom. - [NotNull] - public ZilAtom GetStdAtom(StdAtom id) - { - return stdAtoms[(int)id]; - } - [CanBeNull] - public ZilObject GetProp([NotNull] ZilObject first, [NotNull] ZilObject second) - { - return associations.GetProp(first, second); - } + public ZilAtom GetStdAtom(StdAtom id) => stdAtoms[(int)id]; + + public ZilObject? GetProp(ZilObject first, ZilObject second) => associations.GetProp(first, second); /// /// Sets or clears the value associated with a pair of objects. @@ -488,7 +455,7 @@ namespace Zilf.Interpreter /// The second object in the pair. /// The value to be associated with the pair, or /// null to clear the association. - public void PutProp([NotNull] ZilObject first, [NotNull] ZilObject second, [CanBeNull] ZilObject value) + public void PutProp(ZilObject first, ZilObject second, ZilObject? value) { associations.PutProp(first, second, value); } @@ -497,22 +464,14 @@ namespace Zilf.Interpreter /// Gets an array of listing all active associations. /// /// The array. - [NotNull] - public AsocResult[] GetAllAssociations() - { - return associations.ToArray(); - } + public AsocResult[] GetAllAssociations() => associations.ToArray(); /// /// Gets the local value assigned to an atom. /// /// The atom. /// The local value, or null if no local value is assigned. - [CanBeNull] - public ZilObject GetLocalVal([NotNull] ZilAtom atom) - { - return localEnvironment.GetLocalVal(atom); - } + public ZilObject? GetLocalVal(ZilAtom atom) => localEnvironment.GetLocalVal(atom); /// /// Sets or clears the local value assigned to an atom. @@ -520,12 +479,11 @@ namespace Zilf.Interpreter /// The atom. /// The new local value, or null to clear the local value. /// value does not match the existing DECL for atom. - public void SetLocalVal([NotNull] ZilAtom atom, [CanBeNull] ZilObject value) + public void SetLocalVal(ZilAtom atom, ZilObject? value) { localEnvironment.SetLocalVal(atom, value); } - [NotNull] public LocalEnvironment PushEnvironment() { var result = new LocalEnvironment(this, localEnvironment); @@ -539,7 +497,7 @@ namespace Zilf.Interpreter throw new InvalidOperationException("no parent environment to restore"); } - public T ExecuteInEnvironment([NotNull] LocalEnvironment tempEnvironment, [NotNull] Func func) + public T ExecuteInEnvironment(LocalEnvironment tempEnvironment, Func func) { var prev = localEnvironment; try @@ -569,7 +527,7 @@ namespace Zilf.Interpreter var oblistAtom = GetStdAtom(StdAtom.OBLIST); var rootEnvironment = localEnvironment; - while (rootEnvironment.Parent != null && rootEnvironment.Parent.IsLocalBound(oblistAtom)) + while (rootEnvironment.Parent?.IsLocalBound(oblistAtom) == true) rootEnvironment = rootEnvironment.Parent; var macroEnv = new LocalEnvironment(this); @@ -587,19 +545,16 @@ namespace Zilf.Interpreter } } - [NotNull] public LocalEnvironment LocalEnvironment => localEnvironment; - [NotNull] - public Frame PushFrame([NotNull] ZilForm callingForm) + public Frame PushFrame(ZilForm callingForm) { var result = new CallFrame(this, callingForm); TopFrame = result; return result; } - [NotNull] - public Frame PushFrame([NotNull] ISourceLine sourceLine, [CanBeNull] string description = null) + public Frame PushFrame(ISourceLine sourceLine, string? description = null) { var result = new NativeFrame(this, sourceLine, description); TopFrame = result; @@ -616,8 +571,7 @@ namespace Zilf.Interpreter TopFrame = TopFrame.Parent; } - [NotNull] - public FileContext PushFileContext([NotNull] string path) + public FileContext PushFileContext(string path) { var result = new FileContext(this, path); CurrentFile = result; @@ -633,36 +587,28 @@ namespace Zilf.Interpreter CurrentFile = CurrentFile.Parent; } - public ZilObject GetGlobalVal(ZilAtom atom) - { - return globalValues.TryGetValue(atom, out var binding) ? binding.Value : null; - } - /// - /// Gets the global binding for an atom, optionally creating one if necessary. - /// - /// The atom. - /// to create the binding if it doesn't already exist. - /// The binding, or if it doesn't exist and is . - [ContractAnnotation("create: true => notnull")] - public Binding GetGlobalBinding([NotNull] ZilAtom atom, bool create) + public ZilObject? GetGlobalVal(ZilAtom atom) => + globalValues.TryGetValue(atom, out var binding) ? binding.Value : null; + + public bool TryGetGlobalBinding(ZilAtom atom, [NotNullWhen(true)] out Binding? binding) => + globalValues.TryGetValue(atom, out binding); + + public Binding EnsureGlobalBinding(ZilAtom atom) { - globalValues.TryGetValue(atom, out var binding); + if (globalValues.TryGetValue(atom, out var result)) + return result; - if (binding == null && create) - { - binding = new Binding(null); - globalValues.Add(atom, binding); - } + result = new Binding(null); + globalValues.Add(atom, result); - return binding; + return result; } /// /// Gets all the globally bound atoms and their values. /// /// A sequence of key-value pairs. - [NotNull] public IEnumerable> GetGlobalBindings() => globalValues; /// @@ -671,19 +617,17 @@ namespace Zilf.Interpreter /// The atom. /// The new global value, or null to clear the global value. /// does not match the DECL for . - public void SetGlobalVal([NotNull] ZilAtom atom, [CanBeNull] ZilObject value) + public void SetGlobalVal(ZilAtom atom, ZilObject? value) { if (value != null) { - var binding = GetGlobalBinding(atom, true); + var binding = EnsureGlobalBinding(atom); MaybeCheckDecl(value, binding.Decl, "GVAL of {0}", atom); binding.Value = value; } else { - var binding = GetGlobalBinding(atom, false); - - if (binding != null) + if (TryGetGlobalBinding(atom, out var binding)) binding.Value = null; } } @@ -698,8 +642,8 @@ namespace Zilf.Interpreter /// A parameter for . /// is , is non-null, and failed the check. [StringFormatMethod("usageFormat")] - public void MaybeCheckDecl(IProvideSourceLine src, [NotNull] ZilObject value, [CanBeNull] ZilObject pattern, - [NotNull] string usageFormat, [NotNull] object arg0) + public void MaybeCheckDecl(IProvideSourceLine src, ZilObject value, ZilObject? pattern, + string usageFormat, object arg0) { if (pattern != null && CheckDecls && !Decl.Check(this, value, pattern)) throw new DeclCheckError(src, this, value, pattern, usageFormat, arg0); @@ -714,18 +658,14 @@ namespace Zilf.Interpreter /// A parameter for . /// is , is non-null, and failed the check. [StringFormatMethod("usageFormat")] - public void MaybeCheckDecl([NotNull] ZilObject value, [CanBeNull] ZilObject pattern, [NotNull] string usageFormat, - [NotNull] object arg0) + public void MaybeCheckDecl(ZilObject value, ZilObject? pattern, string usageFormat, + object arg0) { if (pattern != null && CheckDecls && !Decl.Check(this, value, pattern)) throw new DeclCheckError(this, value, pattern, usageFormat, arg0); } - [CanBeNull] - public ZilObject GetZVal([NotNull] ZilAtom atom) - { - return GetProp(atom, GetStdAtom(StdAtom.ZVAL)); - } + public ZilObject? GetZVal(ZilAtom atom) => GetProp(atom, GetStdAtom(StdAtom.ZVAL)); /// /// Sets or clears the Z-code structure assigned to an atom. @@ -734,71 +674,61 @@ namespace Zilf.Interpreter /// The new value, or null to clear the value. /// This is equivalent to <PUTPROP atom ZVAL value> /// but also raises the event. - public void SetZVal([NotNull] ZilAtom atom, ZilObject value) + public void SetZVal(ZilAtom atom, ZilObject value) { PutProp(atom, GetStdAtom(StdAtom.ZVAL), value); ZValChanged?.Invoke(this, new ZValEventArgs(atom, value)); } - public bool GetGlobalOption(StdAtom stdAtom) - { - var value = GetGlobalVal(GetStdAtom(stdAtom)); - return value != null && value.IsTrue; - } - public bool AllowRedefine - { - get - { - var lval = GetLocalVal(GetStdAtom(StdAtom.REDEFINE)); - return lval != null && lval.IsTrue; - } - } - public void Redefine([NotNull] ZilAtom atom) - { - zenv.InternedGlobalNames.Remove(atom); + public bool GetGlobalOption(StdAtom stdAtom) => GetGlobalVal(GetStdAtom(stdAtom))?.IsTrue == true; + + public bool AllowRedefine => GetLocalVal(GetStdAtom(StdAtom.REDEFINE))?.IsTrue == true; - var obj = GetZVal(atom); + public void Redefine(ZilAtom atom) + { + ZEnvironment.InternedGlobalNames.Remove(atom); - switch (obj) + switch (GetZVal(atom)) { case ZilGlobal glob: - zenv.Globals.Remove(glob); + ZEnvironment.Globals.Remove(glob); break; case ZilRoutine rtn: - zenv.Routines.Remove(rtn); + ZEnvironment.Routines.Remove(rtn); break; case ZilModelObject zmo: - zenv.Objects.Remove(zmo); + ZEnvironment.Objects.Remove(zmo); break; case ZilConstant cnst: - zenv.Constants.Remove(cnst); + ZEnvironment.Constants.Remove(cnst); break; } } - public void HandleError([NotNull] ZilErrorBase ex) => DiagnosticManager.Handle(ex.Diagnostic); + public void HandleError(ZilErrorBase ex) => + DiagnosticManager.Handle(ex.Diagnostic ?? throw new ArgumentException("Missing diagnostic", nameof(ex))); /// The file wasn't found in any include path. - [NotNull] - public string FindIncludeFile([NotNull] string name) + public string FindIncludeFile(string name) { - foreach (var path in includePaths) + // ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator + foreach (var path in IncludePaths) { var combined = Path.Combine(path, name); if (FileExists(combined)) return combined; - if (string.IsNullOrEmpty(Path.GetExtension(combined))) - { - combined = Path.ChangeExtension(combined, ".zil"); - if (FileExists(combined)) - return combined; + if (!string.IsNullOrEmpty(Path.GetExtension(combined))) + continue; - combined = Path.ChangeExtension(combined, ".mud"); - if (FileExists(combined)) - return combined; - } + combined = Path.ChangeExtension(combined, ".zil"); + if (FileExists(combined)) + return combined; + + combined = Path.ChangeExtension(combined, ".mud"); + if (FileExists(combined)) + return combined; } throw new FileNotFoundException(); @@ -808,8 +738,7 @@ namespace Zilf.Interpreter /// Adapts a MethodInfo, describing a function that takes a /// specific ZilObject type and returns a ZilObject, to ChtypeDelegate. /// - [NotNull] - static ChtypeDelegate AdaptChtypeMethod1([NotNull] MethodInfo mi) + static ChtypeDelegate AdaptChtypeMethod1(MethodInfo mi) where T : ZilObject { var rawDel = Delegate.CreateDelegate(typeof(Func), mi); @@ -821,8 +750,7 @@ namespace Zilf.Interpreter /// Adapts a MethodInfo, describing a function that takes a context and a /// specific ZilObject type and returns a ZilObject, to ChtypeDelegate. /// - [NotNull] - static ChtypeDelegate AdaptChtypeMethod2([NotNull] MethodInfo mi) + static ChtypeDelegate AdaptChtypeMethod2(MethodInfo mi) where T : ZilObject { var rawDel = Delegate.CreateDelegate(typeof(Func), mi); @@ -837,8 +765,7 @@ namespace Zilf.Interpreter /// /// /// - [NotNull] - static ChtypeDelegate AdaptChtypeCtor([NotNull] ConstructorInfo ci) + static ChtypeDelegate AdaptChtypeCtor(ConstructorInfo ci) where T : ZilObject { var param1 = Expression.Parameter(typeof(Context), "ctx"); @@ -849,10 +776,8 @@ namespace Zilf.Interpreter return expr.Compile(); } - [NotNull] static IReadOnlyDictionary StaticTypeMap => InitStaticTypeMap(); - [NotNull] [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "ChtypeMethod")] static Dictionary InitStaticTypeMap() { @@ -863,14 +788,13 @@ namespace Zilf.Interpreter from a in t.GetCustomAttributes(false) select new { Type = t, Attr = a }; - Type primitiveClassType; - foreach (var r in query) { // look up chtype method Func adaptChtypeMethod1; Func adaptChtypeMethod2; Func adaptChtypeCtor; + Type primitiveClassType; switch (r.Attr.PrimType) { @@ -953,7 +877,6 @@ namespace Zilf.Interpreter $"Expected: ({primitiveClassType.Name}) or ({typeof(Context).Name}, {primitiveClassType.Namespace})\n" + $"Actual: ({string.Join(", ", foundParamTypes.Select(t => t.Name))})"); } - } else { @@ -999,25 +922,23 @@ namespace Zilf.Interpreter void InitTypeMap() { - foreach (var pair in StaticTypeMap) + foreach (var (atom, typeMapEntry) in StaticTypeMap) { - typeMap.Add(GetStdAtom(pair.Key), pair.Value.Clone()); + typeMap.Add(GetStdAtom(atom), typeMapEntry.Clone()); } // default custom types - var defaultCustomTypes = new[] { - new { Name = "BYTE", PrimType = PrimType.FIX }, - new { Name = "SEMI", PrimType = PrimType.STRING }, - new { Name = "VOC", PrimType = PrimType.ATOM } + var defaultCustomTypes = new[] + { + (Name: "BYTE", PrimType: PrimType.FIX), + (Name: "SEMI", PrimType: PrimType.STRING), + (Name: "VOC", PrimType: PrimType.ATOM) }; - foreach (var ct in defaultCustomTypes) + foreach (var (name, primType) in defaultCustomTypes) { // can't use ZilAtom.Parse here because the OBLIST path isn't set up - var atom = rootObList[ct.Name]; - var primType = ct.PrimType; - - RegisterType(atom, primType); + RegisterType(RootObList[name], primType); } } @@ -1028,7 +949,7 @@ namespace Zilf.Interpreter InitPropDefs(); } - public void RegisterType([NotNull] ZilAtom atom, PrimType primType) + public void RegisterType(ZilAtom atom, PrimType primType) { ChtypeDelegate chtypeDelegate; @@ -1038,11 +959,11 @@ namespace Zilf.Interpreter case PrimType.LIST: case PrimType.STRING: case PrimType.VECTOR: - chtypeDelegate = (ctx, zo) => new ZilStructuredHash(atom, primType, (IStructure)zo); + chtypeDelegate = (_, zo) => new ZilStructuredHash(atom, primType, (IStructure)zo); break; default: - chtypeDelegate = (ctx, zo) => new ZilHash(atom, primType, zo); + chtypeDelegate = (_, zo) => new ZilHash(atom, primType, zo); break; } @@ -1054,32 +975,21 @@ namespace Zilf.Interpreter typeMap.Add(atom, entry); } - public bool IsRegisteredType([NotNull] ZilAtom atom) - { - return typeMap.ContainsKey(atom); - } - [ItemNotNull] - [NotNull] + public bool IsRegisteredType(ZilAtom atom) => typeMap.ContainsKey(atom); + public IEnumerable RegisteredTypes => typeMap.Keys; - public static bool IsStructuredType(StdAtom atom) - { - return StaticTypeMap.TryGetValue(atom, out var entry) && - typeof(IStructure).IsAssignableFrom(entry.BuiltinType); - } - public static bool IsApplicableType(StdAtom atom) - { - return StaticTypeMap.TryGetValue(atom, out var entry) && - typeof(IApplicable).IsAssignableFrom(entry.BuiltinType); - } - public PrimType GetTypePrim([NotNull] ZilAtom type) - { - return typeMap[type].PrimType; - } - public static PrimType GetTypePrim(StdAtom type) - { - return StaticTypeMap[type].PrimType; - } + + public static bool IsStructuredType(StdAtom atom) => + StaticTypeMap.TryGetValue(atom, out var entry) && + typeof(IStructure).IsAssignableFrom(entry.BuiltinType); + + public static bool IsApplicableType(StdAtom atom) => + StaticTypeMap.TryGetValue(atom, out var entry) && + typeof(IApplicable).IsAssignableFrom(entry.BuiltinType); + public PrimType GetTypePrim(ZilAtom type) => typeMap[type].PrimType; + + public static PrimType GetTypePrim(StdAtom type) => StaticTypeMap[type].PrimType; public enum SetTypeHandlerResult { @@ -1089,7 +999,7 @@ namespace Zilf.Interpreter BadHandlerType, } - public SetTypeHandlerResult SetPrintType([NotNull] ZilAtom type, [NotNull] ZilObject handler) + public SetTypeHandlerResult SetPrintType(ZilAtom type, ZilObject handler) { return SetTypeHandler(type, handler, StdAtom.PRINT, @@ -1097,12 +1007,14 @@ namespace Zilf.Interpreter e => e.PrintTypeDelegate, (e, h) => e.PrintType = h, (e, d) => e.PrintTypeDelegate = d, - (ctx, t, otherType) => zo => ctx.ChangeType(zo, otherType).ToStringContext(ctx, false, true), + (ctx, _, otherType) => zo => ctx.ChangeType(zo, otherType).ToStringContext(ctx, false, true), (ctx, t, applicable) => zo => { var stringChannel = new ZilStringChannel(FileAccess.Write); var outchanAtom = ctx.GetStdAtom(StdAtom.OUTCHAN); - using (var innerEnv = ctx.PushEnvironment()) + + using var innerEnv = ctx.PushEnvironment(); + using (ctx.PushFrame(SourceLines.Unknown, $"")) { innerEnv.Rebind(outchanAtom, stringChannel); @@ -1112,7 +1024,7 @@ namespace Zilf.Interpreter }); } - public SetTypeHandlerResult SetEvalType([NotNull] ZilAtom type, [NotNull] ZilObject handler) + public SetTypeHandlerResult SetEvalType(ZilAtom type, ZilObject handler) { return SetTypeHandler(type, handler, StdAtom.EVAL, @@ -1130,7 +1042,7 @@ namespace Zilf.Interpreter }); } - public SetTypeHandlerResult SetApplyType([NotNull] ZilAtom type, [NotNull] ZilObject handler) + public SetTypeHandlerResult SetApplyType(ZilAtom type, ZilObject handler) { return SetTypeHandler(type, handler, StdAtom.APPLY, @@ -1138,10 +1050,9 @@ namespace Zilf.Interpreter e => e.ApplyTypeDelegate, (e, h) => e.ApplyType = h, (e, d) => e.ApplyTypeDelegate = d, - (ctx, t, otherType) => (zo, args) => + (ctx, _, otherType) => (zo, args) => { - var chtyped = ctx.ChangeType(zo, otherType).AsApplicable(ctx); - if (chtyped != null) + if (ctx.ChangeType(zo, otherType).IsApplicable(ctx, out var chtyped)) return chtyped.ApplyNoEval(ctx, args); throw new InterpreterError(InterpreterMessages.CHTYPE_To_0_Did_Not_Produce_An_Applicable_Object, otherType); }, @@ -1157,15 +1068,15 @@ namespace Zilf.Interpreter }); } - SetTypeHandlerResult SetTypeHandler([NotNull] ZilAtom type, [NotNull] ZilObject handler, + SetTypeHandlerResult SetTypeHandler(ZilAtom type, ZilObject handler, StdAtom clearIndicator, - Func getHandler, - Func getDelegate, - Action setHandler, - Action setDelegate, + Func getHandler, + Func getDelegate, + Action setHandler, + Action setDelegate, Func makeDelegateFromOtherType, Func makeDelegateFromApplicable) - where TDelegate : class + where TDelegate : Delegate { var entry = typeMap[type]; @@ -1200,56 +1111,56 @@ namespace Zilf.Interpreter return SetTypeHandlerResult.OK; } - if (handler.IsApplicable(this)) - { - // setting to means clearing - if (handler.ExactlyEquals(GetGlobalVal(GetStdAtom(clearIndicator)))) - { - setHandler(entry, null); - setDelegate(entry, null); - } - else - { - setHandler(entry, handler); - setDelegate(entry, makeDelegateFromApplicable(this, type, handler.AsApplicable(this))); - } - return SetTypeHandlerResult.OK; + if (!handler.IsApplicable(this, out var applicableHandler)) + return SetTypeHandlerResult.BadHandlerType; + + // setting to means clearing + if (handler.ExactlyEquals(GetGlobalVal(GetStdAtom(clearIndicator)))) + { + setHandler(entry, null); + setDelegate(entry, null); } - return SetTypeHandlerResult.BadHandlerType; + else + { + setHandler(entry, handler); + setDelegate(entry, makeDelegateFromApplicable(this, type, applicableHandler)); + } + + return SetTypeHandlerResult.OK; } - public ZilObject GetPrintType([NotNull] ZilAtom type) + public ZilObject? GetPrintType(ZilAtom type) { var entry = typeMap[type]; return entry.PrintType; } - public PrintTypeDelegate GetPrintTypeDelegate([NotNull] ZilAtom type) + public PrintTypeDelegate? GetPrintTypeDelegate(ZilAtom type) { var entry = typeMap[type]; return entry.PrintTypeDelegate; } - public ZilObject GetEvalType([NotNull] ZilAtom type) + public ZilObject? GetEvalType(ZilAtom type) { var entry = typeMap[type]; return entry.EvalType; } - public EvalTypeDelegate GetEvalTypeDelegate([NotNull] ZilAtom type) + public EvalTypeDelegate? GetEvalTypeDelegate(ZilAtom type) { var entry = typeMap[type]; return entry.EvalTypeDelegate; } - public ZilObject GetApplyType([NotNull] ZilAtom type) + public ZilObject? GetApplyType(ZilAtom type) { var entry = typeMap[type]; return entry.ApplyType; } - public ApplyTypeDelegate GetApplyTypeDelegate([NotNull] ZilAtom type) + public ApplyTypeDelegate? GetApplyTypeDelegate(ZilAtom type) { var entry = typeMap[type]; return entry.ApplyTypeDelegate; @@ -1296,11 +1207,12 @@ namespace Zilf.Interpreter if (typeMap.TryGetValue(newType, out var entry)) { if (value.PrimType != entry.PrimType) + { throw new InterpreterError( InterpreterMessages.CHTYPE_To_0_Requires_1, newType, entry.PrimType); + } - var result = entry.ChtypeMethod(this, value.GetPrimitive(this)); - return result; + return entry.ChtypeMethod(this, value.GetPrimitive(this)); } // unknown type @@ -1317,7 +1229,7 @@ C * B * "; - zenv.TellPatterns.AddRange(TellPattern.Parse(Program.Parse(this, STellPatterns))); + ZEnvironment.TellPatterns.AddRange(TellPattern.Parse(Program.Parse(this, STellPatterns))); } void InitCompilationFlags() @@ -1343,7 +1255,7 @@ B * } } - public void DefineCompilationFlag([NotNull] ZilAtom name, [NotNull] ZilObject value, bool redefine = false) + public void DefineCompilationFlag(ZilAtom name, ZilObject value, bool redefine = false) { if (GetCompilationFlagValue(name) == null) { @@ -1354,7 +1266,7 @@ B * <1 .A>) (T
)>)>> ) (T <1 .A>) (T )>)>>"; - Program.Evaluate(this, string.Format(MacrosTemplate, name.Text), true); + Program.Evaluate(this, string.Format(CultureInfo.InvariantCulture, MacrosTemplate, name.Text), true); // TODO: correct the source locations in the macros } else if (redefine) @@ -1362,26 +1274,19 @@ B * SetCompilationFlagValue(name, value); } } - public bool GetCompilationFlagOption(StdAtom stdAtom) - { - var value = GetCompilationFlagValue(GetStdAtom(stdAtom)); - return value != null && value.IsTrue; - } - [CanBeNull] - public ZilObject GetCompilationFlagValue([NotNull] ZilAtom atom) - { - return GetCompilationFlagValue(atom.Text); - } + public bool GetCompilationFlagOption(StdAtom stdAtom) => + GetCompilationFlagValue(GetStdAtom(stdAtom))?.IsTrue == true; - [CanBeNull] - public ZilObject GetCompilationFlagValue([NotNull] string name) + public ZilObject? GetCompilationFlagValue(ZilAtom atom) => GetCompilationFlagValue(atom.Text); + + public ZilObject? GetCompilationFlagValue(string name) { var atom = compilationFlagsObList[name]; return GetGlobalVal(atom); } - void SetCompilationFlagValue([NotNull] ZilAtom name, [CanBeNull] ZilObject value) + void SetCompilationFlagValue(ZilAtom name, ZilObject? value) { name = compilationFlagsObList[name.Text]; SetGlobalVal(name, value); @@ -1393,7 +1298,7 @@ B * /// /// The PROPDEFs are version-specific, so this should be called again after changing ; /// - public void InitPropDefs() + void InitPropDefs() { const string SDirectionsPropDef_V3 = @"'[ (DIR TO R:ROOM = @@ -1456,16 +1361,16 @@ B * ) ]"; - InitPropDef(StdAtom.DIRECTIONS, zenv.ZVersion == 3 ? SDirectionsPropDef_V3 : SDirectionsPropDef_V4_Etc); + InitPropDef(StdAtom.DIRECTIONS, ZEnvironment.ZVersion == 3 ? SDirectionsPropDef_V3 : SDirectionsPropDef_V4_Etc); } - void InitPropDef(StdAtom propName, [NotNull] string def) + void InitPropDef(StdAtom propName, string def) { Program.Evaluate(this, ")>"); ZilVector vector; try { - vector = (ZilVector)Program.Evaluate(this, def, true); + vector = (ZilVector)Program.Evaluate(this, def, true)!; Debug.Assert(vector != null, "empty initial PROPDEF"); } finally @@ -1476,17 +1381,16 @@ B * SetPropDef(GetStdAtom(propName), pattern); } - public void SetPropDef([NotNull] ZilAtom propName, [NotNull] ComplexPropDef pattern) + public void SetPropDef(ZilAtom propName, ComplexPropDef pattern) { - foreach (var pair in pattern.GetConstants(this)) + foreach (var (name, value) in pattern.GetConstants(this)) { - AddZConstant(pair.Key, new ZilFix(pair.Value)); + AddZConstant(name, new ZilFix(value)); } PutProp(propName, GetStdAtom(StdAtom.PROPSPEC), pattern); } - [NotNull] - public Stream OpenChannelStream([NotNull] string path, FileAccess fileAccess) + public Stream OpenChannelStream(string path, FileAccess fileAccess) { if (TopFrame.SourceLine is FileSourceLine fileSourceLine) { @@ -1495,21 +1399,12 @@ B * path = Path.Combine(dir, path); } - FileMode mode; - switch (fileAccess) + var mode = fileAccess switch { - case FileAccess.ReadWrite: - mode = FileMode.OpenOrCreate; - break; - - case FileAccess.Write: - mode = FileMode.Create; - break; - - default: - mode = FileMode.Open; - break; - } + FileAccess.ReadWrite => FileMode.OpenOrCreate, + FileAccess.Write => FileMode.Create, + _ => FileMode.Open + }; return new FileStream(path, mode, fileAccess); } @@ -1518,7 +1413,7 @@ B * /// Pushes a new LVAL for the atom OBLIST, to be used for looking up atoms. ///
/// A list to serve as the new LVAL of OBLIST. - public void PushObPath([NotNull] ZilList newObPath) + public void PushObPath(ZilList newObPath) { var atom = GetStdAtom(StdAtom.OBLIST); var old = GetLocalVal(atom) ?? new ZilList(null, null); @@ -1534,8 +1429,7 @@ B * /// /// The current LVAL of OBLIST, or if it's currently unassigned. /// There was no previous LVAL of OBLIST. - [CanBeNull] - public ZilObject PopObPath() + public ZilObject? PopObPath() { var atom = GetStdAtom(StdAtom.OBLIST); var old = GetLocalVal(atom); @@ -1548,22 +1442,16 @@ B * } // ReSharper restore ExceptionNotThrown - [CanBeNull] - public ZilActivation GetEnclosingProgActivation() - { - return GetLocalVal(EnclosingProgActivationAtom) as ZilActivation; - } + public ZilActivation? GetEnclosingProgActivation() => GetLocalVal(EnclosingProgActivationAtom) as ZilActivation; - [NotNull] public ZilAtom EnclosingProgActivationAtom { get; } - [CanBeNull] - public ZilObject RunHook([NotNull] string name, [ItemNotNull] [NotNull] params ZilObject[] args) + public ZilObject? RunHook(string name, params ZilObject[] args) { var hook = GetGlobalVal(hooksObList[name]); // ReSharper disable once PatternAlwaysOfType - if (hook != null && hook.AsApplicable(this) is IApplicable applicable) + if (hook != null && hook.IsApplicable(this, out var applicable)) { return (ZilObject)applicable.ApplyNoEval(this, args); } @@ -1576,18 +1464,12 @@ B * { get { - switch (GetGlobalVal(GetStdAtom(StdAtom.DO_FUNNY_RETURN_P))?.IsTrue) + return GetGlobalVal(GetStdAtom(StdAtom.DO_FUNNY_RETURN_P))?.IsTrue switch { - case true: - return ReturnQuirkMode.PreferRoutine; - - case false: - return ReturnQuirkMode.PreferBlock; - - case null: - default: - return ReturnQuirkMode.ByVersion; - } + true => ReturnQuirkMode.PreferRoutine, + false => ReturnQuirkMode.PreferBlock, + _ => ReturnQuirkMode.ByVersion + }; } } diff --git a/src/Zilf/Interpreter/FileContext.cs b/src/Zilf/Interpreter/FileContext.cs index c95e0cd..354a5bf 100644 --- a/src/Zilf/Interpreter/FileContext.cs +++ b/src/Zilf/Interpreter/FileContext.cs @@ -29,9 +29,9 @@ namespace Zilf.Interpreter public string Path { get; } public FileFlags Flags { get; set; } - public ZilList DefStructDefaults { get; set; } + public ZilList? DefStructDefaults { get; set; } - public FileContext([NotNull] Context ctx, [NotNull] string path) + public FileContext(Context ctx, string path) { Context = ctx; Parent = ctx.CurrentFile; diff --git a/src/Zilf/Interpreter/Frame.cs b/src/Zilf/Interpreter/Frame.cs index e6bd05a..082fc87 100644 --- a/src/Zilf/Interpreter/Frame.cs +++ b/src/Zilf/Interpreter/Frame.cs @@ -19,28 +19,25 @@ using System; using Zilf.Interpreter.Values; using Zilf.Language; -using JetBrains.Annotations; namespace Zilf.Interpreter { abstract class Frame : IDisposable { - [NotNull] public Context Context { get; } public Frame Parent { get; } - [NotNull] public ISourceLine SourceLine { get; } - public abstract string Description { get; } + public abstract string? Description { get; } - protected Frame([NotNull] Context ctx, [NotNull] ZilForm callingForm) + protected Frame(Context ctx, ZilForm callingForm) { Context = ctx; Parent = ctx.TopFrame; SourceLine = callingForm.SourceLine; } - protected Frame([NotNull] Context ctx, [NotNull] ISourceLine sourceLine) + protected Frame(Context ctx, ISourceLine sourceLine) { Context = ctx; Parent = ctx.TopFrame; diff --git a/src/Zilf/Interpreter/IApplicable.cs b/src/Zilf/Interpreter/IApplicable.cs index 121effe..24ae173 100644 --- a/src/Zilf/Interpreter/IApplicable.cs +++ b/src/Zilf/Interpreter/IApplicable.cs @@ -30,7 +30,7 @@ namespace Zilf.Interpreter /// The current context. /// The unevaluated arguments. /// The result of the application. - ZilResult Apply([NotNull] [ProvidesContext] Context ctx, [ItemNotNull] [NotNull] ZilObject[] args); + ZilResult Apply([ProvidesContext] Context ctx, ZilObject[] args); /// /// Applies the object to the given arguments, without evaluating or expanding them. @@ -38,6 +38,6 @@ namespace Zilf.Interpreter /// The current context. /// The arguments. /// The result of the application. - ZilResult ApplyNoEval([NotNull] [ProvidesContext] Context ctx, [ItemNotNull] [NotNull] ZilObject[] args); + ZilResult ApplyNoEval([ProvidesContext] Context ctx, ZilObject[] args); } } \ No newline at end of file diff --git a/src/Zilf/Interpreter/IMayExpand.cs b/src/Zilf/Interpreter/IMayExpand.cs index 30e3f64..4c1c67e 100644 --- a/src/Zilf/Interpreter/IMayExpand.cs +++ b/src/Zilf/Interpreter/IMayExpand.cs @@ -17,7 +17,6 @@ */ using System.Collections.Generic; -using JetBrains.Annotations; using Zilf.Interpreter.Values; namespace Zilf.Interpreter @@ -25,14 +24,12 @@ namespace Zilf.Interpreter interface IMayExpandBeforeEvaluation { bool ShouldExpandBeforeEvaluation { get; } - [NotNull] - IEnumerable ExpandBeforeEvaluation(Context ctx, LocalEnvironment env); + IEnumerable ExpandBeforeEvaluation(Context ctx, LocalEnvironment? env); } interface IMayExpandAfterEvaluation { bool ShouldExpandAfterEvaluation { get; } - [NotNull] IEnumerable ExpandAfterEvaluation(); } } diff --git a/src/Zilf/Interpreter/IStructure.cs b/src/Zilf/Interpreter/IStructure.cs index 45cef33..714a63b 100644 --- a/src/Zilf/Interpreter/IStructure.cs +++ b/src/Zilf/Interpreter/IStructure.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using JetBrains.Annotations; using Zilf.Interpreter.Values; @@ -26,19 +27,21 @@ namespace Zilf.Interpreter [ParamDesc("structure")] interface IStructure : IEnumerable { + // TODO: replace null-returning IStructure methods with "TryGet" equivalents? + /// /// Gets the first element of the structure. /// /// The first element, or null if the structure is empty. - [CanBeNull] - ZilObject GetFirst(); + ZilObject? GetFirst(); + /// /// Gets the remainder of the structure, after skipping the first few elements. /// /// The number of elements to skip. /// A structure containing the unskipped elements, or null if no elements are left. - [CanBeNull] - IStructure GetRest(int skip); + IStructure? GetRest(int skip); + /// /// Reverses , returning a larger structure with some of the /// previously skipped elements included. @@ -48,8 +51,8 @@ namespace Zilf.Interpreter /// have been skipped. /// The operation is not supported by this /// structure type. - [CanBeNull] - IStructure GetBack(int skip); + IStructure? GetBack(int skip); + /// /// Completely reverses , returning all elements of the underlying /// structure. @@ -57,7 +60,6 @@ namespace Zilf.Interpreter /// A structure. /// The operation is not supported by this /// structure type. - [NotNull] IStructure GetTop(); /// @@ -66,7 +68,7 @@ namespace Zilf.Interpreter /// The number of elements to add at the end. /// The number of elements to add at the beginning. /// The initial value of the new elements. - void Grow(int end, int beginning, [NotNull] ZilObject defaultValue); + void Grow(int end, int beginning, ZilObject defaultValue); /// /// Gets a value indicating whether the structure is empty. @@ -87,13 +89,11 @@ namespace Zilf.Interpreter /// /// The structure is read-only. /// + [MaybeNull] ZilObject this[int index] { - [CanBeNull] [System.Diagnostics.Contracts.Pure] get; - - [NotNull] set; } @@ -104,6 +104,7 @@ namespace Zilf.Interpreter /// This method may loop indefinitely if the structure contains /// a reference to itself. int GetLength(); + /// /// Measures the length of the structure, up to a specified maximum. /// diff --git a/src/Zilf/Interpreter/LocalEnvironment.cs b/src/Zilf/Interpreter/LocalEnvironment.cs index 33a8084..10e737d 100644 --- a/src/Zilf/Interpreter/LocalEnvironment.cs +++ b/src/Zilf/Interpreter/LocalEnvironment.cs @@ -30,10 +30,8 @@ namespace Zilf.Interpreter /// class LocalEnvironment : IDisposable { - [NotNull] readonly Context ctx; - [NotNull] readonly Dictionary bindings = new Dictionary(); /// @@ -43,7 +41,7 @@ namespace Zilf.Interpreter /// The parent environment, or to not inherit any bindings. /// Changes made to bindings in the parent environment will be visible in the new environment, /// unless overridden by bindings created in the new environment with . - public LocalEnvironment([NotNull] Context ctx, [CanBeNull] LocalEnvironment parent = null) + public LocalEnvironment(Context ctx, LocalEnvironment? parent = null) { this.ctx = ctx ?? throw new ArgumentNullException(nameof(ctx)); Parent = parent; @@ -67,18 +65,15 @@ namespace Zilf.Interpreter /// /// Gets the parent environment, or if the environment was created without inheritance. /// - [CanBeNull] - public LocalEnvironment Parent { get; } + public LocalEnvironment? Parent { get; } - [CanBeNull] [System.Diagnostics.Contracts.Pure] - Binding MaybeGetBinding([NotNull] ZilAtom atom) + Binding? MaybeGetBinding(ZilAtom atom) { return bindings.TryGetValue(atom, out var result) ? result : Parent?.MaybeGetBinding(atom); } - [NotNull] - Binding GetOrCreateBinding([NotNull] ZilAtom atom) + Binding GetOrCreateBinding(ZilAtom atom) { var result = MaybeGetBinding(atom); @@ -98,7 +93,7 @@ namespace Zilf.Interpreter /// if the atom is bound in this environment or any parent environment, /// or if the atom is unbound. [System.Diagnostics.Contracts.Pure] - public bool IsLocalBound([NotNull] ZilAtom atom) + public bool IsLocalBound(ZilAtom atom) { return MaybeGetBinding(atom) != null; } @@ -109,8 +104,7 @@ namespace Zilf.Interpreter /// The atom. /// The value assigned to the atom in this environment, or the nearest parent environment /// in which it was bound, or if the atom is unbound or unassigned. - [CanBeNull] - public ZilObject GetLocalVal([NotNull] ZilAtom atom) + public ZilObject? GetLocalVal(ZilAtom atom) { return MaybeGetBinding(atom)?.Value; } @@ -124,7 +118,7 @@ namespace Zilf.Interpreter /// exist in a parent environment. If the atom is unbound, a new binding will be created /// in this environment. /// does not match the existing DECL for . - public void SetLocalVal([NotNull] ZilAtom atom, [CanBeNull] ZilObject value) + public void SetLocalVal(ZilAtom atom, ZilObject? value) { var binding = GetOrCreateBinding(atom); @@ -148,7 +142,7 @@ namespace Zilf.Interpreter /// previously assigned value will be overwritten. /// This method does not check against any DECL. /// - public void Rebind([NotNull] ZilAtom atom, [CanBeNull] ZilObject value = null, [CanBeNull] ZilObject decl = null) + public void Rebind(ZilAtom atom, ZilObject? value = null, ZilObject? decl = null) { if (bindings.TryGetValue(atom, out var binding)) { @@ -164,7 +158,6 @@ namespace Zilf.Interpreter binding.Decl = decl; } - [ItemNotNull] private IEnumerable GetLookupPath() { yield return this; @@ -173,7 +166,6 @@ namespace Zilf.Interpreter yield return p; } - [NotNull, ItemNotNull] public IEnumerable GetVisibleAtoms() { return GetLookupPath().SelectMany(env => env.bindings.Keys).Distinct(); diff --git a/src/Zilf/Interpreter/NativeFrame.cs b/src/Zilf/Interpreter/NativeFrame.cs index 5e5bc32..cab4575 100644 --- a/src/Zilf/Interpreter/NativeFrame.cs +++ b/src/Zilf/Interpreter/NativeFrame.cs @@ -23,9 +23,9 @@ namespace Zilf.Interpreter { sealed class NativeFrame : Frame { - public override string Description { get; } + public override string? Description { get; } - public NativeFrame([NotNull] Context ctx, [NotNull] ISourceLine sourceLine, [CanBeNull] string description = null) + public NativeFrame(Context ctx, ISourceLine sourceLine, string? description = null) : base(ctx, sourceLine) { Description = description; diff --git a/src/Zilf/Interpreter/ObList.cs b/src/Zilf/Interpreter/ObList.cs index 3705e66..fa5268a 100644 --- a/src/Zilf/Interpreter/ObList.cs +++ b/src/Zilf/Interpreter/ObList.cs @@ -30,7 +30,6 @@ namespace Zilf.Interpreter [BuiltinType(StdAtom.OBLIST, PrimType.LIST)] class ObList : ZilTiedListBase { - [NotNull] readonly Dictionary dict = new Dictionary(); readonly bool ignoreCase; @@ -45,9 +44,8 @@ namespace Zilf.Interpreter } /// has the wrong number or types of elements. - [NotNull] [ChtypeMethod] - public static ObList FromList([NotNull] [ProvidesContext] Context ctx, [NotNull] ZilListoidBase list) + public static ObList FromList([ProvidesContext] Context ctx, ZilListoidBase list) { var result = new ObList(ctx.IgnoreCase); @@ -56,26 +54,26 @@ namespace Zilf.Interpreter switch (first) { case ZilListoidBase bucket: - { - foreach (var elem in bucket) { - switch (elem) + foreach (var elem in bucket) { - case ZilAtom atom: - result[atom.Text] = atom; - break; - - default: - throw new InterpreterError( - InterpreterMessages._0_In_1_Must_Be_2, - "elements", - "OBLIST bucket", - "atoms"); + switch (elem) + { + case ZilAtom atom: + result[atom.Text] = atom; + break; + + default: + throw new InterpreterError( + InterpreterMessages._0_In_1_Must_Be_2, + "elements", + "OBLIST bucket", + "atoms"); + } } - } - break; - } + break; + } default: throw new InterpreterError( @@ -93,7 +91,6 @@ namespace Zilf.Interpreter return TiedLayout.Create().WithCatchAll(x => x.BucketList); } - [NotNull] public ZilList BucketList { get @@ -110,14 +107,13 @@ namespace Zilf.Interpreter public override StdAtom StdTypeAtom => StdAtom.OBLIST; - public bool Contains([NotNull] string pname) + public bool Contains(string pname) { string key = ignoreCase ? pname.ToUpperInvariant() : pname; return dict.ContainsKey(key); } - [NotNull] - public ZilAtom this[[NotNull] string pname] + public ZilAtom this[string pname] { get { @@ -137,7 +133,7 @@ namespace Zilf.Interpreter } } - internal void Add([NotNull] ZilAtom newAtom) + internal void Add(ZilAtom newAtom) { var key = newAtom.Text; if (ignoreCase) @@ -146,7 +142,7 @@ namespace Zilf.Interpreter dict[key] = newAtom; } - internal void Remove([NotNull] ZilAtom atom) + internal void Remove(ZilAtom atom) { var key = atom.Text; if (ignoreCase) diff --git a/src/Zilf/Interpreter/Recursion.cs b/src/Zilf/Interpreter/Recursion.cs index 9996880..36e8782 100644 --- a/src/Zilf/Interpreter/Recursion.cs +++ b/src/Zilf/Interpreter/Recursion.cs @@ -23,7 +23,7 @@ namespace Zilf.Interpreter { static class Recursion { - static readonly ConditionalWeakTable table = new ConditionalWeakTable(); + static readonly ConditionalWeakTable table = new ConditionalWeakTable(); public static bool TryLock(object obj) { @@ -36,7 +36,7 @@ namespace Zilf.Interpreter return true; } - public static void Unlock([NotNull] object obj) + public static void Unlock(object obj) { table.Remove(obj); } diff --git a/src/Zilf/Interpreter/StructureExtensions.cs b/src/Zilf/Interpreter/StructureExtensions.cs index 107c134..f6738e4 100644 --- a/src/Zilf/Interpreter/StructureExtensions.cs +++ b/src/Zilf/Interpreter/StructureExtensions.cs @@ -17,6 +17,7 @@ */ using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using JetBrains.Annotations; using Zilf.Interpreter.Values; @@ -25,11 +26,11 @@ namespace Zilf.Interpreter static class StructureExtensions { [System.Diagnostics.Contracts.Pure] - public static bool HasLength([NotNull] this IStructure structure, int length) => + public static bool HasLength(this IStructure structure, int length) => structure.GetLength(length) == length; [System.Diagnostics.Contracts.Pure] - public static bool HasLength([NotNull] this IStructure structure, int min, int max) + public static bool HasLength(this IStructure structure, int min, int max) { Debug.Assert(min >= 0 && min < max); var len = structure.GetLength(max); @@ -37,11 +38,11 @@ namespace Zilf.Interpreter } [System.Diagnostics.Contracts.Pure] - public static bool HasLengthAtMost([NotNull] this IStructure structure, int max) => + public static bool HasLengthAtMost(this IStructure structure, int max) => structure.GetLength(max) != null; [System.Diagnostics.Contracts.Pure] - public static bool HasLengthAtLeast([NotNull] this IStructure structure, int min) + public static bool HasLengthAtLeast(this IStructure structure, int min) { var len = structure.GetLength(min); return len == null || len >= min; @@ -60,7 +61,7 @@ namespace Zilf.Interpreter /// or otherwise. [ContractAnnotation("=> true, obj1: notnull")] [ContractAnnotation("=> false, obj1: null")] - public static bool Matches([NotNull] this IStructure structure, [CanBeNull] out T1 obj1) + public static bool Matches(this IStructure structure, out T1? obj1) where T1 : ZilObject { if (structure.HasLength(1) && structure.GetFirst() is T1 elem1) @@ -86,7 +87,8 @@ namespace Zilf.Interpreter /// or otherwise. [ContractAnnotation("=> true, obj1: notnull, obj2: notnull")] [ContractAnnotation("=> false, obj1: null, obj2: null")] - public static bool Matches([NotNull] this IStructure structure, [CanBeNull] out T1 obj1, [CanBeNull] out T2 obj2) + public static bool Matches(this IStructure structure, [NotNullWhen(true)] out T1? obj1, + [NotNullWhen(true)] out T2? obj2) where T1 : ZilObject where T2 : ZilObject { @@ -117,13 +119,15 @@ namespace Zilf.Interpreter /// or otherwise. [ContractAnnotation("=> true, obj1: notnull, obj2: notnull, obj3: notnull")] [ContractAnnotation("=> false, obj1: null, obj2: null, obj3: null")] - public static bool Matches([NotNull] this IStructure structure, [CanBeNull] out T1 obj1, [CanBeNull] out T2 obj2, - [CanBeNull] out T3 obj3) + public static bool Matches(this IStructure structure, [NotNullWhen(true)] out T1? obj1, + [NotNullWhen(true)] out T2? obj2, + [NotNullWhen(true)] out T3? obj3) where T1 : ZilObject where T2 : ZilObject where T3 : ZilObject { - if (structure.HasLength(3) && structure[0] is T1 elem1 && structure[1] is T2 elem2 && structure[2] is T3 elem3) + if (structure.HasLength(3) && structure[0] is T1 elem1 && structure[1] is T2 elem2 && + structure[2] is T3 elem3) { obj1 = elem1; obj2 = elem2; @@ -154,14 +158,15 @@ namespace Zilf.Interpreter /// or otherwise. [ContractAnnotation("=> true, obj1: notnull, obj2: notnull, obj3: notnull, obj4: notnull")] [ContractAnnotation("=> false, obj1: null, obj2: null, obj3: null, obj4: null")] - public static bool Matches([NotNull] this IStructure structure, [CanBeNull] out T1 obj1, [CanBeNull] out T2 obj2, - [CanBeNull] out T3 obj3, [CanBeNull] out T4 obj4) + public static bool Matches(this IStructure structure, [NotNullWhen(true)] out T1? obj1, + [NotNullWhen(true)] out T2? obj2, [NotNullWhen(true)] out T3? obj3, [NotNullWhen(true)] out T4? obj4) where T1 : ZilObject where T2 : ZilObject where T3 : ZilObject where T4 : ZilObject { - if (structure.HasLength(4) && structure[0] is T1 elem1 && structure[1] is T2 elem2 && structure[2] is T3 elem3 && + if (structure.HasLength(4) && structure[0] is T1 elem1 && structure[1] is T2 elem2 && + structure[2] is T3 elem3 && structure[3] is T4 elem4) { obj1 = elem1; @@ -193,7 +198,7 @@ namespace Zilf.Interpreter /// or otherwise. [ContractAnnotation("=> true, obj1: notnull")] [ContractAnnotation("=> false, obj1: null")] - public static bool StartsWith([NotNull] this IStructure structure, [CanBeNull] out T1 obj1) + public static bool StartsWith(this IStructure structure, [NotNullWhen(true)] out T1? obj1) where T1 : ZilObject { if (structure.HasLengthAtLeast(1) && structure.GetFirst() is T1 elem1) @@ -219,7 +224,8 @@ namespace Zilf.Interpreter /// or otherwise. [ContractAnnotation("=> true, obj1: notnull, obj2: notnull")] [ContractAnnotation("=> false, obj1: null, obj2: null")] - public static bool StartsWith([NotNull] this IStructure structure, [CanBeNull] out T1 obj1, [CanBeNull] out T2 obj2) + public static bool StartsWith(this IStructure structure, [NotNullWhen(true)] out T1? obj1, + [NotNullWhen(true)] out T2? obj2) where T1 : ZilObject where T2 : ZilObject { @@ -235,82 +241,6 @@ namespace Zilf.Interpreter return false; } - /// - /// Tests whether a structure has the specified minimum number and types of elements, - /// and extracts the typed elements if so. - /// - /// The expected type of the first element. - /// The expected type of the second element. - /// The expected type of the third element. - /// The structure to test. - /// The first element, or if the match failed. - /// The second element, or if the match failed. - /// The third element, or if the match failed. - /// if the structure had the specified minimum number and types of elements, - /// or otherwise. - [ContractAnnotation("=> true, obj1: notnull, obj2: notnull, obj3: notnull")] - [ContractAnnotation("=> false, obj1: null, obj2: null, obj3: null")] - public static bool StartsWith([NotNull] this IStructure structure, [CanBeNull] out T1 obj1, [CanBeNull] out T2 obj2, - [CanBeNull] out T3 obj3) - where T1 : ZilObject - where T2 : ZilObject - where T3 : ZilObject - { - if (structure.HasLengthAtLeast(3) && structure[0] is T1 elem1 && structure[1] is T2 elem2 && structure[2] is T3 elem3) - { - obj1 = elem1; - obj2 = elem2; - obj3 = elem3; - return true; - } - - obj1 = default; - obj2 = default; - obj3 = default; - return false; - } - - /// - /// Tests whether a structure has the specified minimum number and types of elements, - /// and extracts the typed elements if so. - /// - /// The expected type of the first element. - /// The expected type of the second element. - /// The expected type of the third element. - /// The expected type of the fourth element. - /// The structure to test. - /// The first element, or if the match failed. - /// The second element, or if the match failed. - /// The third element, or if the match failed. - /// The fourth element, or if the match failed. - /// if the structure had the specified minimum number and types of elements, - /// or otherwise. - [ContractAnnotation("=> true, obj1: notnull, obj2: notnull, obj3: notnull, obj4: notnull")] - [ContractAnnotation("=> false, obj1: null, obj2: null, obj3: null, obj4: null")] - public static bool StartsWith([NotNull] this IStructure structure, [CanBeNull] out T1 obj1, [CanBeNull] out T2 obj2, - [CanBeNull] out T3 obj3, [CanBeNull] out T4 obj4) - where T1 : ZilObject - where T2 : ZilObject - where T3 : ZilObject - where T4 : ZilObject - { - if (structure.HasLengthAtLeast(4) && structure[0] is T1 elem1 && structure[1] is T2 elem2 && structure[2] is T3 elem3 && - structure[3] is T4 elem4) - { - obj1 = elem1; - obj2 = elem2; - obj3 = elem3; - obj4 = elem4; - return true; - } - - obj1 = default; - obj2 = default; - obj3 = default; - obj4 = default; - return false; - } - #endregion } } diff --git a/src/Zilf/Interpreter/Subrs.Atoms.cs b/src/Zilf/Interpreter/Subrs.Atoms.cs index af1a075..e6bb4b4 100644 --- a/src/Zilf/Interpreter/Subrs.Atoms.cs +++ b/src/Zilf/Interpreter/Subrs.Atoms.cs @@ -30,82 +30,76 @@ namespace Zilf.Interpreter [SuppressMessage("ReSharper", "InconsistentNaming")] static partial class Subrs { - [NotNull] [Subr] [Subr("PNAME")] - public static ZilObject SPNAME(Context ctx, [NotNull] ZilAtom atom) + public static ZilObject SPNAME(Context ctx, ZilAtom atom) { return ZilString.FromString(atom.Text); } [Subr] - public static ZilObject PARSE([NotNull] Context ctx, [NotNull] string text, [Decl("'10")] int radix = 10, - [CanBeNull] [Either(typeof(ObList), typeof(ZilList))] ZilObject lookupObList = null) + public static ZilObject PARSE(Context ctx, string text, [Decl("'10")] int radix = 10, + [Either(typeof(ObList), typeof(ZilList))] ZilObject lookupObList = null!) { return PerformParse(ctx, text, radix, lookupObList, "PARSE", true); } [Subr] - public static ZilObject LPARSE([NotNull] Context ctx, [NotNull] string text, [Decl("'10")] int radix = 10, - [CanBeNull] [Either(typeof(ObList), typeof(ZilList))] ZilObject lookupObList = null) + public static ZilObject LPARSE(Context ctx, string text, [Decl("'10")] int radix = 10, + [Either(typeof(ObList), typeof(ZilList))] ZilObject lookupObList = null!) { return PerformParse(ctx, text, radix, lookupObList, "LPARSE", false); } - static ZilObject PerformParse([NotNull] [ProvidesContext] Context ctx, [NotNull] string text, int radix, ZilObject lookupObList, - [NotNull] string name, bool singleResult) + static ZilObject PerformParse([ProvidesContext] Context ctx, string text, int radix, ZilObject lookupObList, + string name, bool singleResult) { if (radix != 10) throw new ArgumentOutOfRangeException(nameof(radix)); - using (var innerEnv = ctx.PushEnvironment()) + using var innerEnv = ctx.PushEnvironment(); + + if (lookupObList != null) { - if (lookupObList != null) - { - if (lookupObList is ObList) - lookupObList = new ZilList(lookupObList, new ZilList(null, null)); + if (lookupObList is ObList) + lookupObList = new ZilList(lookupObList, new ZilList(null, null)); - innerEnv.Rebind(ctx.GetStdAtom(StdAtom.OBLIST), lookupObList); - } + innerEnv.Rebind(ctx.GetStdAtom(StdAtom.OBLIST), lookupObList); + } - var ztree = Program.Parse(ctx, text); // TODO: move into FrontEnd class - if (singleResult) - { - try - { - return ztree.First(); - } - catch (InvalidOperationException ex) - { - throw new InterpreterError(InterpreterMessages._0_No_Expressions_Found, name, ex); - } - } + var ztree = Program.Parse(ctx, text); // TODO: move into FrontEnd class + if (!singleResult) return new ZilList(ztree); + + try + { + return ztree.First(); + } + catch (InvalidOperationException ex) + { + throw new InterpreterError(InterpreterMessages._0_No_Expressions_Found, name, ex); } } - [NotNull] [Subr] - public static ZilObject UNPARSE([NotNull] Context ctx, [NotNull] ZilObject arg) + public static ZilObject UNPARSE(Context ctx, ZilObject arg) { // in MDL, this takes an optional second argument (radix), but we don't bother return ZilString.FromString(arg.ToStringContext(ctx, false)); } - [NotNull] [Subr] - public static ZilObject LOOKUP([NotNull] Context ctx, [NotNull] string str, [NotNull] ObList oblist) + public static ZilObject LOOKUP(Context ctx, string str, ObList oblist) { return oblist.Contains(str) ? oblist[str] : ctx.FALSE; } /// already contains an atom named , or is an atom that is already on a different OBLIST. - [NotNull] [Subr] - public static ZilObject INSERT([NotNull] Context ctx, - [NotNull, Either(typeof(string), typeof(ZilAtom))] object stringOrAtom, - [NotNull] ObList oblist) + public static ZilObject INSERT(Context ctx, + [Either(typeof(string), typeof(ZilAtom))] object stringOrAtom, + ObList oblist) { switch (stringOrAtom) { @@ -143,10 +137,9 @@ namespace Zilf.Interpreter } #pragma warning restore CS0649 - [NotNull] [Subr] public static ZilObject REMOVE(Context ctx, - [NotNull] [Either(typeof(ZilAtom), typeof(RemoveParams.PnameAndObList), DefaultParamDesc = "atom")] object atomOrNameAndObList) + [Either(typeof(ZilAtom), typeof(RemoveParams.PnameAndObList), DefaultParamDesc = "atom")] object atomOrNameAndObList) { if (atomOrNameAndObList is ZilAtom atom) { @@ -174,7 +167,7 @@ namespace Zilf.Interpreter /// already contains an atom named . [Subr] - public static ZilObject LINK([NotNull] Context ctx, ZilObject value, [NotNull] string str, [NotNull] ObList oblist) + public static ZilObject LINK(Context ctx, ZilObject value, string str, ObList oblist) { if (oblist.Contains(str)) throw new InterpreterError(InterpreterMessages._0_OBLIST_Already_Contains_An_Atom_Named_1, "LINK", str); @@ -186,46 +179,40 @@ namespace Zilf.Interpreter return value; } - [NotNull] [Subr] - public static ZilObject ATOM(Context ctx, [NotNull] string pname) + public static ZilObject ATOM(Context ctx, string pname) { return new ZilAtom(pname, null, StdAtom.NONE); } - [NotNull] [Subr] - public static ZilObject ROOT([NotNull] Context ctx) + public static ZilObject ROOT(Context ctx) { return ctx.RootObList; } - [NotNull] [Subr] - public static ZilObject MOBLIST([NotNull] Context ctx, [NotNull] ZilAtom name) + public static ZilObject MOBLIST(Context ctx, ZilAtom name) { return ctx.GetProp(name, ctx.GetStdAtom(StdAtom.OBLIST)) as ObList ?? ctx.MakeObList(name); } - [NotNull] [Subr("OBLIST?")] - public static ZilObject OBLIST_P(Context ctx, [NotNull] ZilAtom atom) + public static ZilObject OBLIST_P(Context ctx, ZilAtom atom) { return atom.ObList ?? ctx.FALSE; } - [NotNull] [Subr] - public static ZilObject BLOCK([NotNull] Context ctx, [NotNull] ZilList list) + public static ZilObject BLOCK(Context ctx, ZilList list) { ctx.PushObPath(list); return list; } /// ENDBLOCK is not allowed here. - [NotNull] [Subr] - public static ZilObject ENDBLOCK([NotNull] Context ctx) + public static ZilObject ENDBLOCK(Context ctx) { try { @@ -239,30 +226,29 @@ namespace Zilf.Interpreter [Subr] [MdlZilRedirect(typeof(Subrs), nameof(GLOBAL), TopLevelOnly = true)] - public static ZilObject SETG([NotNull] Context ctx, [NotNull] ZilAtom atom, ZilObject value) + public static ZilObject SETG(Context ctx, ZilAtom atom, ZilObject value) { ctx.SetGlobalVal(atom, value); return value; } [Subr] - public static ZilObject SETG20([NotNull] Context ctx, [NotNull] ZilAtom atom, ZilObject value) + public static ZilObject SETG20(Context ctx, ZilAtom atom, ZilObject value) { ctx.SetGlobalVal(atom, value); return value; } [Subr] - public static ZilObject SET(Context ctx, [NotNull] ZilAtom atom, ZilObject value, [NotNull] LocalEnvironment env) + public static ZilObject SET(Context ctx, ZilAtom atom, ZilObject value, LocalEnvironment env) { env.SetLocalVal(atom, value); return value; } /// has no global value. - [NotNull] [Subr] - public static ZilObject GVAL([NotNull] Context ctx, [NotNull] ZilAtom atom) + public static ZilObject GVAL(Context ctx, ZilAtom atom) { var result = ctx.GetGlobalVal(atom); if (result == null) @@ -275,27 +261,22 @@ namespace Zilf.Interpreter return result; } - [NotNull] [Subr("GASSIGNED?")] - public static ZilObject GASSIGNED_P([NotNull] Context ctx, [NotNull] ZilAtom atom) + public static ZilObject GASSIGNED_P(Context ctx, ZilAtom atom) { return ctx.GetGlobalVal(atom) != null ? ctx.TRUE : ctx.FALSE; } - [NotNull] [Subr] - public static ZilObject GUNASSIGN([NotNull] Context ctx, [NotNull] ZilAtom atom) + public static ZilObject GUNASSIGN(Context ctx, ZilAtom atom) { ctx.SetGlobalVal(atom, null); return atom; } - [NotNull] [Subr("GBOUND?")] - public static ZilObject GBOUND_P([NotNull] Context ctx, [NotNull] ZilAtom atom) - { - return ctx.GetGlobalBinding(atom, false) != null ? ctx.TRUE : ctx.FALSE; - } + public static ZilObject GBOUND_P(Context ctx, ZilAtom atom) => + ctx.TryGetGlobalBinding(atom, out _) ? ctx.TRUE : ctx.FALSE; #pragma warning disable CS0649 public static class DeclParams @@ -315,15 +296,14 @@ namespace Zilf.Interpreter } #pragma warning restore CS0649 - [NotNull] [FSubr] - public static ZilObject GDECL([NotNull] Context ctx, [NotNull] DeclParams.AtomsDeclSequence[] pairs) + public static ZilObject GDECL(Context ctx, DeclParams.AtomsDeclSequence[] pairs) { foreach (var pair in pairs) { foreach (var atom in pair.Atoms.Atoms) { - var binding = ctx.GetGlobalBinding(atom, true); + var binding = ctx.EnsureGlobalBinding(atom); binding.Decl = pair.Decl; } } @@ -331,16 +311,12 @@ namespace Zilf.Interpreter return ctx.TRUE; } - [NotNull] [Subr("DECL?")] - public static ZilObject DECL_P([NotNull] Context ctx, [NotNull] ZilObject value, [NotNull] ZilObject pattern) - { - return Decl.Check(ctx, value, pattern) ? ctx.TRUE : ctx.FALSE; - } + public static ZilObject DECL_P(Context ctx, ZilObject value, ZilObject pattern) => + Decl.Check(ctx, value, pattern) ? ctx.TRUE : ctx.FALSE; - [NotNull] [Subr("DECL-CHECK")] - public static ZilObject DECL_CHECK([NotNull] Context ctx, bool enable) + public static ZilObject DECL_CHECK(Context ctx, bool enable) { var wasEnabled = ctx.CheckDecls; ctx.CheckDecls = enable; @@ -348,7 +324,7 @@ namespace Zilf.Interpreter } [Subr("GET-DECL")] - public static ZilResult GET_DECL(Context ctx, [NotNull] ZilObject item) + public static ZilResult GET_DECL(Context ctx, ZilObject item) { if (item is ZilOffset offset) return offset.StructurePattern; @@ -356,9 +332,8 @@ namespace Zilf.Interpreter return GETPROP(ctx, item, ctx.GetStdAtom(StdAtom.DECL)); } - [NotNull] [Subr("PUT-DECL")] - public static ZilObject PUT_DECL(Context ctx, [NotNull] ZilObject item, ZilObject pattern) + public static ZilObject PUT_DECL(Context ctx, ZilObject item, ZilObject pattern) { if (item is ZilOffset offset) return new ZilOffset(offset.Index, pattern, offset.ValuePattern); @@ -367,25 +342,25 @@ namespace Zilf.Interpreter } /// has no local value in . - [NotNull] [Subr] - public static ZilObject LVAL(Context ctx, [NotNull] ZilAtom atom, [NotNull] LocalEnvironment env) + public static ZilObject LVAL(Context ctx, ZilAtom atom, LocalEnvironment env) { var result = env.GetLocalVal(atom); if (result == null) + { throw new InterpreterError( InterpreterMessages._0_Atom_1_Has_No_2_Value, "LVAL", atom.ToStringContext(ctx, false), "local"); + } return result; } /// is - [NotNull] [Subr] - public static ZilObject UNASSIGN(Context ctx, [NotNull] ZilAtom atom, [NotNull] LocalEnvironment env) + public static ZilObject UNASSIGN(Context ctx, ZilAtom atom, LocalEnvironment env) { if (atom == null) throw new ArgumentNullException(nameof(atom)); @@ -396,47 +371,39 @@ namespace Zilf.Interpreter return atom; } - [NotNull] [Subr("ASSIGNED?")] - public static ZilObject ASSIGNED_P([NotNull] Context ctx, [NotNull] ZilAtom atom, [NotNull] LocalEnvironment env) - { - return env.GetLocalVal(atom) != null ? ctx.TRUE : ctx.FALSE; - } + public static ZilObject ASSIGNED_P(Context ctx, ZilAtom atom, LocalEnvironment env) => + env.GetLocalVal(atom) != null ? ctx.TRUE : ctx.FALSE; - [NotNull] [Subr("BOUND?")] - public static ZilObject BOUND_P([NotNull] Context ctx, [NotNull] ZilAtom atom, [NotNull] LocalEnvironment env) - { - return env.IsLocalBound(atom) ? ctx.TRUE : ctx.FALSE; - } + public static ZilObject BOUND_P(Context ctx, ZilAtom atom, LocalEnvironment env) => + env.IsLocalBound(atom) ? ctx.TRUE : ctx.FALSE; /// has no local or global value in . - [NotNull] [Subr] - public static ZilObject VALUE(Context ctx, [NotNull] ZilAtom atom, [NotNull] LocalEnvironment env) + public static ZilObject VALUE(Context ctx, ZilAtom atom, LocalEnvironment env) { var result = env.GetLocalVal(atom) ?? ctx.GetGlobalVal(atom); if (result == null) + { throw new InterpreterError( InterpreterMessages._0_Atom_1_Has_No_2_Value, "VALUE", atom.ToStringContext(ctx, false), "local or global"); + } return result; } [Subr] - public static ZilResult GETPROP([NotNull] Context ctx, [NotNull] ZilObject item, [NotNull] ZilObject indicator, - [CanBeNull] ZilObject defaultValue = null) - { - return ctx.GetProp(item, indicator) ?? defaultValue?.Eval(ctx) ?? ctx.FALSE; - } + public static ZilResult GETPROP(Context ctx, ZilObject item, ZilObject indicator, + ZilObject? defaultValue = null) => + ctx.GetProp(item, indicator) ?? defaultValue?.Eval(ctx) ?? ctx.FALSE; - [NotNull] [Subr] - public static ZilObject PUTPROP([NotNull] Context ctx, [NotNull] ZilObject item, [NotNull] ZilObject indicator, - [CanBeNull] ZilObject value = null) + public static ZilObject PUTPROP(Context ctx, ZilObject item, ZilObject indicator, + ZilObject? value = null) { if (value == null) { @@ -451,38 +418,24 @@ namespace Zilf.Interpreter return item; } - [NotNull] [Subr] - public static ZilObject ASSOCIATIONS([NotNull] Context ctx) + public static ZilObject ASSOCIATIONS(Context ctx) { var results = ctx.GetAllAssociations(); return results.Length > 0 ? new ZilAsoc(results, 0) : ctx.FALSE; } - [NotNull] [Subr] - public static ZilObject NEXT(Context ctx, [NotNull] ZilAsoc asoc) - { - return asoc.GetNext() ?? ctx.FALSE; - } + public static ZilObject NEXT(Context ctx, ZilAsoc asoc) => asoc.GetNext() ?? ctx.FALSE; [Subr] - public static ZilObject ITEM(Context ctx, [NotNull] ZilAsoc asoc) - { - return asoc.Item; - } + public static ZilObject ITEM(Context ctx, ZilAsoc asoc) => asoc.Item; [Subr] - public static ZilObject INDICATOR(Context ctx, [NotNull] ZilAsoc asoc) - { - return asoc.Indicator; - } + public static ZilObject INDICATOR(Context ctx, ZilAsoc asoc) => asoc.Indicator; [Subr] - public static ZilObject AVALUE(Context ctx, [NotNull] ZilAsoc asoc) - { - return asoc.Value; - } + public static ZilObject AVALUE(Context ctx, ZilAsoc asoc) => asoc.Value; } } diff --git a/src/Zilf/Interpreter/Subrs.Conditionals.cs b/src/Zilf/Interpreter/Subrs.Conditionals.cs index ef621ec..21e40c5 100644 --- a/src/Zilf/Interpreter/Subrs.Conditionals.cs +++ b/src/Zilf/Interpreter/Subrs.Conditionals.cs @@ -25,9 +25,9 @@ namespace Zilf.Interpreter static partial class Subrs { [FSubr] - public static ZilResult COND(Context ctx, [NotNull] [Required] CondClause[] clauses) + public static ZilResult COND(Context ctx, [Required] CondClause[] clauses) { - ZilResult result = null; + ZilResult result = ctx.FALSE; foreach (var clause in clauses) { @@ -35,17 +35,17 @@ namespace Zilf.Interpreter if (result.ShouldPass()) break; - if (((ZilObject)result).IsTrue) - { - foreach (var inner in clause.Body) - { - result = inner.Eval(ctx); - if (result.ShouldPass()) - break; - } + if (!((ZilObject)result).IsTrue) + continue; - break; + foreach (var inner in clause.Body) + { + result = inner.Eval(ctx); + if (result.ShouldPass()) + break; } + + break; } return result; @@ -61,7 +61,7 @@ namespace Zilf.Interpreter #pragma warning restore CS0649 [FSubr] - public static ZilResult OR([NotNull] Context ctx, [ItemNotNull] [NotNull] ZilObject[] args) + public static ZilResult OR(Context ctx, ZilObject[] args) { var resultObj = ctx.FALSE; @@ -81,7 +81,7 @@ namespace Zilf.Interpreter } [FSubr] - public static ZilResult AND([NotNull] Context ctx, [NotNull] [ItemNotNull] ZilObject[] args) + public static ZilResult AND(Context ctx, ZilObject[] args) { var resultObj = ctx.TRUE; diff --git a/src/Zilf/Interpreter/Subrs.DefStruct.cs b/src/Zilf/Interpreter/Subrs.DefStruct.cs index 2c762e0..2ef059d 100644 --- a/src/Zilf/Interpreter/Subrs.DefStruct.cs +++ b/src/Zilf/Interpreter/Subrs.DefStruct.cs @@ -24,16 +24,14 @@ using Zilf.Interpreter.Values; using Zilf.Language; using Zilf.Diagnostics; using Zilf.Common; -using JetBrains.Annotations; namespace Zilf.Interpreter { static partial class Subrs { // TODO: use ArgDecoder - [NotNull] [FSubr("SET-DEFSTRUCT-FILE-DEFAULTS")] - public static ZilObject SET_DEFSTRUCT_FILE_DEFAULTS([NotNull] Context ctx, [NotNull] ZilObject[] args) + public static ZilObject SET_DEFSTRUCT_FILE_DEFAULTS(Context ctx, ZilObject[] args) { var defaults = new ZilList(args); ctx.CurrentFile.DefStructDefaults = defaults; @@ -42,11 +40,12 @@ namespace Zilf.Interpreter struct DefStructDefaults { - public ZilAtom NthFunc, PutFunc, PrintFunc; + public ZilAtom NthFunc, PutFunc; + public ZilAtom? PrintFunc; public int StartOffset; public bool SuppressType, SuppressDefaultCtor, SuppressDecl; - public ZilList CustomCtorSpec; - public ZilList InitArgs; + public ZilList? CustomCtorSpec; + public ZilList? InitArgs; } struct DefStructField @@ -55,7 +54,7 @@ namespace Zilf.Interpreter public ZilAtom NthFunc, PutFunc; public int Offset; public ZilObject Decl; - public ZilObject Default; + public ZilObject? Default; public bool NoDefault; } @@ -173,12 +172,11 @@ namespace Zilf.Interpreter #pragma warning restore 649 /// A type named is already defined. - [NotNull] [FSubr] - public static ZilObject DEFSTRUCT([NotNull] Context ctx, [NotNull] ZilAtom name, - [NotNull] [Either(typeof(ZilAtom), typeof(DefStructParams.DefaultsList), DefaultParamDesc = "base-type")] + public static ZilObject DEFSTRUCT(Context ctx, ZilAtom name, + [Either(typeof(ZilAtom), typeof(DefStructParams.DefaultsList), DefaultParamDesc = "base-type")] object baseTypeOrDefaults, - [NotNull] [Required] + [Required] DefStructParams.FieldSpecList[] fieldSpecs) { // new type name @@ -301,8 +299,7 @@ namespace Zilf.Interpreter return name; } - [NotNull] - static ZilObject MakeDefstructDecl([NotNull] Context ctx, [NotNull] ZilAtom baseType, [NotNull] List fields) + static ZilObject MakeDefstructDecl(Context ctx, ZilAtom baseType, List fields) { if (ctx == null) throw new ArgumentNullException(nameof(ctx)); @@ -321,8 +318,8 @@ namespace Zilf.Interpreter return new ZilSegment(new ZilForm(parts)); } - static ZilObject MakeDefstructCustomCtorMacro([NotNull] Context ctx, ZilAtom ctorName, [NotNull] ZilAtom typeName, [NotNull] ZilAtom baseType, - [NotNull] List fields, [NotNull] ZilList initArgs, int startOffset, [NotNull] ArgSpec argspec) + static ZilObject MakeDefstructCustomCtorMacro(Context ctx, ZilAtom ctorName, ZilAtom typeName, ZilAtom baseType, + List fields, ZilList initArgs, int startOffset, ArgSpec argspec) { // {0} = constructor name // {1} = type name @@ -364,22 +361,22 @@ namespace Zilf.Interpreter { case ArgItem.ArgType.Required: resultInitializers.Add(Program.Parse( - ctx, - SRequiredArgInitializer, - new ZilFix(field.Offset - startOffset + 1), - arg.Atom, - field.Default ?? DefaultForDecl(ctx, field.Decl)) + ctx, + SRequiredArgInitializer, + new ZilFix(field.Offset - startOffset + 1), + arg.Atom, + field.Default ?? DefaultForDecl(ctx, field.Decl)) .Single()); break; case ArgItem.ArgType.Optional: case ArgItem.ArgType.Auxiliary: resultInitializers.Add(Program.Parse( - ctx, - SOptAuxArgInitializer, - new ZilFix(field.Offset - startOffset + 1), - arg.Atom, - field.Default ?? DefaultForDecl(ctx, field.Decl)) + ctx, + SOptAuxArgInitializer, + new ZilFix(field.Offset - startOffset + 1), + arg.Atom, + field.Default ?? DefaultForDecl(ctx, field.Decl)) .Single()); break; @@ -397,28 +394,27 @@ namespace Zilf.Interpreter // {1} = default value const string SOmittedFieldInitializer = ""; resultInitializers.Add(Program.Parse( - ctx, - SOmittedFieldInitializer, - new ZilFix(field.Offset - startOffset + 1), - field.Default) + ctx, + SOmittedFieldInitializer, + new ZilFix(field.Offset - startOffset + 1), + field.Default) .Single()); } return Program.Parse( - ctx, - SMacroTemplate, - ctorName, - typeName, - argspec.ToZilList(), - new ZilFix(fields.Count), - baseType, - initArgs, - new ZilList(resultInitializers)) + ctx, + SMacroTemplate, + ctorName, + typeName, + argspec.ToZilList(), + new ZilFix(fields.Count), + baseType, + initArgs, + new ZilList(resultInitializers)) .Single(); } - [NotNull] - static ZilObject DefaultForDecl([NotNull] Context ctx, [NotNull] ZilObject decl) + static ZilObject DefaultForDecl(Context ctx, ZilObject decl) { foreach (var zo in LikelyDefaults(ctx)) { @@ -430,7 +426,7 @@ namespace Zilf.Interpreter return ctx.FALSE; } - static IEnumerable LikelyDefaults([NotNull] Context ctx) + static IEnumerable LikelyDefaults(Context ctx) { yield return ctx.FALSE; yield return ZilFix.Zero; @@ -440,8 +436,8 @@ namespace Zilf.Interpreter yield return ctx.GetStdAtom(StdAtom.SORRY); } - static ZilObject MakeDefstructCtorMacro([NotNull] Context ctx, [NotNull] ZilAtom name, [NotNull] ZilAtom baseType, [NotNull] List fields, - [NotNull] ZilList initArgs, int startOffset) + static ZilObject MakeDefstructCtorMacro(Context ctx, ZilAtom name, ZilAtom baseType, List fields, + ZilList initArgs, int startOffset) { // the MAKE-[STRUCT] macro can be called with a parameter telling it to stuff values into an existing object: // @@ -548,57 +544,57 @@ namespace Zilf.Interpreter var orderFix = new ZilFix(definitionOrder); existingObjectDefaults.Add(Program.Parse( - ctx, - field.NoDefault ? SExistingObjectDefaultTemplate_NoDefault : SExistingObjectDefaultTemplate, - field.Name, field.PutFunc, actualOffset, orderFix, defaultValue) + ctx, + field.NoDefault ? SExistingObjectDefaultTemplate_NoDefault : SExistingObjectDefaultTemplate, + field.Name, field.PutFunc, actualOffset, orderFix, defaultValue) .Single()); newObjectDefaults.Add(Program.Parse( - ctx, - SNewObjectDefaultTemplate, - field.Name, field.PutFunc, adjustedOffset, orderFix, defaultValue) + ctx, + SNewObjectDefaultTemplate, + field.Name, field.PutFunc, adjustedOffset, orderFix, defaultValue) .Single()); boaConstructorDefaultClauses.Add(Program.Parse( - ctx, - SBoaConstructorDefaultClauseTemplate, - field.Name, field.PutFunc, adjustedOffset, orderFix, defaultValue) + ctx, + SBoaConstructorDefaultClauseTemplate, + field.Name, field.PutFunc, adjustedOffset, orderFix, defaultValue) .Single()); existingObjectClauses.Add(Program.Parse( - ctx, - SExistingObjectCondClauseTemplate, - field.Name, field.PutFunc, actualOffset, orderFix, defaultValue) + ctx, + SExistingObjectCondClauseTemplate, + field.Name, field.PutFunc, actualOffset, orderFix, defaultValue) .Single()); newObjectClauses.Add(Program.Parse( - ctx, - SNewObjectCondClauseTemplate, - field.Name, field.PutFunc, adjustedOffset, orderFix, defaultValue) + ctx, + SNewObjectCondClauseTemplate, + field.Name, field.PutFunc, adjustedOffset, orderFix, defaultValue) .Single()); boaConstructorClauses.Add(Program.Parse( - ctx, - SBoaConstructorCondClauseTemplate, - field.Name, field.PutFunc, adjustedOffset, orderFix, defaultValue) + ctx, + SBoaConstructorCondClauseTemplate, + field.Name, field.PutFunc, adjustedOffset, orderFix, defaultValue) .Single()); definitionOrder++; } return Program.Parse( - ctx, - SMacroTemplate, - name, - new ZilFix(fields.Count), - new ZilList(existingObjectClauses), - new ZilList(newObjectClauses), - baseType, - initArgs, - new ZilList(boaConstructorClauses), - new ZilList(boaConstructorDefaultClauses), - new ZilList(newObjectDefaults), - new ZilList(existingObjectDefaults)) + ctx, + SMacroTemplate, + name, + new ZilFix(fields.Count), + new ZilList(existingObjectClauses), + new ZilList(newObjectClauses), + baseType, + initArgs, + new ZilList(boaConstructorClauses), + new ZilList(boaConstructorDefaultClauses), + new ZilList(newObjectDefaults), + new ZilList(existingObjectDefaults)) .Single(); } - static ZilObject MakeDefstructAccessMacro([NotNull] Context ctx, [NotNull] ZilAtom structName, DefStructDefaults defaults, + static ZilObject MakeDefstructAccessMacro(Context ctx, ZilAtom structName, DefStructDefaults defaults, DefStructField field) { // {0} = field name @@ -638,14 +634,14 @@ namespace Zilf.Interpreter template = SFullCheckTemplate; return Program.Parse( - ctx, - template, - field.Name, - structName, - field.PutFunc, - field.NthFunc, - new ZilFix(field.Offset), - field.Decl) + ctx, + template, + field.Name, + structName, + field.PutFunc, + field.NthFunc, + new ZilFix(field.Offset), + field.Decl) .Single(); } @@ -727,15 +723,13 @@ namespace Zilf.Interpreter } // TODO: delete once SET-DEFSTRUCT-FILE-DEFAULTS is using ArgDecoder - static void ParseDefStructDefaults([NotNull] Context ctx, [NotNull] ZilList fileDefaults, ref DefStructDefaults defaults) + static void ParseDefStructDefaults(Context ctx, ZilList fileDefaults, ref DefStructDefaults defaults) { var quoteAtom = ctx.GetStdAtom(StdAtom.QUOTE); foreach (var part in fileDefaults) { - if (part is ZilForm partForm && - partForm.First == quoteAtom && - partForm.Rest.First is ZilAtom tag) + if (part is ZilForm { First: var qt, Rest: { First: ZilAtom tag } } && qt == quoteAtom) { switch (tag.StdAtom) { @@ -764,55 +758,63 @@ namespace Zilf.Interpreter if (!(part is ZilListoidBase partList && partList is ZilList)) throw new InterpreterError(InterpreterMessages._0_Parts_Of_Defaults_Section_Must_Be_Quoted_Atoms_Or_Lists, "DEFSTRUCT"); - if (!(partList.First is ZilForm first) || - first.First != quoteAtom || - !(first.Rest.First is ZilAtom tag2)) + //if (!(partList.First is ZilForm first) || + // first.First != quoteAtom || + // !(first.Rest.First is ZilAtom tag2)) + //{ + // throw new InterpreterError(InterpreterMessages._0_Lists_In_Defaults_Section_Must_Start_With_A_Quoted_Atom, "DEFSTRUCT"); + //} + + if (!(partList is { + First: ZilForm { First: var qt2, Rest: { First: ZilAtom tag2 } } partFirst, + Rest: {} partRest + } && qt2 == quoteAtom)) { - throw new InterpreterError(InterpreterMessages._0_Lists_In_Defaults_Section_Must_Start_With_A_Quoted_Atom, "DEFSTRUCT"); + throw new InterpreterError( + InterpreterMessages._0_Lists_In_Defaults_Section_Must_Start_With_A_Quoted_Atom, + "DEFSTRUCT"); } switch (tag2.StdAtom) { case StdAtom.NTH: - partList = partList.Rest; - defaults.NthFunc = partList.First as ZilAtom; - if (defaults.NthFunc == null) - throw new InterpreterError(InterpreterMessages._0_Expected_1_After_2, "DEFSTRUCT", "an atom", first); + defaults.NthFunc = partRest.First as ZilAtom ?? + throw new InterpreterError(InterpreterMessages._0_Expected_1_After_2, + "DEFSTRUCT", + "an atom", + partFirst); break; case StdAtom.PUT: - partList = partList.Rest; - defaults.PutFunc = partList.First as ZilAtom; - if (defaults.PutFunc == null) - throw new InterpreterError(InterpreterMessages._0_Expected_1_After_2, "DEFSTRUCT", "an atom", first); + defaults.PutFunc = partRest.First as ZilAtom ?? + throw new InterpreterError(InterpreterMessages._0_Expected_1_After_2, + "DEFSTRUCT", + "an atom", + partFirst); break; case StdAtom.START_OFFSET: - partList = partList.Rest; - if (!(partList.First is ZilFix fix)) - throw new InterpreterError(InterpreterMessages._0_Expected_1_After_2, "DEFSTRUCT", "a FIX", first); + if (!(partRest.First is ZilFix fix)) + throw new InterpreterError(InterpreterMessages._0_Expected_1_After_2, "DEFSTRUCT", "a FIX", partFirst); defaults.StartOffset = fix.Value; break; case StdAtom.PRINTTYPE: - partList = partList.Rest; - defaults.PrintFunc = partList.First as ZilAtom; + defaults.PrintFunc = partRest.First as ZilAtom; if (defaults.PrintFunc == null) - throw new InterpreterError(InterpreterMessages._0_Expected_1_After_2, "DEFSTRUCT", "an atom", first); + throw new InterpreterError(InterpreterMessages._0_Expected_1_After_2, "DEFSTRUCT", "an atom", partFirst); break; case StdAtom.CONSTRUCTOR: - partList = partList.Rest; - defaults.CustomCtorSpec = partList.AsZilList(); + defaults.CustomCtorSpec = partRest.AsZilList(); break; case StdAtom.INIT_ARGS: - partList = partList.Rest; - defaults.InitArgs = partList.AsZilList(); + defaults.InitArgs = partRest.AsZilList(); break; default: - throw new InterpreterError(InterpreterMessages._0_Unrecognized_1_2, "DEFSTRUCT", "tag in defaults section", first); + throw new InterpreterError(InterpreterMessages._0_Unrecognized_1_2, "DEFSTRUCT", "tag in defaults section", partFirst); } } } diff --git a/src/Zilf/Interpreter/Subrs.Functions.cs b/src/Zilf/Interpreter/Subrs.Functions.cs index 13b9e32..f83db1c 100644 --- a/src/Zilf/Interpreter/Subrs.Functions.cs +++ b/src/Zilf/Interpreter/Subrs.Functions.cs @@ -26,32 +26,29 @@ namespace Zilf.Interpreter { static partial class Subrs { - [NotNull] [FSubr] [MdlZilRedirect(typeof(Subrs), nameof(ROUTINE))] - public static ZilObject DEFINE([NotNull] Context ctx, [NotNull] ZilAtom name, - [CanBeNull] [Optional] ZilAtom activationAtom, [ItemNotNull] [NotNull] ZilList argList, - [CanBeNull] [Optional] ZilDecl decl, [ItemNotNull] [NotNull] [Required] ZilObject[] body) - { - return PerformDefine(ctx, name, activationAtom, argList, decl, body, "DEFINE"); - } + public static ZilObject DEFINE(Context ctx, ZilAtom name, + [Optional] ZilAtom? activationAtom, ZilList argList, + [Optional] ZilDecl? decl, [Required] ZilObject[] body) => + PerformDefine(ctx, name, activationAtom, argList, decl, body, "DEFINE"); - [NotNull] [FSubr] - public static ZilObject DEFINE20([NotNull] Context ctx, [NotNull] ZilAtom name, - [CanBeNull] [Optional] ZilAtom activationAtom, [NotNull] [ItemNotNull] ZilList argList, - [CanBeNull] [Optional] ZilDecl decl, [ItemCanBeNull] [NotNull] [Required] ZilObject[] body) + public static ZilObject DEFINE20(Context ctx, ZilAtom name, + [Optional] ZilAtom? activationAtom, ZilList argList, + [Optional] ZilDecl? decl, [Required] ZilObject[] body) { return PerformDefine(ctx, name, activationAtom, argList, decl, body, "DEFINE20"); } - [NotNull] - static ZilObject PerformDefine([NotNull] [ProvidesContext] Context ctx, [NotNull] ZilAtom name, - [CanBeNull] ZilAtom activationAtom, - [NotNull] ZilList argList, ZilDecl decl, [NotNull] ZilObject[] body, [NotNull] string subrName) + static ZilObject PerformDefine([ProvidesContext] Context ctx, ZilAtom name, + ZilAtom? activationAtom, + ZilList argList, ZilDecl? decl, ZilObject[] body, string subrName) { if (!ctx.AllowRedefine && ctx.GetGlobalVal(name) != null) - throw new InterpreterError(InterpreterMessages._0_Already_Defined_1, subrName, name.ToStringContext(ctx, false)); + throw new InterpreterError(InterpreterMessages._0_Already_Defined_1, + subrName, + name.ToStringContext(ctx, false)); var func = new ZilFunction( subrName, @@ -65,11 +62,10 @@ namespace Zilf.Interpreter } /// A global named is already defined. - [NotNull] [FSubr] - public static ZilObject DEFMAC([NotNull] Context ctx, [NotNull] ZilAtom name, - [CanBeNull] [Optional] ZilAtom activationAtom, [ItemNotNull] [NotNull] ZilList argList, - [CanBeNull] [Optional] ZilDecl decl, [NotNull] [Required] ZilObject[] body) + public static ZilObject DEFMAC(Context ctx, ZilAtom name, + [Optional] ZilAtom? activationAtom, ZilList argList, + [Optional] ZilDecl? decl, [Required] ZilObject[] body) { if (!ctx.AllowRedefine && ctx.GetGlobalVal(name) != null) throw new InterpreterError(InterpreterMessages._0_Already_Defined_1, "DEFMAC", name.ToStringContext(ctx, false)); @@ -93,22 +89,22 @@ namespace Zilf.Interpreter } [Subr] - public static ZilResult EVAL([NotNull] Context ctx, [NotNull] ZilObject value, [NotNull] LocalEnvironment env) + public static ZilResult EVAL(Context ctx, ZilObject value, LocalEnvironment env) { return value.Eval(ctx, env); } #pragma warning disable RECS0154 // Parameter is never used [Subr("EVAL-IN-SEGMENT")] - public static ZilResult EVAL_IN_SEGMENT([NotNull] Context ctx, ZilObject dummy1, - [NotNull] ZilObject value, [CanBeNull] ZilObject dummy2 = null) + public static ZilResult EVAL_IN_SEGMENT(Context ctx, ZilObject dummy1, + ZilObject value, ZilObject? dummy2 = null) #pragma warning restore RECS0154 // Parameter is never used { return value.Eval(ctx); } [Subr] - public static ZilResult EXPAND([NotNull] Context ctx, [NotNull] ZilObject value) + public static ZilResult EXPAND(Context ctx, ZilObject value) { var result = value.Expand(ctx); if (result.ShouldPass()) @@ -121,7 +117,7 @@ namespace Zilf.Interpreter } [Subr] - public static ZilResult APPLY([NotNull] Context ctx, [NotNull] IApplicable ap, [NotNull] ZilObject[] args) + public static ZilResult APPLY(Context ctx, IApplicable ap, ZilObject[] args) { return ap.ApplyNoEval(ctx, args); } diff --git a/src/Zilf/Interpreter/Subrs.Loops.cs b/src/Zilf/Interpreter/Subrs.Loops.cs index a0dc3b0..39e65f7 100644 --- a/src/Zilf/Interpreter/Subrs.Loops.cs +++ b/src/Zilf/Interpreter/Subrs.Loops.cs @@ -16,6 +16,7 @@ * along with ZILF. If not, see . */ +using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using Zilf.Interpreter.Values; @@ -53,7 +54,7 @@ namespace Zilf.Interpreter } } - public ZilObject Decl + public ZilObject? Decl { get { @@ -64,7 +65,7 @@ namespace Zilf.Interpreter } } - public ZilObject Initializer + public ZilObject? Initializer { get { @@ -86,38 +87,38 @@ namespace Zilf.Interpreter #pragma warning restore CS0649 [FSubr] - public static ZilResult PROG([NotNull] Context ctx, - [CanBeNull] [Optional] ZilAtom activationAtom, + public static ZilResult PROG(Context ctx, + [Optional] ZilAtom? activationAtom, BindingParams.BindingList bindings, - [CanBeNull] [Optional] ZilDecl bodyDecl, - [NotNull] [Required] ZilObject[] body) + [Optional] ZilDecl? bodyDecl, + [Required] ZilObject[] body) { return PerformProg(ctx, activationAtom, bindings, bodyDecl, body, "PROG", false, true); } [FSubr] - public static ZilResult REPEAT([NotNull] Context ctx, - [CanBeNull] [Optional] ZilAtom activationAtom, + public static ZilResult REPEAT(Context ctx, + [Optional] ZilAtom? activationAtom, BindingParams.BindingList bindings, - [CanBeNull] [Optional] ZilDecl bodyDecl, - [NotNull] [Required] ZilObject[] body) + [Optional] ZilDecl? bodyDecl, + [Required] ZilObject[] body) { return PerformProg(ctx, activationAtom, bindings, bodyDecl, body, "REPEAT", true, true); } [FSubr] - public static ZilResult BIND([NotNull] Context ctx, - [CanBeNull] [Optional] ZilAtom activationAtom, + public static ZilResult BIND(Context ctx, + [Optional] ZilAtom? activationAtom, BindingParams.BindingList bindings, - [CanBeNull] [Optional] ZilDecl bodyDecl, - [ItemNotNull] [NotNull] [Required] ZilObject[] body) + [Optional] ZilDecl? bodyDecl, + [Required] ZilObject[] body) { return PerformProg(ctx, activationAtom, bindings, bodyDecl, body, "BIND", false, false); } - static ZilResult PerformProg([NotNull] [ProvidesContext] Context ctx, [CanBeNull] ZilAtom activationAtom, - BindingParams.BindingList bindings, [CanBeNull] ZilDecl bodyDecl, [ItemNotNull] [NotNull] ZilObject[] body, - [NotNull] string name, bool repeat, bool catchy) + static ZilResult PerformProg([ProvidesContext] Context ctx, ZilAtom? activationAtom, + BindingParams.BindingList bindings, ZilDecl? bodyDecl, ZilObject[] body, + string name, bool repeat, bool catchy) { using (var activation = new ZilActivation(ctx.GetStdAtom(StdAtom.PROG))) { @@ -135,7 +136,7 @@ namespace Zilf.Interpreter var atom = b.Atom; var initializer = b.Initializer; - ZilObject value; + ZilObject? value; if (initializer != null) { @@ -151,13 +152,16 @@ namespace Zilf.Interpreter var previousDecl = b.Decl; var firstBodyDecl = bodyAtomDecls?[atom].FirstOrDefault(); - if (firstBodyDecl != null && (previousDecl != null || bodyAtomDecls[atom].Skip(1).Any())) + if (firstBodyDecl != null && (previousDecl != null || bodyAtomDecls![atom].Skip(1).Any())) throw new InterpreterError(InterpreterMessages._0_Conflicting_DECLs_For_Atom_1, name, atom); var decl = previousDecl ?? firstBodyDecl; if (value != null) + { + Debug.Assert(initializer != null); ctx.MaybeCheckDecl(initializer, value, decl, "LVAL of {0}", atom); + } innerEnv.Rebind(atom, value, decl); } @@ -166,7 +170,7 @@ namespace Zilf.Interpreter innerEnv.Rebind(ctx.EnclosingProgActivationAtom, activation); // evaluate body - ZilResult result = null; + ZilResult result = default; bool again; do { @@ -193,7 +197,7 @@ namespace Zilf.Interpreter /// No enclosing PROG/REPEAT. [Subr] - public static ZilResult RETURN(Context ctx, ZilObject value = null, ZilActivation activation = null) + public static ZilResult RETURN(Context ctx, ZilObject? value = null, ZilActivation? activation = null) { if (value == null) value = ctx.TRUE; @@ -210,7 +214,7 @@ namespace Zilf.Interpreter /// No enclosing PROG/REPEAT. [Subr] - public static ZilResult AGAIN(Context ctx, ZilActivation activation = null) + public static ZilResult AGAIN(Context ctx, ZilActivation? activation = null) { if (activation == null) { diff --git a/src/Zilf/Interpreter/Subrs.Map.cs b/src/Zilf/Interpreter/Subrs.Map.cs index 270b129..ff1cddc 100644 --- a/src/Zilf/Interpreter/Subrs.Map.cs +++ b/src/Zilf/Interpreter/Subrs.Map.cs @@ -27,29 +27,27 @@ namespace Zilf.Interpreter static partial class Subrs { [Subr] - public static ZilResult MAPF([NotNull] Context ctx, + public static ZilResult MAPF(Context ctx, [Decl("")] ZilObject finalf, - IApplicable loopf, [ItemNotNull] [NotNull] IStructure[] structs) + IApplicable loopf, IStructure[] structs) { return PerformMap(ctx, finalf, loopf, structs, true); } [Subr] - public static ZilResult MAPR([NotNull] Context ctx, + public static ZilResult MAPR(Context ctx, [Decl("")] ZilObject finalf, - IApplicable loopf, [NotNull] [ItemNotNull] IStructure[] structs) + IApplicable loopf, IStructure[] structs) { return PerformMap(ctx, finalf, loopf, structs, false); } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] - static ZilResult PerformMap([NotNull] Context ctx, ZilObject finalf, IApplicable loopf, [NotNull] IStructure[] structs, bool first) + static ZilResult PerformMap(Context ctx, ZilObject finalf, IApplicable loopf, IStructure[] structs, bool first) { if (structs == null) throw new ArgumentNullException(nameof(structs)); - var finalf_app = finalf.AsApplicable(ctx); - int numStructs = structs.Length; var loopArgs = new ZilObject[numStructs]; @@ -63,15 +61,15 @@ namespace Zilf.Interpreter for (i = 0; i < numStructs; i++) { var st = structs[i]; - if (st == null || st.IsEmpty) + if (st?.IsEmpty != false) break; if (first) - loopArgs[i] = st.GetFirst(); + loopArgs[i] = st.GetFirst()!; else loopArgs[i] = (ZilObject)st; - structs[i] = st.GetRest(1); + structs[i] = st.GetRest(1)!; } if (i < numStructs) @@ -113,28 +111,19 @@ namespace Zilf.Interpreter } // apply final function - if (finalf_app != null) - return finalf_app.ApplyNoEval(ctx, results.ToArray()); + if (finalf.IsApplicable(ctx, out var finalfApplicable)) + return finalfApplicable.ApplyNoEval(ctx, results.ToArray()); - return results.Count > 0 ? results[results.Count - 1] : ctx.FALSE; + return results.Count > 0 ? results[^1] : ctx.FALSE; } [Subr] - public static ZilResult MAPRET(Context ctx, [NotNull] ZilObject[] args) - { - return ZilResult.MapRet(args); - } + public static ZilResult MAPRET(Context ctx, ZilObject[] args) => ZilResult.MapRet(args); [Subr] - public static ZilResult MAPSTOP(Context ctx, [NotNull] ZilObject[] args) - { - return ZilResult.MapStop(args); - } + public static ZilResult MAPSTOP(Context ctx, ZilObject[] args) => ZilResult.MapStop(args); [Subr] - public static ZilResult MAPLEAVE(Context ctx, [CanBeNull] ZilObject value = null) - { - return ZilResult.MapLeave(value ?? ctx.TRUE); - } + public static ZilResult MAPLEAVE(Context ctx, ZilObject? value = null) => ZilResult.MapLeave(value ?? ctx.TRUE); } } diff --git a/src/Zilf/Interpreter/Subrs.Math.cs b/src/Zilf/Interpreter/Subrs.Math.cs index 43808fc..0cea9ad 100644 --- a/src/Zilf/Interpreter/Subrs.Math.cs +++ b/src/Zilf/Interpreter/Subrs.Math.cs @@ -21,14 +21,13 @@ using System.Linq; using Zilf.Interpreter.Values; using Zilf.Language; using Zilf.Diagnostics; -using JetBrains.Annotations; namespace Zilf.Interpreter { + [System.Diagnostics.CodeAnalysis.SuppressMessage("Redundancy", "RCS1163:Unused parameter.", Justification = "Context parameter is required by the arg decoder.")] static partial class Subrs { - [NotNull] - static ZilObject PerformArithmetic(int init, [NotNull] Func op, [NotNull] int[] args) + static ZilObject PerformArithmetic(int init, Func op, int[] args) { switch (args.Length) { @@ -50,31 +49,27 @@ namespace Zilf.Interpreter } } - [NotNull] [Subr("+")] - public static ZilObject Plus([NotNull] Context ctx, [NotNull] int[] args) + public static ZilObject Plus(Context ctx, int[] args) { return PerformArithmetic(0, (x, y) => x + y, args); } - [NotNull] [Subr("-")] - public static ZilObject Minus([NotNull] Context ctx, [NotNull] int[] args) + public static ZilObject Minus(Context ctx, int[] args) { return PerformArithmetic(0, (x, y) => x - y, args); } - [NotNull] [Subr("*")] - public static ZilObject Times([NotNull] Context ctx, [NotNull] int[] args) + public static ZilObject Times(Context ctx, int[] args) { return PerformArithmetic(1, (x, y) => x * y, args); } /// Division by zero. - [NotNull] [Subr("/")] - public static ZilObject Divide([NotNull] Context ctx, [NotNull] int[] args) + public static ZilObject Divide(Context ctx, int[] args) { try { @@ -87,9 +82,8 @@ namespace Zilf.Interpreter } /// Division by zero. - [NotNull] [Subr] - public static ZilObject MOD([NotNull] Context ctx, int a, int b) + public static ZilObject MOD(Context ctx, int a, int b) { try { @@ -101,9 +95,8 @@ namespace Zilf.Interpreter } } - [NotNull] [Subr] - public static ZilObject LSH([NotNull] Context ctx, int a, int b) + public static ZilObject LSH(Context ctx, int a, int b) { // "Logical shift", not left shift. // Positive shifts left, negative shifts right. @@ -124,51 +117,47 @@ namespace Zilf.Interpreter return new ZilFix(result); } - [NotNull] [Subr] - public static ZilObject ORB([NotNull] Context ctx, [NotNull] int[] args) + public static ZilObject ORB(Context ctx, int[] args) { return PerformArithmetic(0, (x, y) => x | y, args); } - [NotNull] [Subr] - public static ZilObject ANDB([NotNull] Context ctx, [NotNull] int[] args) + public static ZilObject ANDB(Context ctx, int[] args) { return PerformArithmetic(-1, (x, y) => x & y, args); } - [NotNull] [Subr] - public static ZilObject XORB([NotNull] Context ctx, [NotNull] int[] args) + public static ZilObject XORB(Context ctx, int[] args) { return PerformArithmetic(0, (x, y) => x ^ y, args); } - [CanBeNull] [Subr] - public static ZilObject EQVB([NotNull] Context ctx, [NotNull] int[] args) + public static ZilObject? EQVB(Context ctx, int[] args) { return PerformArithmetic(-1, (x, y) => ~(x ^ y), args); } - [CanBeNull] [Subr] - public static ZilObject MIN([NotNull] Context ctx, [NotNull] [Required] int[] args) + [System.Diagnostics.CodeAnalysis.SuppressMessage("Redundancy", "RCS1163:Unused parameter.", Justification = "", + MessageId = "args")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "")] + public static ZilObject? MIN(Context ctx, [Required] int[] args) { return new ZilFix(args.Min()); } - [NotNull] [Subr] - public static ZilObject MAX([NotNull] Context ctx, [NotNull] [Required] int[] args) + public static ZilObject MAX(Context ctx, [Required] int[] args) { return new ZilFix(args.Max()); } - [NotNull] [Subr("OR?")] - public static ZilObject OR_P([NotNull] Context ctx, [NotNull] [ItemNotNull] ZilObject[] args) + public static ZilObject OR_P(Context ctx, ZilObject[] args) { var result = ctx.FALSE; @@ -182,9 +171,8 @@ namespace Zilf.Interpreter return result; } - [NotNull] [Subr("AND?")] - public static ZilObject AND_P([NotNull] Context ctx, [ItemNotNull] [NotNull] ZilObject[] args) + public static ZilObject AND_P(Context ctx, ZilObject[] args) { var result = ctx.TRUE; @@ -198,72 +186,62 @@ namespace Zilf.Interpreter return result; } - [NotNull] [Subr] - public static ZilObject NOT([NotNull] Context ctx, [NotNull] ZilObject arg) + public static ZilObject NOT(Context ctx, ZilObject arg) { return arg.IsTrue ? ctx.FALSE : ctx.TRUE; } - [NotNull] [Subr("=?")] - public static ZilObject Eq_P([NotNull] Context ctx, [NotNull] ZilObject a, [NotNull] ZilObject b) + public static ZilObject Eq_P(Context ctx, ZilObject a, ZilObject b) { return a.StructurallyEquals(b) ? ctx.TRUE : ctx.FALSE; } - [NotNull] [Subr("N=?")] - public static ZilObject NEq_P([NotNull] Context ctx, [NotNull] ZilObject a, [NotNull] ZilObject b) + public static ZilObject NEq_P(Context ctx, ZilObject a, ZilObject b) { return a.StructurallyEquals(b) ? ctx.FALSE : ctx.TRUE; } - [NotNull] [Subr("==?")] - public static ZilObject Eeq_P([NotNull] Context ctx, [NotNull] ZilObject a, [NotNull] ZilObject b) + public static ZilObject Eeq_P(Context ctx, ZilObject a, ZilObject b) { return a.ExactlyEquals(b) ? ctx.TRUE : ctx.FALSE; } - [NotNull] [Subr("N==?")] - public static ZilObject NEeq_P([NotNull] Context ctx, [NotNull] ZilObject a, [NotNull] ZilObject b) + public static ZilObject NEeq_P(Context ctx, ZilObject a, ZilObject b) { return a.ExactlyEquals(b) ? ctx.FALSE : ctx.TRUE; } - [NotNull] [Subr("L?")] - public static ZilObject L_P([NotNull] Context ctx, int a, int b) + public static ZilObject L_P(Context ctx, int a, int b) { return a < b ? ctx.TRUE : ctx.FALSE; } - [NotNull] [Subr("L=?")] - public static ZilObject LEq_P([NotNull] Context ctx, int a, int b) + public static ZilObject LEq_P(Context ctx, int a, int b) { return a <= b ? ctx.TRUE : ctx.FALSE; } - [NotNull] [Subr("G?")] - public static ZilObject G_P([NotNull] Context ctx, int a, int b) + public static ZilObject G_P(Context ctx, int a, int b) { return a > b ? ctx.TRUE : ctx.FALSE; } - [NotNull] [Subr("G=?")] - public static ZilObject GEq_P([NotNull] Context ctx, int a, int b) + public static ZilObject GEq_P(Context ctx, int a, int b) { return a >= b ? ctx.TRUE : ctx.FALSE; } - [NotNull] [Subr("0?")] - public static ZilObject Zero_P([NotNull] Context ctx, [NotNull] ZilObject arg) + public static ZilObject Zero_P(Context ctx, ZilObject arg) { if (arg is ZilFix fix && fix.Value == 0) return ctx.TRUE; @@ -271,9 +249,8 @@ namespace Zilf.Interpreter return ctx.FALSE; } - [NotNull] [Subr("1?")] - public static ZilObject One_P([NotNull] Context ctx, [NotNull] ZilObject arg) + public static ZilObject One_P(Context ctx, ZilObject arg) { if (arg is ZilFix fix && fix.Value == 1) return ctx.TRUE; diff --git a/src/Zilf/Interpreter/Subrs.Meta.cs b/src/Zilf/Interpreter/Subrs.Meta.cs index a68d1de..2e13d10 100644 --- a/src/Zilf/Interpreter/Subrs.Meta.cs +++ b/src/Zilf/Interpreter/Subrs.Meta.cs @@ -31,8 +31,7 @@ namespace Zilf.Interpreter static partial class Subrs { /// The file was not found or could not be loaded. - [NotNull] - static ZilObject PerformLoadFile([NotNull] Context ctx, [NotNull] string file, [NotNull] string name) + static ZilObject PerformLoadFile(Context ctx, string file, string name) { try { @@ -58,11 +57,10 @@ namespace Zilf.Interpreter } /// The file was not found or could not be loaded. - [NotNull] [Subr("INSERT-FILE")] [Subr("FLOAD")] [Subr("XFLOAD")] - public static ZilObject INSERT_FILE([NotNull] Context ctx, [NotNull] string file, [ItemNotNull] [NotNull] ZilObject[] args) + public static ZilObject INSERT_FILE(Context ctx, string file, ZilObject[] args) { // we ignore arguments after the first @@ -70,9 +68,8 @@ namespace Zilf.Interpreter } /// Unrecognized flag. - [NotNull] [Subr("FILE-FLAGS")] - public static ZilObject FILE_FLAGS([NotNull] Context ctx, [NotNull] ZilAtom[] flags) + public static ZilObject FILE_FLAGS(Context ctx, ZilAtom[] flags) { var newFlags = FileFlags.None; @@ -106,9 +103,8 @@ namespace Zilf.Interpreter } /// The section has already been referenced. - [NotNull] [Subr("DELAY-DEFINITION")] - public static ZilObject DELAY_DEFINITION([NotNull] Context ctx, [NotNull] ZilAtom name) + public static ZilObject DELAY_DEFINITION(Context ctx, ZilAtom name) { name = ctx.ZEnvironment.InternGlobalName(name); @@ -121,7 +117,7 @@ namespace Zilf.Interpreter /// The section has already been inserted, or a replacement has already been defined, or it is in a bad state. [FSubr("REPLACE-DEFINITION")] - public static ZilResult REPLACE_DEFINITION([NotNull] Context ctx, [NotNull] ZilAtom name, [NotNull] [Required] ZilObject[] body) + public static ZilResult REPLACE_DEFINITION(Context ctx, ZilAtom name, [Required] ZilObject[] body) { name = ctx.ZEnvironment.InternGlobalName(name); @@ -153,7 +149,7 @@ namespace Zilf.Interpreter /// The section is in a bad state. [FSubr("DEFAULT-DEFINITION")] - public static ZilResult DEFAULT_DEFINITION([NotNull] Context ctx, ZilAtom name, [Required] ZilObject[] body) + public static ZilResult DEFAULT_DEFINITION(Context ctx, ZilAtom name, [Required] ZilObject[] body) { name = ctx.ZEnvironment.InternGlobalName(name); @@ -190,29 +186,26 @@ namespace Zilf.Interpreter throw new InterpreterError(InterpreterMessages._0_Bad_State_1, "DEFAULT-DEFINITION", state); } - [NotNull] [Subr("COMPILATION-FLAG")] - public static ZilObject COMPILATION_FLAG([NotNull] Context ctx, - AtomParams.StringOrAtom name, [CanBeNull] ZilObject value = null) + public static ZilObject COMPILATION_FLAG(Context ctx, + AtomParams.StringOrAtom name, ZilObject? value = null) { var atom = name.GetAtom(ctx); ctx.DefineCompilationFlag(atom, value ?? ctx.TRUE, true); return atom; } - [NotNull] [Subr("COMPILATION-FLAG-DEFAULT")] - public static ZilObject COMPILATION_FLAG_DEFAULT([NotNull] Context ctx, - AtomParams.StringOrAtom name, [NotNull] ZilObject value) + public static ZilObject COMPILATION_FLAG_DEFAULT(Context ctx, + AtomParams.StringOrAtom name, ZilObject value) { var atom = name.GetAtom(ctx); ctx.DefineCompilationFlag(atom, value); return atom; } - [NotNull] [Subr("COMPILATION-FLAG-VALUE")] - public static ZilObject COMPILATION_FLAG_VALUE([NotNull] Context ctx, + public static ZilObject COMPILATION_FLAG_VALUE(Context ctx, AtomParams.StringOrAtom name) { var atom = name.GetAtom(ctx); @@ -220,12 +213,12 @@ namespace Zilf.Interpreter } [FSubr("IFFLAG")] - public static ZilResult IFFLAG([NotNull] Context ctx, [NotNull] [Required] CondClause[] args) + public static ZilResult IFFLAG(Context ctx, [Required] CondClause[] args) { foreach (var clause in args) { bool match; - ZilObject value; + ZilObject? value; switch (clause.Condition) { @@ -273,12 +266,11 @@ namespace Zilf.Interpreter /// The original form. /// A new form, containing elements from the original and/or /// the values of compilation flags. - [NotNull] - internal static ZilForm SubstituteIfflagForm([NotNull] Context ctx, [NotNull] ZilForm form) + internal static ZilForm SubstituteIfflagForm(Context ctx, ZilForm form) { var body = form.Select(zo => { - ZilObject value; + ZilObject? value; switch (zo) { @@ -293,7 +285,6 @@ namespace Zilf.Interpreter return new ZilForm(body) { SourceLine = form.SourceLine }; } - [NotNull] [Subr("TIME")] public static ZilObject TIME(Context ctx) { @@ -302,7 +293,7 @@ namespace Zilf.Interpreter } [Subr("QUIT")] - public static ZilObject QUIT([NotNull] Context ctx, ZilObject exitCode = null) + public static ZilObject QUIT(Context ctx, ZilObject? exitCode = null) { int code; switch (exitCode) @@ -326,16 +317,14 @@ namespace Zilf.Interpreter return ctx.TRUE; } - [NotNull] [Subr] [Subr("STACK")] [Subr("SNAME")] - public static ZilObject ID([NotNull] Context ctx, ZilObject arg) + public static ZilObject ID(Context ctx, ZilObject arg) { return arg; } - [NotNull] [Subr("GC-MON")] [Subr("BLOAT")] [Subr("ZSTR-ON")] @@ -351,16 +340,15 @@ namespace Zilf.Interpreter [Subr("NEVER-ZAP-TO-SOURCE-DIRECTORY?")] [Subr("ASK-FOR-PICTURE-FILE?")] [Subr("PICFILE")] - public static ZilObject SubrIgnored([NotNull] Context ctx, [ItemNotNull] [NotNull] ZilObject[] args) + public static ZilObject SubrIgnored(Context ctx, ZilObject[] args) { // nada return ctx.FALSE; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.GC.Collect")] - [NotNull] [Subr] - public static ZilObject GC([NotNull] Context ctx, [ItemNotNull] [NotNull] ZilObject[] args) + public static ZilObject GC(Context ctx, ZilObject[] args) { System.GC.Collect(); return ctx.TRUE; @@ -368,7 +356,7 @@ namespace Zilf.Interpreter /// Always thrown. [Subr] - public static ZilObject ERROR([NotNull] Context ctx, [ItemNotNull] [NotNull] ZilObject[] args) + public static ZilObject ERROR(Context ctx, ZilObject[] args) { throw new InterpreterError( InterpreterMessages.UserSpecifiedError_0_1, @@ -376,9 +364,8 @@ namespace Zilf.Interpreter string.Join(" ", args.Select(a => a.ToStringContext(ctx, false)))); } - [NotNull] [Subr("WARN-AS-ERROR?")] - public static ZilObject WARN_AS_ERROR_P([NotNull] Context ctx, bool enabled = true) + public static ZilObject WARN_AS_ERROR_P(Context ctx, bool enabled = true) { ctx.WarningsAsErrors = enabled; return ctx.TRUE; @@ -400,8 +387,7 @@ namespace Zilf.Interpreter return Content is Wildcard w ? w.Atom.StdAtom : (StdAtom?)null; } - [CanBeNull] - public string[] GetCodes() + public string[]? GetCodes() { return Content is AtomParams.StringOrAtom[] sas ? sas.Select(sa => sa.ToString()).ToArray() @@ -421,9 +407,8 @@ namespace Zilf.Interpreter } } - [NotNull] [Subr("SUPPRESS-WARNINGS?")] - public static ZilObject SUPPRESS_WARNINGS_P([NotNull] Context ctx, + public static ZilObject SUPPRESS_WARNINGS_P(Context ctx, WarningParams.CodesOrWildcard codesOrWildcard) { switch (codesOrWildcard.GetWildcard()) @@ -450,9 +435,8 @@ namespace Zilf.Interpreter #region IDE Help - [NotNull] [Subr("DESC-BUILTINS", ObList = "YOMIN")] - public static ZilObject DESCRIBE_BUILTINS([NotNull] Context ctx) + public static ZilObject DESCRIBE_BUILTINS(Context ctx) { var result = new JObject(); diff --git a/src/Zilf/Interpreter/Subrs.Output.cs b/src/Zilf/Interpreter/Subrs.Output.cs index 3d2ed91..cadd14f 100644 --- a/src/Zilf/Interpreter/Subrs.Output.cs +++ b/src/Zilf/Interpreter/Subrs.Output.cs @@ -30,9 +30,8 @@ namespace Zilf.Interpreter static partial class Subrs { /// Bad OUTCHAN. - [NotNull] [Subr] - public static ZilObject PRINT([NotNull] Context ctx, [NotNull] ZilObject value, ZilChannel channel = null) + public static ZilObject PRINT(Context ctx, ZilObject value, ZilChannel? channel = null) { if (channel == null) { @@ -54,9 +53,8 @@ namespace Zilf.Interpreter } /// Bad OUTCHAN. - [NotNull] [Subr] - public static ZilObject PRIN1([NotNull] Context ctx, [NotNull] ZilObject value, ZilChannel channel = null) + public static ZilObject PRIN1(Context ctx, ZilObject value, ZilChannel? channel = null) { if (channel == null) { @@ -76,9 +74,8 @@ namespace Zilf.Interpreter } /// Bad OUTCHAN. - [NotNull] [Subr] - public static ZilObject PRINC([NotNull] Context ctx, [NotNull] ZilObject value, ZilChannel channel = null) + public static ZilObject PRINC(Context ctx, ZilObject value, ZilChannel? channel = null) { if (channel == null) { @@ -98,9 +95,8 @@ namespace Zilf.Interpreter } /// Bad OUTCHAN. - [NotNull] [Subr] - public static ZilObject CRLF([NotNull] Context ctx, ZilChannel channel = null) + public static ZilObject CRLF(Context ctx, ZilChannel? channel = null) { if (channel == null) { @@ -119,23 +115,25 @@ namespace Zilf.Interpreter /// is an atom which has no local or global value. [Subr("PRINT-MANY")] - public static ZilObject PRINT_MANY([NotNull] Context ctx, ZilChannel channel, - [Decl("")] ZilObject printer, [NotNull] ZilObject[] items) + public static ZilObject PRINT_MANY(Context ctx, ZilChannel channel, + [Decl("")] ZilObject printer, ZilObject[] items) { if (printer is ZilAtom atom) { - printer = ctx.GetGlobalVal(atom) ?? ctx.GetLocalVal(atom); - if (printer == null) - throw new InterpreterError( - InterpreterMessages._0_Atom_1_Has_No_2_Value, - "PRINT-MANY", - atom.ToStringContext(ctx, false), - "local or global"); + printer = ctx.GetGlobalVal(atom) ?? ctx.GetLocalVal(atom) ?? + throw new InterpreterError( + InterpreterMessages._0_Atom_1_Has_No_2_Value, + "PRINT-MANY", + atom.ToStringContext(ctx, false), + "local or global"); } - var applicablePrinter = printer.AsApplicable(ctx); - if (applicablePrinter == null) - throw new InterpreterError(InterpreterMessages._0_Not_Applicable_1, "PRINT-MANY", printer.ToStringContext(ctx, false)); + if (!printer.IsApplicable(ctx, out var applicablePrinter)) + { + throw new InterpreterError(InterpreterMessages._0_Not_Applicable_1, + "PRINT-MANY", + printer.ToStringContext(ctx, false)); + } var crlf = ctx.GetStdAtom(StdAtom.PRMANY_CRLF); var result = ctx.TRUE; @@ -166,9 +164,8 @@ namespace Zilf.Interpreter } /// Bad OUTCHAN. - [NotNull] [Subr] - public static ZilObject IMAGE([NotNull] Context ctx, [NotNull] ZilFix ch, ZilChannel channel = null) + public static ZilObject IMAGE(Context ctx, ZilFix ch, ZilChannel? channel = null) { if (channel == null) { @@ -187,47 +184,42 @@ namespace Zilf.Interpreter static readonly Regex RetroPathRE = new Regex(@"^(?:(?[^:]+):)?(?:<(?[^>]+)>)?(?[^:<>]+)$"); - [NotNull] [Subr] - public static ZilObject OPEN([NotNull] Context ctx, [Decl("'\"READ\"")] string mode, [NotNull] string path) + public static ZilObject OPEN(Context ctx, [Decl("'\"READ\"")] string mode, string path) { var result = new ZilFileChannel(ConvertPath(path), FileAccess.Read); result.Reset(ctx); return result; } - [NotNull] - static string ConvertPath([NotNull] string retroPath) + static string ConvertPath(string retroPath) { var match = RetroPathRE.Match(retroPath); return match.Success ? match.Groups["filename"].Value : retroPath; } - [NotNull] [Subr] - public static ZilObject CLOSE([NotNull] Context ctx, [NotNull] ZilChannel channel) + public static ZilObject CLOSE(Context ctx, ZilChannel channel) { channel.Close(); return channel; } - [NotNull] [Subr("FILE-LENGTH")] - public static ZilObject FILE_LENGTH([NotNull] Context ctx, [NotNull] ZilChannel channel) + public static ZilObject FILE_LENGTH(Context ctx, ZilChannel channel) { var length = channel.GetFileLength(); return length == null ? ctx.FALSE : new ZilFix((int)length.Value); } - [NotNull] [Subr] - public static ZilObject READSTRING([NotNull] Context ctx, [NotNull] ZilString dest, ZilChannel channel, - [CanBeNull] [Decl("")] ZilObject maxLengthOrStopChars = null) + public static ZilObject READSTRING(Context ctx, ZilString dest, ZilChannel channel, + [Decl("")] ZilObject? maxLengthOrStopChars = null) { // TODO: support 1- and 4-argument forms? int maxLength = dest.Text.Length; - ZilString stopChars = null; + ZilString? stopChars = null; if (maxLengthOrStopChars != null) { @@ -262,9 +254,8 @@ namespace Zilf.Interpreter } /// Not supported by this type of channel. - [NotNull] [Subr("M-HPOS")] - public static ZilObject M_HPOS([NotNull] Context ctx, [NotNull] ZilChannel channel) + public static ZilObject M_HPOS(Context ctx, ZilChannel channel) { if (!(channel is IChannelWithHPos hposChannel)) throw new InterpreterError(InterpreterMessages._0_Not_Supported_By_This_Type_Of_Channel, "M-HPOS"); @@ -273,9 +264,8 @@ namespace Zilf.Interpreter } /// is negative. - [NotNull] [Subr("INDENT-TO")] - public static ZilObject INDENT_TO([NotNull] Context ctx, [NotNull] ZilFix position, ZilChannel channel = null) + public static ZilObject INDENT_TO(Context ctx, ZilFix position, ZilChannel? channel = null) { if (position.Value < 0) throw new InterpreterError( diff --git a/src/Zilf/Interpreter/Subrs.Packages.cs b/src/Zilf/Interpreter/Subrs.Packages.cs index 537d55d..32a53b5 100644 --- a/src/Zilf/Interpreter/Subrs.Packages.cs +++ b/src/Zilf/Interpreter/Subrs.Packages.cs @@ -27,11 +27,10 @@ namespace Zilf.Interpreter { static partial class Subrs { - [NotNull] [Subr] [Subr("ZPACKAGE")] [Subr("ZZPACKAGE")] - public static ZilObject PACKAGE([NotNull] Context ctx, [NotNull] string pname) + public static ZilObject PACKAGE(Context ctx, string pname) { // external oblist var externalAtom = ctx.PackageObList[pname]; @@ -53,11 +52,10 @@ namespace Zilf.Interpreter return externalAtom; } - [NotNull] [Subr] [Subr("ZSECTION")] [Subr("ZZSECTION")] - public static ZilObject DEFINITIONS([NotNull] Context ctx, [NotNull] string pname) + public static ZilObject DEFINITIONS(Context ctx, string pname) { // external oblist var externalAtom = ctx.PackageObList[pname]; @@ -74,19 +72,17 @@ namespace Zilf.Interpreter return externalAtom; } - [NotNull] [Subr] [Subr("END-DEFINITIONS")] [Subr("ENDSECTION")] - public static ZilObject ENDPACKAGE([NotNull] Context ctx) + public static ZilObject ENDPACKAGE(Context ctx) { return ENDBLOCK(ctx); } /// OBLIST path is malformed. - [NotNull] [Subr] - public static ZilObject ENTRY([NotNull] Context ctx, [NotNull] ZilAtom[] args) + public static ZilObject ENTRY(Context ctx, ZilAtom[] args) { if (!(ctx.GetLocalVal(ctx.GetStdAtom(StdAtom.OBLIST)) is ZilList currentObPath) || currentObPath.GetLength(1) != null || @@ -117,7 +113,7 @@ namespace Zilf.Interpreter throw new InterpreterError( InterpreterMessages._0_All_Atoms_Must_Be_On_Internal_Oblist_1_Failed_For_2, "ENTRY", - ctx.GetProp(internalObList, ctx.GetStdAtom(StdAtom.OBLIST))?.ToStringContext(ctx, false), + ctx.GetProp(internalObList, ctx.GetStdAtom(StdAtom.OBLIST))?.ToStringContext(ctx, false) ?? "", string.Join(", ", onWrongOblist.Select(a => a.ToStringContext(ctx, false)))); } @@ -128,9 +124,8 @@ namespace Zilf.Interpreter } /// OBLIST path is malformed. - [NotNull] [Subr] - public static ZilObject RENTRY([NotNull] Context ctx, [NotNull] ZilAtom[] args) + public static ZilObject RENTRY(Context ctx, ZilAtom[] args) { if (!(ctx.GetLocalVal(ctx.GetStdAtom(StdAtom.OBLIST)) is ZilList currentObPath) || currentObPath.GetLength(1) != null || @@ -162,7 +157,7 @@ namespace Zilf.Interpreter { throw new InterpreterError(InterpreterMessages._0_All_Atoms_Must_Be_On_Internal_Oblist_1_Failed_For_2, "RENTRY", - ctx.GetProp(internalObList, ctx.GetStdAtom(StdAtom.OBLIST))?.ToStringContext(ctx, false), + ctx.GetProp(internalObList, ctx.GetStdAtom(StdAtom.OBLIST))?.ToStringContext(ctx, false) ?? "", string.Join(", ", onWrongOblist.Select(a => a.ToStringContext(ctx, false)))); } @@ -172,36 +167,31 @@ namespace Zilf.Interpreter return ctx.TRUE; } - [NotNull] [Subr] - public static ZilObject USE([NotNull] Context ctx, [NotNull] string[] args) + public static ZilObject USE(Context ctx, string[] args) { return PerformUse(ctx, args, "USE", StdAtom.PACKAGE); } - [NotNull] [Subr] - public static ZilObject INCLUDE([NotNull] Context ctx, [NotNull] string[] args) + public static ZilObject INCLUDE(Context ctx, string[] args) { return PerformUse(ctx, args, "INCLUDE", StdAtom.DEFINITIONS); } - [NotNull] [Subr("USE-WHEN")] - public static ZilObject USE_WHEN(Context ctx, [NotNull] ZilObject condition, string[] args) + public static ZilObject USE_WHEN(Context ctx, ZilObject condition, string[] args) { return condition.IsTrue ? PerformUse(ctx, args, "USE-WHEN", StdAtom.PACKAGE) : condition; } - [NotNull] [Subr("INCLUDE-WHEN")] - public static ZilObject INCLUDE_WHEN(Context ctx, [NotNull] ZilObject condition, string[] args) + public static ZilObject INCLUDE_WHEN(Context ctx, ZilObject condition, string[] args) { return condition.IsTrue ? PerformUse(ctx, args, "INCLUDE-WHEN", StdAtom.DEFINITIONS) : condition; } - [NotNull] - static ZilObject PerformUse([NotNull] Context ctx, [NotNull] string[] args, string name, StdAtom requiredPackageType) + static ZilObject PerformUse(Context ctx, string[] args, string name, StdAtom requiredPackageType) { if (!(ctx.GetLocalVal(ctx.GetStdAtom(StdAtom.OBLIST)) is ZilList obpath)) { @@ -225,7 +215,7 @@ namespace Zilf.Interpreter PerformLoadFile(ctx, packageName, name); // throws on failure } - ObList externalObList = null; + ObList? externalObList = null; if (ctx.PackageObList.Contains(packageName)) { var packageNameAtom = ctx.PackageObList[packageName]; @@ -249,9 +239,10 @@ namespace Zilf.Interpreter return ctx.TRUE; } - [NotNull] [Subr("COMPILING?")] - public static ZilObject COMPILING_P([NotNull] Context ctx, ZilObject[] args) + [System.Diagnostics.CodeAnalysis.SuppressMessage("Redundancy", "RCS1163:Unused parameter.", Justification = "Arguments are discarded.")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "Arguments are discarded.")] + public static ZilObject COMPILING_P(Context ctx, ZilObject[] args) { // always true return ctx.TRUE; diff --git a/src/Zilf/Interpreter/Subrs.Structures.cs b/src/Zilf/Interpreter/Subrs.Structures.cs index 7300245..badd74d 100644 --- a/src/Zilf/Interpreter/Subrs.Structures.cs +++ b/src/Zilf/Interpreter/Subrs.Structures.cs @@ -19,21 +19,22 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.Serialization; +using Zilf.Common; +using Zilf.Diagnostics; using Zilf.Interpreter.Values; using Zilf.Language; -using Zilf.Diagnostics; -using Zilf.Common; -using JetBrains.Annotations; namespace Zilf.Interpreter { + [SuppressMessage("Performance", "CA1801", Justification = "Subrs parameters are needed for validation, even if the values aren't used.")] + [SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "Subrs parameters are needed for validation, even if the values aren't used.")] static partial class Subrs { - [NotNull] [Subr("EMPTY?")] - public static ZilObject EMPTY_P([NotNull] Context ctx, [NotNull] IStructure st) + public static ZilObject EMPTY_P(Context ctx, IStructure st) { return st.IsEmpty ? ctx.TRUE : ctx.FALSE; } @@ -52,24 +53,22 @@ namespace Zilf.Interpreter }*/ /// has fewer than elements. - [NotNull] [Subr] - public static ZilObject REST(Context ctx, [NotNull] IStructure st, int skip = 1) + public static ZilObject REST(Context ctx, IStructure st, int skip = 1) { - var result = (ZilObject)st.GetRest(skip); + var result = (ZilObject?)st.GetRest(skip); if (result == null) throw new InterpreterError(InterpreterMessages._0_Not_Enough_Elements, "REST"); return result.GetPrimitive(ctx); } /// The type of does not support this operation, or has not been RESTed at least elements. - [NotNull] [Subr] - public static ZilObject BACK(Context ctx, [NotNull] IStructure st, int skip = 1) + public static ZilObject BACK(Context ctx, IStructure st, int skip = 1) { try { - var result = (ZilObject)st.GetBack(skip); + var result = (ZilObject?)st.GetBack(skip); if (result == null) throw new InterpreterError(InterpreterMessages._0_Not_Enough_Elements); return result; @@ -81,9 +80,8 @@ namespace Zilf.Interpreter } /// The type of does not support this operation. - [NotNull] [Subr] - public static ZilObject TOP(Context ctx, [NotNull] IStructure st) + public static ZilObject TOP(Context ctx, IStructure st) { try { @@ -96,9 +94,8 @@ namespace Zilf.Interpreter } /// or are negative, or the type of does not support this operation. - [NotNull] [Subr] - public static ZilObject GROW(Context ctx, [NotNull] IStructure st, int end, int beginning) + public static ZilObject GROW(Context ctx, IStructure st, int end, int beginning) { if (end < 0 || beginning < 0) { @@ -121,9 +118,8 @@ namespace Zilf.Interpreter } /// is past the end of . - [NotNull] [Subr] - public static ZilObject NTH(Context ctx, [NotNull] IStructure st, int idx) + public static ZilObject NTH(Context ctx, IStructure st, int idx) { var result = st[idx - 1]; if (result == null) @@ -133,9 +129,8 @@ namespace Zilf.Interpreter } /// is past the end of , or is read-only. - [NotNull] [Subr] - public static ZilObject PUT(Context ctx, [NotNull] IStructure st, int idx, ZilObject newValue) + public static ZilObject PUT(Context ctx, IStructure st, int idx, ZilObject newValue) { try { @@ -153,39 +148,34 @@ namespace Zilf.Interpreter return (ZilObject)st; } - [NotNull] [Subr] - public static ZilObject OFFSET(Context ctx, int offset, [NotNull] ZilObject structurePattern, [CanBeNull] ZilObject valuePattern = null) + public static ZilObject OFFSET(Context ctx, int offset, ZilObject structurePattern, ZilObject? valuePattern = null) { return new ZilOffset(offset, structurePattern, valuePattern ?? ctx.GetStdAtom(StdAtom.ANY)); } - [NotNull] [Subr] - public static ZilObject INDEX(Context ctx, [NotNull] ZilOffset offset) + public static ZilObject INDEX(Context ctx, ZilOffset offset) { return new ZilFix(offset.Index); } - [NotNull] [Subr] - public static ZilObject LENGTH(Context ctx, [NotNull] IStructure st) + public static ZilObject LENGTH(Context ctx, IStructure st) { return new ZilFix(st.GetLength()); } - [NotNull] [Subr("LENGTH?")] - public static ZilObject LENGTH_P(Context ctx, [NotNull] IStructure st, int limit) + public static ZilObject LENGTH_P(Context ctx, IStructure st, int limit) { var length = st.GetLength(limit); return length != null ? new ZilFix((int)length) : ctx.FALSE; } /// is empty. - [NotNull] [Subr] - public static ZilObject PUTREST(Context ctx, [NotNull] ZilListoidBase list, [NotNull] ZilListoidBase newRest) + public static ZilObject PUTREST(Context ctx, ZilListoidBase list, ZilListoidBase newRest) { if (list.IsEmpty) throw new InterpreterError(InterpreterMessages._0_Writing_Past_End_Of_Structure, "PUTREST"); @@ -213,21 +203,22 @@ namespace Zilf.Interpreter } /// is negative, or or are too short, or the types of and are incompatible. - [NotNull] - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] + [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] [Subr] - public static ZilObject SUBSTRUC(Context ctx, [NotNull] IStructure from, int rest = 0, int? amount = null, - [CanBeNull] IStructure dest = null) + public static ZilObject SUBSTRUC(Context ctx, IStructure from, int rest = 0, int? amount = null, + IStructure? dest = null) { if (amount != null) { var max = from.GetLength(rest + (int)amount); if (max != null && max.Value - rest < amount) + { throw new InterpreterError( InterpreterMessages._0_1_Element1s_Requested_But_Only_2_Available, "SUBSTRUC", amount, max.Value - rest); + } } else { @@ -238,7 +229,7 @@ namespace Zilf.Interpreter throw new InterpreterError(InterpreterMessages._0_Negative_Element_Count, "SUBSTRUC"); var fromObj = (ZilObject)from; - var destObj = (ZilObject)dest; + var destObj = (ZilObject?)dest; var primitive = (IStructure)fromObj.GetPrimitive(ctx); if (destObj != null) @@ -268,7 +259,7 @@ namespace Zilf.Interpreter // this is crazy inefficient, but works with ZilString and OffsetString // TODO: method on ZilString to do this more efficiently? for (i = 0; i < amount; i++) - str[i] = primitive[i + rest]; + str[i] = primitive[i + rest]!; break; case ZilVector vector: @@ -290,39 +281,30 @@ namespace Zilf.Interpreter } // no destination, return a new structure - switch (fromObj.PrimType) + return fromObj.PrimType switch { - case PrimType.LIST: - return new ZilList(primitive.Skip(rest).Take((int)amount)); - - case PrimType.STRING: - return ZilString.FromString(((ZilString)primitive).Text.Substring(rest, (int)amount)); - - case PrimType.TABLE: - throw new InterpreterError(InterpreterMessages._0_Primtype_TABLE_Not_Supported, "SUBSTRUC"); - - case PrimType.VECTOR: - return new ZilVector(((ZilVector)primitive).Skip(rest).Take((int)amount).ToArray()); - - default: - throw UnhandledCaseException.FromEnum(fromObj.PrimType, "structured primtype"); - } + PrimType.LIST => (ZilObject)new ZilList(primitive.Skip(rest).Take((int)amount)), + PrimType.STRING => ZilString.FromString(((ZilString)primitive).Text.Substring(rest, (int)amount)), + PrimType.TABLE => throw new InterpreterError(InterpreterMessages._0_Primtype_TABLE_Not_Supported, + "SUBSTRUC"), + PrimType.VECTOR => new ZilVector(((ZilVector)primitive).Skip(rest).Take((int)amount).ToArray()), + _ => throw UnhandledCaseException.FromEnum(fromObj.PrimType, "structured primtype") + }; } - [NotNull] [Subr] - public static ZilObject MEMBER(Context ctx, [NotNull] ZilObject needle, [NotNull] IStructure haystack) + public static ZilObject MEMBER(Context ctx, ZilObject needle, IStructure haystack) { if (needle.PrimType == PrimType.STRING && ((ZilObject)haystack).PrimType == PrimType.STRING) { string n = ((ZilString)needle.GetPrimitive(ctx)).Text; - if (n != "") + if (n.Length > 0) { string h = ((ZilString)((ZilObject)haystack).GetPrimitive(ctx)).Text; int pos = h.IndexOf(n, StringComparison.Ordinal); if (pos >= 0) { - return (ZilObject)haystack.GetRest(pos) ?? ctx.FALSE; + return (ZilObject?)haystack.GetRest(pos) ?? ctx.FALSE; } } } @@ -330,23 +312,21 @@ namespace Zilf.Interpreter return PerformMember(ctx, needle, haystack, (a, b) => a.StructurallyEquals(b)); } - [NotNull] [Subr] - public static ZilObject MEMQ(Context ctx, [NotNull] ZilObject needle, [NotNull] IStructure haystack) + public static ZilObject MEMQ(Context ctx, ZilObject needle, IStructure haystack) { return PerformMember(ctx, needle, haystack, (a, b) => a.ExactlyEquals(b)); } - [NotNull] - static ZilObject PerformMember(Context ctx, [NotNull] ZilObject needle, [NotNull] IStructure haystack, - [NotNull] Func equality) + static ZilObject PerformMember(Context ctx, ZilObject needle, IStructure haystack, + Func equality) { - while (haystack != null && !haystack.IsEmpty) + while (haystack?.IsEmpty == false) { - if (equality(needle, haystack.GetFirst())) + if (equality(needle, haystack.GetFirst()!)) return (ZilObject)haystack; - haystack = haystack.GetRest(1); + haystack = haystack.GetRest(1)!; } return ctx.FALSE; @@ -373,17 +353,29 @@ namespace Zilf.Interpreter } protected SortAbortedException( - [NotNull] SerializationInfo info, + SerializationInfo info, StreamingContext context) : base(info, context) { } + + public SortAbortedException(string message, Exception innerException) : base(message, innerException) + { + } + + public SortAbortedException() + { + } + + public SortAbortedException(string message) : base(message) + { + } } [Subr] public static ZilResult SORT(Context ctx, - [NotNull] [Decl("")] ZilObject predicate, - [NotNull] ZilVector vector, int recordSize = 1, int keyOffset = 0, - [CanBeNull] AdditionalSortParam[] additionalSorts = null) + [Decl("")] ZilObject predicate, + ZilVector vector, int recordSize = 1, int keyOffset = 0, + AdditionalSortParam[]? additionalSorts = null) { if (keyOffset < 0 || keyOffset >= recordSize) throw new InterpreterError(InterpreterMessages._0_Expected_0__Key_Offset__Record_Size, "SORT"); @@ -412,14 +404,18 @@ namespace Zilf.Interpreter } } - ZilObject KeySelector(int i) => vector[i * recordSize + keyOffset]; + ZilObject KeySelector(int i) + { + return vector[i * recordSize + keyOffset]!; + } + Comparison comparison; if (predicate.IsTrue) { // user-provided comparison - var applicable = predicate.AsApplicable(ctx); - Debug.Assert(applicable != null); + if (!predicate.IsApplicable(ctx, out var applicable)) + throw new UnhandledCaseException("non-false, non-applicable predicate"); var args = new ZilObject[2]; comparison = (a, b) => @@ -463,20 +459,15 @@ namespace Zilf.Interpreter a = a.GetPrimitive(ctx); b = b.GetPrimitive(ctx); - switch (a.PrimType) + return a.PrimType switch { - case PrimType.ATOM: - return string.Compare(((ZilAtom)a).Text, ((ZilAtom)b).Text, StringComparison.Ordinal); - - case PrimType.FIX: - return ((ZilFix)a).Value.CompareTo(((ZilFix)b).Value); - - case PrimType.STRING: - return string.Compare(((ZilString)a).Text, ((ZilString)b).Text, StringComparison.Ordinal); - - default: - throw new InterpreterError(InterpreterMessages._0_Key_Primtypes_Must_Be_ATOM_FIX_Or_STRING_To_Use_Default_Comparison, "SORT"); - } + PrimType.ATOM => string.CompareOrdinal(((ZilAtom)a).Text, ((ZilAtom)b).Text), + PrimType.FIX => ((ZilFix)a).Value.CompareTo(((ZilFix)b).Value), + PrimType.STRING => string.CompareOrdinal(((ZilString)a).Text, ((ZilString)b).Text), + _ => throw new InterpreterError( + InterpreterMessages._0_Key_Primtypes_Must_Be_ATOM_FIX_Or_STRING_To_Use_Default_Comparison, + "SORT"), + }; }; } @@ -507,15 +498,22 @@ namespace Zilf.Interpreter } } - static void RearrangeVector([NotNull] ZilVector vector, int recordSize, [NotNull] int[] desiredIndexOrder) + static void RearrangeVector(ZilVector vector, int recordSize, int[] desiredIndexOrder) { - var output = new List(vector.GetLength()); + int length = vector.GetLength(); + + if (recordSize < 1) + throw new ArgumentOutOfRangeException(nameof(recordSize)); + + var output = new List(length); foreach (var srcIndex in desiredIndexOrder) { + Debug.Assert(srcIndex >= 0 && (srcIndex + 1) * recordSize <= length); + for (int i = 0; i < recordSize; i++) { - output.Add(vector[srcIndex * recordSize + i]); + output.Add(vector[srcIndex * recordSize + i]!); } } diff --git a/src/Zilf/Interpreter/Subrs.Types.cs b/src/Zilf/Interpreter/Subrs.Types.cs index 505f4fd..1604803 100644 --- a/src/Zilf/Interpreter/Subrs.Types.cs +++ b/src/Zilf/Interpreter/Subrs.Types.cs @@ -33,16 +33,14 @@ namespace Zilf.Interpreter [SuppressMessage("ReSharper", "InconsistentNaming")] static partial class Subrs { - [NotNull] [Subr] - public static ZilObject TYPE([NotNull] Context ctx, [NotNull] ZilObject value) + public static ZilObject TYPE(Context ctx, ZilObject value) { return value.GetTypeAtom(ctx); } - [NotNull] [Subr("TYPE?")] - public static ZilObject TYPE_P([NotNull] Context ctx, [NotNull] ZilObject value, [NotNull] [Required] ZilAtom[] types) + public static ZilObject TYPE_P(Context ctx, ZilObject value, [Required] ZilAtom[] types) { var type = value.GetTypeAtom(ctx); @@ -81,17 +79,15 @@ namespace Zilf.Interpreter } } - [NotNull] [Subr] - public static ZilObject PRIMTYPE([NotNull] Context ctx, [NotNull] ZilObject value) + public static ZilObject PRIMTYPE(Context ctx, ZilObject value) { return ctx.GetStdAtom(PrimTypeToType(value.PrimType)); } /// is not a registered type. - [NotNull] [Subr] - public static ZilObject TYPEPRIM([NotNull] Context ctx, [NotNull] ZilAtom type) + public static ZilObject TYPEPRIM(Context ctx, ZilAtom type) { if (!ctx.IsRegisteredType(type)) throw new InterpreterError(InterpreterMessages._0_Unrecognized_1_2, "TYPEPRIM", "type", type.ToStringContext(ctx, false)); @@ -99,18 +95,16 @@ namespace Zilf.Interpreter return ctx.GetStdAtom(PrimTypeToType(ctx.GetTypePrim(type))); } - [NotNull] [Subr] - public static ZilObject CHTYPE([NotNull] Context ctx, [NotNull] ZilObject value, [NotNull] ZilAtom atom) + public static ZilObject CHTYPE(Context ctx, ZilObject value, ZilAtom atom) { return ctx.ChangeType(value, atom); } /// is already a registered type, or is not. - [NotNull] [Subr] - public static ZilObject NEWTYPE([NotNull] Context ctx, [NotNull] ZilAtom name, [NotNull] ZilAtom primtypeAtom, - [CanBeNull] ZilObject decl = null) + public static ZilObject NEWTYPE(Context ctx, ZilAtom name, ZilAtom primtypeAtom, + ZilObject? decl = null) { if (ctx.IsRegisteredType(name)) throw new InterpreterError(InterpreterMessages._0_Already_Defined_1, "NEWTYPE", name.ToStringContext(ctx, false)); @@ -126,24 +120,21 @@ namespace Zilf.Interpreter return name; } - [NotNull] [Subr] - public static ZilObject ALLTYPES([NotNull] Context ctx) + public static ZilObject ALLTYPES(Context ctx) { return new ZilVector(ctx.RegisteredTypes.ToArray()); } - [NotNull] [Subr("VALID-TYPE?")] - public static ZilObject VALID_TYPE_P([NotNull] Context ctx, [NotNull] ZilAtom atom) + public static ZilObject VALID_TYPE_P(Context ctx, ZilAtom atom) { return ctx.IsRegisteredType(atom) ? atom : ctx.FALSE; } - [NotNull] [Subr] - public static ZilObject PRINTTYPE([NotNull] Context ctx, [NotNull] ZilAtom atom, - [CanBeNull] [Decl("")] ZilObject handler = null) + public static ZilObject PRINTTYPE(Context ctx, ZilAtom atom, + [Decl("")] ZilObject? handler = null) { return PerformTypeHandler(ctx, atom, handler, "PRINTTYPE", @@ -151,10 +142,9 @@ namespace Zilf.Interpreter (c, a, h) => c.SetPrintType(a, h)); } - [NotNull] [Subr] - public static ZilObject EVALTYPE([NotNull] Context ctx, [NotNull] ZilAtom atom, - [CanBeNull] [Decl("")] ZilObject handler = null) + public static ZilObject EVALTYPE(Context ctx, ZilAtom atom, + [Decl("")] ZilObject? handler = null) { return PerformTypeHandler(ctx, atom, handler, "EVALTYPE", @@ -162,10 +152,9 @@ namespace Zilf.Interpreter (c, a, h) => c.SetEvalType(a, h)); } - [NotNull] [Subr] - public static ZilObject APPLYTYPE([NotNull] Context ctx, [NotNull] ZilAtom atom, - [CanBeNull] [Decl("")] ZilObject handler = null) + public static ZilObject APPLYTYPE(Context ctx, ZilAtom atom, + [Decl("")] ZilObject? handler = null) { return PerformTypeHandler(ctx, atom, handler, "APPLYTYPE", @@ -173,10 +162,9 @@ namespace Zilf.Interpreter (c, a, h) => c.SetApplyType(a, h)); } - [NotNull] - static ZilObject PerformTypeHandler([NotNull] Context ctx, [NotNull] ZilAtom atom, [CanBeNull] ZilObject handler, + static ZilObject PerformTypeHandler(Context ctx, ZilAtom atom, ZilObject? handler, string name, - Func getter, + Func getter, Func setter) { if (!ctx.IsRegisteredType(atom)) @@ -209,60 +197,53 @@ namespace Zilf.Interpreter } } - [NotNull] [Subr("MAKE-GVAL")] - public static ZilObject MAKE_GVAL([NotNull] Context ctx, ZilObject arg) + public static ZilObject MAKE_GVAL(Context ctx, ZilObject arg) { return new ZilForm(new[] { ctx.GetStdAtom(StdAtom.GVAL), arg }) { SourceLine = SourceLines.MakeGval }; } - [NotNull] [Subr("APPLICABLE?")] - public static ZilObject APPLICABLE_P([NotNull] Context ctx, ZilObject arg) + public static ZilObject APPLICABLE_P(Context ctx, ZilObject arg) { return arg.IsApplicable(ctx) ? ctx.TRUE : ctx.FALSE; } - [NotNull] [Subr("STRUCTURED?")] - public static ZilObject STRUCTURED_P([NotNull] Context ctx, ZilObject arg) + public static ZilObject STRUCTURED_P(Context ctx, ZilObject arg) { return (arg is IStructure) ? ctx.TRUE : ctx.FALSE; } - [NotNull] [Subr("LEGAL?")] - public static ZilObject LEGAL_P([NotNull] Context ctx, ZilObject arg) + public static ZilObject LEGAL_P(Context ctx, ZilObject arg) { // non-evanescent values are always legal return (arg as IEvanescent)?.IsLegal == false ? ctx.FALSE : ctx.TRUE; } - [NotNull] [Subr] - public static ZilObject FORM([NotNull] Context ctx, [NotNull] ZilObject[] args) + public static ZilObject FORM(Context ctx, ZilObject[] args) { return new ZilForm(args) { SourceLine = ctx.TopFrame.SourceLine }; } - [NotNull] [Subr] - public static ZilObject LIST([NotNull] Context ctx, [NotNull] ZilObject[] args) + public static ZilObject LIST(Context ctx, ZilObject[] args) { return new ZilList(args); } - [NotNull] [Subr] [Subr("TUPLE")] - public static ZilObject VECTOR([NotNull] Context ctx, [NotNull] ZilObject[] args) + public static ZilObject VECTOR(Context ctx, ZilObject[] args) { return new ZilVector(args); } /// is negative. [Subr] - public static ZilResult ILIST(Context ctx, int count, [CanBeNull] ZilObject init = null) + public static ZilResult ILIST(Context ctx, int count, ZilObject? init = null) { if (count < 0) throw new InterpreterError( @@ -289,7 +270,7 @@ namespace Zilf.Interpreter /// is negative. [Subr] - public static ZilResult IVECTOR(Context ctx, int count, [CanBeNull] ZilObject init = null) + public static ZilResult IVECTOR(Context ctx, int count, ZilObject? init = null) { if (count < 0) throw new InterpreterError( @@ -315,34 +296,30 @@ namespace Zilf.Interpreter return new ZilVector(contents.ToArray()); } - [NotNull] [Subr] - public static ZilObject BYTE([NotNull] Context ctx, [NotNull] ZilObject arg) + public static ZilObject BYTE(Context ctx, ZilObject arg) { return ctx.ChangeType(arg, ctx.GetStdAtom(StdAtom.BYTE)); } - [NotNull] [Subr] - public static ZilObject CONS(Context ctx, ZilObject first, [NotNull] ZilListBase rest) + public static ZilObject CONS(Context ctx, ZilObject first, ZilListBase rest) { return new ZilList( first, rest is ZilList restList ? restList : new ZilList(rest)); } - [NotNull] [FSubr] - public static ZilObject FUNCTION(Context ctx, [CanBeNull] [Optional] ZilAtom activationAtom, - [NotNull] ZilList argList, [CanBeNull] [Optional] ZilDecl decl, [NotNull] [Required] ZilObject[] body) + public static ZilObject FUNCTION(Context ctx, [Optional] ZilAtom? activationAtom, + ZilList argList, [Optional] ZilDecl? decl, [Required] ZilObject[] body) { return new ZilFunction("FUNCTION", null, activationAtom, argList, decl, body); } - [NotNull] [Subr] public static ZilObject STRING(Context ctx, - [NotNull] [Decl("]>")] ZilObject[] args) + [Decl("]>")] ZilObject[] args) { var sb = new StringBuilder(); @@ -356,7 +333,7 @@ namespace Zilf.Interpreter /// is negative. [Subr] - public static ZilResult ISTRING(Context ctx, int count, [CanBeNull] ZilObject init = null) + public static ZilResult ISTRING(Context ctx, int count, ZilObject? init = null) { if (count < 0) throw new InterpreterError( @@ -384,7 +361,6 @@ namespace Zilf.Interpreter return ZilString.FromString(new string(contents.ToArray())); } - [NotNull] [Subr] public static ZilObject ASCII(Context ctx, [Decl("")] ZilObject arg) { diff --git a/src/Zilf/Interpreter/Subrs.ZModel.cs b/src/Zilf/Interpreter/Subrs.ZModel.cs index faf9ff5..e85d69a 100644 --- a/src/Zilf/Interpreter/Subrs.ZModel.cs +++ b/src/Zilf/Interpreter/Subrs.ZModel.cs @@ -39,9 +39,8 @@ namespace Zilf.Interpreter #region Z-Code: Routines, Objects, Constants, Globals /// Unrecognized flag. - [NotNull] [Subr("ROUTINE-FLAGS")] - public static ZilObject ROUTINE_FLAGS([NotNull] Context ctx, [ItemNotNull] [NotNull] ZilAtom[] flags) + public static ZilObject ROUTINE_FLAGS(Context ctx, ZilAtom[] flags) { var newFlags = RoutineFlags.None; @@ -63,11 +62,10 @@ namespace Zilf.Interpreter } /// is already defined, or defines too many required parameters for the Z-machine version. - [NotNull] [FSubr] - public static ZilObject ROUTINE([NotNull] Context ctx, [NotNull] ZilAtom name, - [CanBeNull] [Optional] ZilAtom activationAtom, [NotNull] ZilList argList, - [ItemNotNull] [NotNull] [Required] ZilObject[] body) + public static ZilObject ROUTINE(Context ctx, ZilAtom name, + [Optional] ZilAtom? activationAtom, ZilList argList, + [Required] ZilObject[] body) { var oldAtom = ctx.ZEnvironment.InternGlobalName(name); if (ctx.GetZVal(oldAtom) != null) @@ -154,7 +152,7 @@ namespace Zilf.Interpreter } } - public ZilObject Decl + public ZilObject? Decl { get { @@ -180,7 +178,6 @@ namespace Zilf.Interpreter [Either(typeof(ZilAtom), typeof(string))] public object Content; - [NotNull] public ZilAtom GetAtom(Context ctx) { if (Content is ZilAtom atom) @@ -189,10 +186,7 @@ namespace Zilf.Interpreter return ZilAtom.Parse((string)Content, ctx); } - public override string ToString() - { - return Content.ToString(); - } + public override string ToString() => Content.ToString()!; } } #pragma warning restore CS0649 @@ -200,8 +194,8 @@ namespace Zilf.Interpreter /// is already defined. [FSubr] [FSubr("MSETG")] - public static ZilResult CONSTANT([NotNull] Context ctx, - AtomParams.AdeclOrAtom name, [NotNull] ZilObject value) + public static ZilResult CONSTANT(Context ctx, + AtomParams.AdeclOrAtom name, ZilObject value) { var atom = name.Atom; var zr = value.Eval(ctx); @@ -225,7 +219,9 @@ namespace Zilf.Interpreter } else { - throw new InterpreterError(InterpreterMessages._0_Already_Defined_1, "CONSTANT", oldAtom.ToStringContext(ctx, false)); + throw new InterpreterError(InterpreterMessages._0_Already_Defined_1, + "CONSTANT", + oldAtom.ToStringContext(ctx, false)); } } @@ -237,12 +233,12 @@ namespace Zilf.Interpreter /// is already defined. [FSubr] public static ZilResult GLOBAL( - [NotNull] Context ctx, + Context ctx, AtomParams.AdeclOrAtom name, ZilObject defaultValue, #pragma warning disable RECS0154 // Parameter is never used - [CanBeNull] ZilObject decl = null, - [CanBeNull] ZilAtom size = null) + ZilObject? decl = null, + ZilAtom? size = null) #pragma warning restore RECS0154 // Parameter is never used { // typical form: @@ -261,20 +257,22 @@ namespace Zilf.Interpreter var oldVal = ctx.GetZVal(oldAtom); if (oldVal != null) { - if (ctx.AllowRedefine) + if (!ctx.AllowRedefine) { - if (oldVal is ZilGlobal glob && glob.Value is ZilTable tbl) - { - // prevent errors about duplicate symbol T?GLOBAL-NAME - // TODO: undefine the table if it hasn't been referenced anywhere yet - tbl.Name = null; - } + throw new InterpreterError(InterpreterMessages._0_Already_Defined_1, + "GLOBAL", + oldAtom.ToStringContext(ctx, false)); + } - ctx.Redefine(oldAtom); - ctx.ZEnvironment.InternGlobalName(atom); + if (oldVal is ZilGlobal glob && glob.Value is ZilTable tbl) + { + // prevent errors about duplicate symbol T?GLOBAL-NAME + // TODO: undefine the table if it hasn't been referenced anywhere yet + tbl.Name = null; } - else - throw new InterpreterError(InterpreterMessages._0_Already_Defined_1, "GLOBAL", oldAtom.ToStringContext(ctx, false)); + + ctx.Redefine(oldAtom); + ctx.ZEnvironment.InternGlobalName(atom); } if (defaultValue is ZilTable table) @@ -305,11 +303,11 @@ namespace Zilf.Interpreter [FSubr("DEFINE-GLOBALS")] public static ZilResult DEFINE_GLOBALS( - [NotNull] Context ctx, + Context ctx, #pragma warning disable RECS0154 // Parameter is never used ZilAtom groupName, #pragma warning restore RECS0154 // Parameter is never used - [NotNull] DefineGlobalsParams.GlobalSpec[] args) + DefineGlobalsParams.GlobalSpec[] args) { foreach (var spec in args) { @@ -317,7 +315,7 @@ namespace Zilf.Interpreter // create global and macros var globalAtom = ZilAtom.Parse("G?" + name.Text, ctx); - ZilObject initializer; + ZilObject? initializer; if (spec.Initializer != null) { var zr = spec.Initializer.Eval(ctx); @@ -355,37 +353,34 @@ namespace Zilf.Interpreter return ctx.TRUE; } - [NotNull] [Subr] - public static ZilObject OBJECT([NotNull] Context ctx, [NotNull] ZilAtom name, - [NotNull] [Decl("")] ZilList[] props) + public static ZilObject OBJECT(Context ctx, ZilAtom name, + [Decl("")] ZilList[] props) { return PerformObject(ctx, name, props, false); } - [NotNull] [Subr] - public static ZilObject ROOM([NotNull] Context ctx, [NotNull] ZilAtom name, - [NotNull] [Decl("")] ZilList[] props) + public static ZilObject ROOM(Context ctx, ZilAtom name, + [Decl("")] ZilList[] props) { return PerformObject(ctx, name, props, true); } - [NotNull] - static ZilObject PerformObject([NotNull] Context ctx, [NotNull] ZilAtom atom, [NotNull] ZilList[] props, bool isRoom) + static ZilObject PerformObject(Context ctx, ZilAtom atom, ZilList[] props, bool isRoom) { string name = isRoom ? "ROOM" : "OBJECT"; var oldAtom = ctx.ZEnvironment.InternGlobalName(atom); if (ctx.GetZVal(oldAtom) != null) { - if (ctx.AllowRedefine) - { - ctx.Redefine(atom); - ctx.ZEnvironment.InternGlobalName(atom); - } - else - throw new InterpreterError(InterpreterMessages._0_Already_Defined_1, name, oldAtom.ToStringContext(ctx, false)); + if (!ctx.AllowRedefine) + throw new InterpreterError(InterpreterMessages._0_Already_Defined_1, + name, + oldAtom.ToStringContext(ctx, false)); + + ctx.Redefine(atom); + ctx.ZEnvironment.InternGlobalName(atom); } var zmo = new ZilModelObject(atom, props, isRoom) { SourceLine = ctx.TopFrame.SourceLine }; @@ -395,7 +390,7 @@ namespace Zilf.Interpreter } [FSubr] - public static ZilResult PROPDEF([NotNull] Context ctx, [NotNull] ZilAtom atom, [NotNull] ZilObject defaultValue, ZilObject[] spec) + public static ZilResult PROPDEF(Context ctx, ZilAtom atom, ZilObject defaultValue, ZilObject[] spec) { if (ctx.ZEnvironment.PropertyDefaults.ContainsKey(atom)) ctx.HandleError(new InterpreterError(InterpreterMessages.Overriding_Default_Value_For_Property_0, atom)); @@ -407,27 +402,26 @@ namespace Zilf.Interpreter ctx.ZEnvironment.PropertyDefaults[atom] = (ZilObject)zr; // complex property patterns - if (spec.Length > 0) - { - var pattern = ComplexPropDef.Parse(spec); - ctx.SetPropDef(atom, pattern); - } + if (spec.Length <= 0) + return atom; + + var pattern = ComplexPropDef.Parse(spec); + ctx.SetPropDef(atom, pattern); return atom; } [Subr] - public static ZilObject ZSTART([NotNull] Context ctx, ZilAtom atom) + public static ZilObject ZSTART(Context ctx, ZilAtom atom) { ctx.ZEnvironment.EntryRoutineName = atom; return atom; } /// One of the is already defined. - [NotNull] [Subr("BIT-SYNONYM")] - public static ZilObject BIT_SYNONYM([NotNull] Context ctx, [NotNull] ZilAtom first, - [NotNull] [Required] ZilAtom[] synonyms) + public static ZilObject BIT_SYNONYM(Context ctx, ZilAtom first, + [Required] ZilAtom[] synonyms) { if (ctx.ZEnvironment.TryGetBitSynonym(first, out var original)) first = original; @@ -448,12 +442,11 @@ namespace Zilf.Interpreter #region Z-Code: Tables /// The syntax is invalid, or is less than 1. - [NotNull] [Subr] - public static ZilObject ITABLE([NotNull] Context ctx, - [CanBeNull] [Optional] ZilAtom specifier, + public static ZilObject ITABLE(Context ctx, + [Optional] ZilAtom? specifier, int count, - [CanBeNull] [Optional, Decl("")] ZilList flagList, + [Optional, Decl("")] ZilList? flagList, ZilObject[] initializer) { // Syntax: @@ -535,32 +528,32 @@ namespace Zilf.Interpreter } } - if (initializer.Length == 0) - initializer = null; - - var tab = ZilTable.Create(count, initializer, flags, null); + var tab = ZilTable.Create(count, initializer.Length == 0 ? null : initializer, flags, null); tab.SourceLine = ctx.TopFrame.SourceLine; if ((flags & TableFlags.TempTable) == 0) ctx.ZEnvironment.Tables.Add(tab); return tab; } - [NotNull] - static ZilTable PerformTable([NotNull] Context ctx, ZilListoidBase flagList, [ItemNotNull] [NotNull] ZilObject[] values, + static ZilTable PerformTable(Context ctx, ZilListoidBase? flagList, ZilObject[] values, bool pure, bool wantLength) { // syntax: // <[P][L]TABLE [(flags...)] values...> - string name = pure ? - (wantLength ? "PLTABLE" : "PTABLE") : - (wantLength ? "LTABLE" : "TABLE"); + var name = (pure, wantLength) switch + { + (true, true) => "PLTABLE", + (true, false) => "PTABLE", + (false, true) => "LTABLE", + _ => "TABLE", + }; const int T_WORDS = 0; const int T_BYTES = 1; const int T_STRING = 2; int type = T_WORDS; - ZilObject[] pattern = null; + ZilObject[]? pattern = null; bool tempTable = false; bool parserTable = false; @@ -660,7 +653,7 @@ namespace Zilf.Interpreter return tab; } - static void ValidateTablePattern([NotNull] string name, [NotNull] ZilObject[] pattern) + static void ValidateTablePattern(string name, ZilObject[] pattern) { if (pattern.Length == 0) throw new InterpreterError(InterpreterMessages._0_PATTERN_Must_Not_Be_Empty, name); @@ -706,42 +699,37 @@ namespace Zilf.Interpreter return value is ZilAtom atom && (atom.StdAtom == StdAtom.BYTE || atom.StdAtom == StdAtom.WORD); } - [NotNull] [Subr] - public static ZilObject TABLE([NotNull] Context ctx, [CanBeNull] [Optional] ZilList flagList, - [ItemNotNull] [NotNull] ZilObject[] values) + public static ZilObject TABLE(Context ctx, [Optional] ZilList? flagList, + ZilObject[] values) { return PerformTable(ctx, flagList, values, false, false); } - [NotNull] [Subr] - public static ZilObject LTABLE([NotNull] Context ctx, [CanBeNull] [Optional] ZilList flagList, - [ItemNotNull] [NotNull] ZilObject[] values) + public static ZilObject LTABLE(Context ctx, [Optional] ZilList? flagList, + ZilObject[] values) { return PerformTable(ctx, flagList, values, false, true); } - [NotNull] [Subr] - public static ZilObject PTABLE([NotNull] Context ctx, [CanBeNull] [Optional] ZilList flagList, - [NotNull] ZilObject[] values) + public static ZilObject PTABLE(Context ctx, [Optional] ZilList? flagList, + ZilObject[] values) { return PerformTable(ctx, flagList, values, true, false); } - [NotNull] [Subr] - public static ZilObject PLTABLE([NotNull] Context ctx, [CanBeNull] [Optional] ZilList flagList, - [NotNull] ZilObject[] values) + public static ZilObject PLTABLE(Context ctx, [Optional] ZilList? flagList, + ZilObject[] values) { return PerformTable(ctx, flagList, values, true, true); } /// is out of range, or the element at is not a word. - [NotNull] [Subr] - public static ZilObject ZGET([NotNull] Context ctx, [NotNull] [Decl("")] ZilObject tableish, int index) + public static ZilObject ZGET(Context ctx, [Decl("")] ZilObject tableish, int index) { if (index < 0) throw new InterpreterError(InterpreterMessages._0_Negative_Element_Count, "ZGET"); @@ -766,10 +754,9 @@ namespace Zilf.Interpreter } /// is out of range. - [NotNull] [Subr] - public static ZilObject ZPUT([NotNull] Context ctx, [NotNull] [Decl("")] ZilObject tableish, int index, - [NotNull] ZilObject newValue) + public static ZilObject ZPUT(Context ctx, [Decl("")] ZilObject tableish, int index, + ZilObject newValue) { if (index < 0) throw new InterpreterError(InterpreterMessages._0_Negative_Element_Count, "ZPUT"); @@ -783,9 +770,8 @@ namespace Zilf.Interpreter return newValue; } - [NotNull] [Subr] - public static ZilObject GETB([NotNull] Context ctx, [NotNull] [Decl("")] ZilObject tableish, int index) + public static ZilObject GETB(Context ctx, [Decl("")] ZilObject tableish, int index) { if (index < 0) throw new InterpreterError(InterpreterMessages._0_Negative_Element_Count, "GETB"); @@ -809,10 +795,9 @@ namespace Zilf.Interpreter } } - [NotNull] [Subr] - public static ZilObject PUTB([NotNull] Context ctx, [NotNull] [Decl("")] ZilObject tableish, int index, - [NotNull] ZilObject newValue) + public static ZilObject PUTB(Context ctx, [Decl("")] ZilObject tableish, int index, + ZilObject newValue) { if (index < 0) throw new InterpreterError(InterpreterMessages._0_Negative_Element_Count, "PUTB"); @@ -826,9 +811,8 @@ namespace Zilf.Interpreter return newValue; } - [NotNull] [Subr] - public static ZilObject ZREST([NotNull] Context ctx, [NotNull] [Decl("")] ZilObject tableish, int bytes) + public static ZilObject ZREST(Context ctx, [Decl("")] ZilObject tableish, int bytes) { if (bytes < 0) throw new InterpreterError(InterpreterMessages._0_Negative_Element_Count, "ZREST"); @@ -845,11 +829,10 @@ namespace Zilf.Interpreter #region Z-Code: Version, Options, Capabilities - [NotNull] [Subr] - public static ZilObject VERSION([NotNull] Context ctx, - [NotNull] ZilObject versionExpr, - [CanBeNull] [Decl("'TIME")] ZilAtom time = null) + public static ZilObject VERSION(Context ctx, + ZilObject versionExpr, + [Decl("'TIME")] ZilAtom? time = null) { var newVersion = ParseZVersion("VERSION", versionExpr); @@ -866,7 +849,7 @@ namespace Zilf.Interpreter return new ZilFix(newVersion); } - static int ParseZVersion([NotNull] string name, [NotNull] ZilObject expr) + static int ParseZVersion(string name, ZilObject expr) { int newVersion; switch (expr) @@ -913,17 +896,16 @@ namespace Zilf.Interpreter return newVersion; } - [NotNull] [Subr("CHECK-VERSION?")] - public static ZilObject CHECK_VERSION_P([NotNull] Context ctx, [NotNull] ZilObject versionExpr) + public static ZilObject CHECK_VERSION_P(Context ctx, ZilObject versionExpr) { var version = ParseZVersion("CHECK-VERSION?", versionExpr); return ctx.ZEnvironment.ZVersion == version ? ctx.TRUE : ctx.FALSE; } [FSubr("VERSION?")] - public static ZilResult VERSION_P([NotNull] Context ctx, - [NotNull] CondClause[] clauses) + public static ZilResult VERSION_P(Context ctx, + CondClause[] clauses) { var tAtom = ctx.GetStdAtom(StdAtom.T); var elseAtom = ctx.GetStdAtom(StdAtom.ELSE); @@ -949,9 +931,8 @@ namespace Zilf.Interpreter return ctx.FALSE; } - [NotNull] [Subr("ORDER-OBJECTS?")] - public static ZilObject ORDER_OBJECTS_P([NotNull] Context ctx, [NotNull] ZilAtom atom) + public static ZilObject ORDER_OBJECTS_P(Context ctx, ZilAtom atom) { switch (atom.StdAtom) { @@ -975,9 +956,8 @@ namespace Zilf.Interpreter "DEFINED, ROOMS-FIRST, ROOMS-AND-LGS-FIRST, or ROOMS-LAST"); } - [NotNull] [Subr("ORDER-TREE?")] - public static ZilObject ORDER_TREE_P([NotNull] Context ctx, [NotNull] ZilAtom atom) + public static ZilObject ORDER_TREE_P(Context ctx, ZilAtom atom) { switch (atom.StdAtom) { @@ -995,7 +975,7 @@ namespace Zilf.Interpreter [Subr("ORDER-FLAGS?")] public static ZilObject ORDER_FLAGS_P(Context ctx, [Decl("'LAST")] ZilAtom order, - [NotNull] [Required] ZilAtom[] objects) + [Required] ZilAtom[] objects) { foreach (var atom in objects) { @@ -1006,9 +986,8 @@ namespace Zilf.Interpreter } /// Unrecognized option. - [NotNull] [Subr("ZIP-OPTIONS")] - public static ZilObject ZIP_OPTIONS([NotNull] Context ctx, [NotNull] ZilAtom[] args) + public static ZilObject ZIP_OPTIONS(Context ctx, ZilAtom[] args) { foreach (var atom in args) { @@ -1055,28 +1034,25 @@ namespace Zilf.Interpreter return ctx.TRUE; } - [NotNull] [Subr("LONG-WORDS?")] - public static ZilObject LONG_WORDS_P([NotNull] Context ctx, bool enabled = true) + public static ZilObject LONG_WORDS_P(Context ctx, bool enabled = true) { ctx.DefineCompilationFlag(ctx.GetStdAtom(StdAtom.LONG_WORDS), enabled ? ctx.TRUE : ctx.FALSE, true); return ctx.TRUE; } - [NotNull] [Subr("FUNNY-GLOBALS?")] - public static ZilObject FUNNY_GLOBALS_P([NotNull] Context ctx, bool enabled = true) + public static ZilObject FUNNY_GLOBALS_P(Context ctx, bool enabled = true) { ctx.SetGlobalVal(ctx.GetStdAtom(StdAtom.DO_FUNNY_GLOBALS_P), enabled ? ctx.TRUE : ctx.FALSE); return ctx.TRUE; } - [NotNull] [Subr] public static ZilObject CHRSET(Context ctx, int alphabetNum, - [NotNull] [Required, Decl("]>")] ZilObject[] args) + [Required, Decl("]>")] ZilObject[] args) { if (alphabetNum < 0 || alphabetNum > 2) throw new InterpreterError(InterpreterMessages._0_Alphabet_Number_Must_Be_Between_0_And_2, "CHRSET"); @@ -1130,9 +1106,8 @@ namespace Zilf.Interpreter return ZilString.FromString(alphabetStr); } - [NotNull] [Subr] - public static ZilObject LANGUAGE([NotNull] Context ctx, [NotNull] ZilAtom name, char escapeChar = '%', bool changeChrset = true) + public static ZilObject LANGUAGE(Context ctx, ZilAtom name, char escapeChar = '%', bool changeChrset = true) { var language = ZModel.Language.Get(name.Text) ?? throw new InterpreterError(InterpreterMessages._0_Unrecognized_1_2, "LANGUAGE", "language", name.Text); @@ -1155,9 +1130,8 @@ namespace Zilf.Interpreter #region Z-Code: Vocabulary and Syntax - [NotNull] [Subr] - public static ZilObject DIRECTIONS([NotNull] Context ctx, [NotNull] [Required] ZilAtom[] args) + public static ZilObject DIRECTIONS(Context ctx, [Required] ZilAtom[] args) { // if a PROPSPEC is set for DIRECTIONS, it'll be copied to the new direction properties var propspecAtom = ctx.GetStdAtom(StdAtom.PROPSPEC); @@ -1176,9 +1150,8 @@ namespace Zilf.Interpreter return ctx.TRUE; } - [NotNull] [Subr] - public static ZilObject BUZZ([NotNull] Context ctx, [NotNull] [Required] ZilAtom[] args) + public static ZilObject BUZZ(Context ctx, [Required] ZilAtom[] args) { foreach (var arg in args) ctx.ZEnvironment.Buzzwords.Add(new KeyValuePair(arg, ctx.TopFrame.SourceLine)); @@ -1186,9 +1159,8 @@ namespace Zilf.Interpreter return ctx.TRUE; } - [NotNull] [Subr] - public static ZilObject VOC([NotNull] Context ctx, [NotNull] string text, [CanBeNull] [Decl("")] ZilObject type = null) + public static ZilObject VOC(Context ctx, string text, [Decl("")] ZilObject? type = null) { var atom = ZilAtom.Parse(text, ctx); ctx.ZEnvironment.GetVocab(atom); @@ -1232,9 +1204,8 @@ namespace Zilf.Interpreter } /// is too short. - [NotNull] [Subr] - public static ZilObject SYNTAX([NotNull] Context ctx, [NotNull] ZilObject[] args) + public static ZilObject SYNTAX(Context ctx, ZilObject[] args) { if (args.Length < 3) throw ArgumentCountError.WrongCount(new FunctionCallSite("SYNTAX"), 3, null); @@ -1250,10 +1221,9 @@ namespace Zilf.Interpreter return syntax.Verb.Atom; } - [NotNull] - static ZilObject PerformSynonym([NotNull] Context ctx, [NotNull] ZilAtom original, [NotNull] ZilAtom[] synonyms, [NotNull] Type synonymType) + static ZilObject PerformSynonym(Context ctx, ZilAtom original, ZilAtom[] synonyms, Type synonymType) { - if (ctx.ZEnvironment.Vocabulary.TryGetValue(original, out var oldWord) == false) + if (!ctx.ZEnvironment.Vocabulary.TryGetValue(original, out var oldWord)) { oldWord = ctx.ZEnvironment.VocabFormat.CreateWord(original); ctx.ZEnvironment.Vocabulary.Add(original, oldWord); @@ -1264,7 +1234,7 @@ namespace Zilf.Interpreter foreach (var synonym in synonyms) { - if (ctx.ZEnvironment.Vocabulary.TryGetValue(synonym, out var newWord) == false) + if (!ctx.ZEnvironment.Vocabulary.TryGetValue(synonym, out var newWord)) { newWord = ctx.ZEnvironment.VocabFormat.CreateWord(synonym); ctx.ZEnvironment.Vocabulary.Add(synonym, newWord); @@ -1272,43 +1242,38 @@ namespace Zilf.Interpreter ctorArgs[1] = newWord; ctx.ZEnvironment.Synonyms.Add((Synonym)Activator.CreateInstance( - synonymType, ctorArgs)); + synonymType, ctorArgs)!); } return original; } - [NotNull] [Subr] - public static ZilObject SYNONYM([NotNull] Context ctx, [NotNull] ZilAtom original, [NotNull] ZilAtom[] synonyms) + public static ZilObject SYNONYM(Context ctx, ZilAtom original, ZilAtom[] synonyms) { return PerformSynonym(ctx, original, synonyms, typeof(Synonym)); } - [NotNull] [Subr("VERB-SYNONYM")] - public static ZilObject VERB_SYNONYM([NotNull] Context ctx, [NotNull] ZilAtom original, [NotNull] ZilAtom[] synonyms) + public static ZilObject VERB_SYNONYM(Context ctx, ZilAtom original, ZilAtom[] synonyms) { return PerformSynonym(ctx, original, synonyms, typeof(VerbSynonym)); } - [NotNull] [Subr("PREP-SYNONYM")] - public static ZilObject PREP_SYNONYM([NotNull] Context ctx, [NotNull] ZilAtom original, [NotNull] ZilAtom[] synonyms) + public static ZilObject PREP_SYNONYM(Context ctx, ZilAtom original, ZilAtom[] synonyms) { return PerformSynonym(ctx, original, synonyms, typeof(PrepSynonym)); } - [NotNull] [Subr("ADJ-SYNONYM")] - public static ZilObject ADJ_SYNONYM([NotNull] Context ctx, [NotNull] ZilAtom original, [NotNull] ZilAtom[] synonyms) + public static ZilObject ADJ_SYNONYM(Context ctx, ZilAtom original, ZilAtom[] synonyms) { return PerformSynonym(ctx, original, synonyms, typeof(AdjSynonym)); } - [NotNull] [Subr("DIR-SYNONYM")] - public static ZilObject DIR_SYNONYM([NotNull] Context ctx, [NotNull] ZilAtom original, [NotNull] ZilAtom[] synonyms) + public static ZilObject DIR_SYNONYM(Context ctx, ZilAtom original, ZilAtom[] synonyms) { return PerformSynonym(ctx, original, synonyms, typeof(DirSynonym)); } @@ -1317,17 +1282,15 @@ namespace Zilf.Interpreter #region Z-Code: Tell - [NotNull] [FSubr("TELL-TOKENS")] - public static ZilObject TELL_TOKENS([NotNull] Context ctx, [NotNull] ZilObject[] args) + public static ZilObject TELL_TOKENS(Context ctx, ZilObject[] args) { ctx.ZEnvironment.TellPatterns.Clear(); return ADD_TELL_TOKENS(ctx, args); } - [NotNull] [FSubr("ADD-TELL-TOKENS")] - public static ZilObject ADD_TELL_TOKENS([NotNull] Context ctx, [NotNull] ZilObject[] args) + public static ZilObject ADD_TELL_TOKENS(Context ctx, ZilObject[] args) { ctx.ZEnvironment.TellPatterns.AddRange(TellPattern.Parse(args)); return ctx.TRUE; @@ -1338,20 +1301,19 @@ namespace Zilf.Interpreter #region Z-Code: Version 6 Parser /// NEW-PARSER? is not enabled. - [NotNull] [Subr("ADD-WORD")] [Subr("NEW-ADD-WORD")] - public static ZilObject NEW_ADD_WORD([NotNull] Context ctx, + public static ZilObject NEW_ADD_WORD(Context ctx, AtomParams.StringOrAtom name, - [CanBeNull] ZilAtom type = null, - [CanBeNull] ZilObject value = null, - ZilFix flags = null) + ZilAtom? type = null, + ZilObject? value = null, + ZilFix? flags = null) { if (!ctx.GetGlobalOption(StdAtom.NEW_PARSER_P)) throw new InterpreterError(InterpreterMessages._0_Requires_NEWPARSER_Option, "NEW-ADD-WORD"); var nameAtom = name.GetAtom(ctx); - flags = flags ?? ZilFix.Zero; + flags ??= ZilFix.Zero; return ((NewParserVocabFormat)ctx.ZEnvironment.VocabFormat).NewAddWord(nameAtom, type, value, flags); } diff --git a/src/Zilf/Interpreter/Subrs.cs b/src/Zilf/Interpreter/Subrs.cs index 06c7e27..7cb3607 100644 --- a/src/Zilf/Interpreter/Subrs.cs +++ b/src/Zilf/Interpreter/Subrs.cs @@ -30,16 +30,14 @@ namespace Zilf.Interpreter [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] public abstract class SubrAttributeBase : Attribute { - protected SubrAttributeBase([CanBeNull] string name) + protected SubrAttributeBase(string? name) { Name = name; } - [CanBeNull] - public string Name { get; } + public string? Name { get; } - [CanBeNull] - public string ObList { get; set; } + public string? ObList { get; set; } } public sealed class SubrAttribute : SubrAttributeBase @@ -49,7 +47,7 @@ namespace Zilf.Interpreter { } - public SubrAttribute([NotNull] string name) + public SubrAttribute(string name) : base(name) { } @@ -62,7 +60,7 @@ namespace Zilf.Interpreter { } - public FSubrAttribute([NotNull] string name) + public FSubrAttribute(string name) : base(name) { } @@ -71,16 +69,14 @@ namespace Zilf.Interpreter [AttributeUsage(AttributeTargets.Method)] public sealed class MdlZilRedirectAttribute : Attribute { - public MdlZilRedirectAttribute([NotNull] Type type, [NotNull] string target) + public MdlZilRedirectAttribute(Type type, string target) { Type = type; Target = target; } - [NotNull] public Type Type { get; } - [NotNull] public string Target { get; } public bool TopLevelOnly { get; set; } diff --git a/src/Zilf/Interpreter/Values/Tied/TiedLayout.cs b/src/Zilf/Interpreter/Values/Tied/TiedLayout.cs index df37b6d..e5152e4 100644 --- a/src/Zilf/Interpreter/Values/Tied/TiedLayout.cs +++ b/src/Zilf/Interpreter/Values/Tied/TiedLayout.cs @@ -29,8 +29,7 @@ namespace Zilf.Interpreter.Values.Tied { internal static readonly Dictionary Layouts = new Dictionary(); - [NotNull] - public static TiedLayout Create(params Expression>[] elements) + public static TiedLayout Create(params Expression>[] elements) where T : ZilObject, IStructure { var properties = from e in elements @@ -41,18 +40,17 @@ namespace Zilf.Interpreter.Values.Tied return new TiedLayout(properties.ToArray()); } - TiedLayout(IReadOnlyList properties, [CanBeNull] PropertyInfo catchAll = null) + TiedLayout(IReadOnlyList properties, PropertyInfo? catchAll = null) { PropertyInfos = properties; CatchAllPropertyInfo = catchAll; } public IReadOnlyList PropertyInfos { get; } - public PropertyInfo CatchAllPropertyInfo { get; } + public PropertyInfo? CatchAllPropertyInfo { get; } public int MinLength => PropertyInfos.Count; - [NotNull] - public TiedLayout WithCatchAll([NotNull] Expression> catchAll) + public TiedLayout WithCatchAll(Expression> catchAll) where T : ZilObject, IStructure { if (CatchAllPropertyInfo != null) diff --git a/src/Zilf/Interpreter/Values/Tied/ZilTiedListBase.cs b/src/Zilf/Interpreter/Values/Tied/ZilTiedListBase.cs index 82361ce..f7a1185 100644 --- a/src/Zilf/Interpreter/Values/Tied/ZilTiedListBase.cs +++ b/src/Zilf/Interpreter/Values/Tied/ZilTiedListBase.cs @@ -29,7 +29,6 @@ namespace Zilf.Interpreter.Values.Tied [SuppressMessage("ReSharper", "PatternAlwaysOfType")] abstract class ZilTiedListBase : ZilListoidBase { - [NotNull] protected abstract TiedLayout GetLayout(); TiedLayout MyLayout @@ -50,7 +49,6 @@ namespace Zilf.Interpreter.Values.Tied } } - [NotNull] public sealed override ZilObject GetPrimitive(Context ctx) { return new ZilList(this); @@ -76,7 +74,6 @@ namespace Zilf.Interpreter.Values.Tied static readonly ObList detachedObList = new ObList(); - [NotNull] protected static ZilAtom GetStdAtom(StdAtom stdAtom) { /* Tied values with atoms in their printed representation may need to return @@ -88,7 +85,6 @@ namespace Zilf.Interpreter.Values.Tied return detachedObList[stdAtom.ToString()]; } - [NotNull] protected static ZilObject FALSE { get @@ -111,16 +107,16 @@ namespace Zilf.Interpreter.Values.Tied if (index >= 0) { if (index < layout.MinLength) - return (ZilObject)layout.PropertyInfos[index].GetValue(this); + return (ZilObject?)layout.PropertyInfos[index].GetValue(this)!; if (layout.CatchAllPropertyInfo is PropertyInfo pi) { - var catchAll = (IStructure)pi.GetValue(this); - return catchAll[index - layout.MinLength]; + var catchAll = (IStructure)pi.GetValue(this)!; + return catchAll[index - layout.MinLength]!; } } - return null; + return null!; } set @@ -146,7 +142,7 @@ namespace Zilf.Interpreter.Values.Tied { if (pi.CanWrite) { - var catchAll = (IStructure)pi.GetValue(this); + var catchAll = (IStructure)pi.GetValue(this)!; catchAll[index - layout.MinLength] = value; pi.SetValue(this, catchAll); } @@ -169,35 +165,34 @@ namespace Zilf.Interpreter.Values.Tied { var layout = MyLayout; - var query = layout.PropertyInfos.Select(pi => (ZilObject)pi.GetValue(this)); + var query = layout.PropertyInfos.Select(pi => (ZilObject)pi.GetValue(this)!); if (layout.CatchAllPropertyInfo is PropertyInfo pi2) - query = query.Concat((IStructure)pi2.GetValue(this)); + query = query.Concat((IStructure)pi2.GetValue(this)!); return query.GetEnumerator(); } - public sealed override ZilObject First + public sealed override ZilObject? First { get { var layout = MyLayout; if (layout.MinLength > 0) - return (ZilObject)layout.PropertyInfos[0].GetValue(this); + return (ZilObject)layout.PropertyInfos[0].GetValue(this)!; if (layout.CatchAllPropertyInfo is PropertyInfo pi) - return ((IStructure)pi.GetValue(this)).GetFirst(); + return ((IStructure)pi.GetValue(this)!).GetFirst(); return null; } - set => this[0] = value; + set => this[0] = value!; } // ReSharper disable once AnnotationConflictInHierarchy - [NotNull] - public sealed override ZilListoidBase Rest + public sealed override ZilListoidBase? Rest { get => GetRest(1) ?? new ZilList(null, null); set => throw new NotSupportedException(); @@ -208,7 +203,7 @@ namespace Zilf.Interpreter.Values.Tied var result = MyLayout.PropertyInfos.Count; if (MyLayout.CatchAllPropertyInfo is PropertyInfo pi) - result += ((IStructure)pi.GetValue(this)).GetLength(); + result += ((IStructure)pi.GetValue(this)!).GetLength(); return result; } @@ -222,7 +217,7 @@ namespace Zilf.Interpreter.Values.Tied if (MyLayout.CatchAllPropertyInfo is PropertyInfo pi) { - var more = ((IStructure)pi.GetValue(this)).GetLength(limit - result); + var more = ((IStructure)pi.GetValue(this)!).GetLength(limit - result); if (more == null) return null; @@ -236,7 +231,7 @@ namespace Zilf.Interpreter.Values.Tied return result; } - public sealed override ZilListoidBase GetRest(int skip) + public sealed override ZilListoidBase? GetRest(int skip) { return this.HasLengthAtLeast(skip) ? new Wrapper(this, skip) : null; } @@ -268,15 +263,14 @@ namespace Zilf.Interpreter.Values.Tied return orig.Skip(offset).GetEnumerator(); } - public override ZilObject First + public override ZilObject? First { get => orig[offset]; - set => orig[offset] = value; + set => orig[offset] = value!; } // ReSharper disable once AnnotationConflictInHierarchy - [NotNull] - public override ZilListoidBase Rest + public override ZilListoidBase? Rest { get { @@ -290,13 +284,12 @@ namespace Zilf.Interpreter.Values.Tied public override int? GetLength(int limit) => orig.GetLength(limit + offset) - offset; - [NotNull] public override ZilObject GetPrimitive(Context ctx) { return new ZilList(this); } - public override ZilListoidBase GetRest(int skip) + public override ZilListoidBase? GetRest(int skip) { return GetLength(skip) < skip ? null : new Wrapper(orig, offset + skip); } diff --git a/src/Zilf/Interpreter/Values/ZilActivation.cs b/src/Zilf/Interpreter/Values/ZilActivation.cs index 215f6af..3e1ee7e 100644 --- a/src/Zilf/Interpreter/Values/ZilActivation.cs +++ b/src/Zilf/Interpreter/Values/ZilActivation.cs @@ -17,6 +17,7 @@ */ using System; +using System.Diagnostics.CodeAnalysis; using Zilf.Language; using Zilf.Diagnostics; using JetBrains.Annotations; @@ -41,7 +42,10 @@ namespace Zilf.Interpreter.Values /// Always thrown. [ChtypeMethod] [ContractAnnotation("=> halt")] - public static ZilActivation FromAtom([NotNull] Context ctx, [NotNull] ZilAtom name) => + [DoesNotReturn] + [SuppressMessage("Style", "IDE0060:Remove unused parameter")] + [SuppressMessage("Performance", "CA1801:Unused parameter")] + public static ZilActivation FromAtom(Context ctx, ZilAtom name) => throw new InterpreterError(InterpreterMessages.CHTYPE_To_0_Not_Supported, "ACTIVATION"); public override StdAtom StdTypeAtom => StdAtom.ACTIVATION; diff --git a/src/Zilf/Interpreter/Values/ZilAdecl.cs b/src/Zilf/Interpreter/Values/ZilAdecl.cs index 90ecfcb..f3a8b04 100644 --- a/src/Zilf/Interpreter/Values/ZilAdecl.cs +++ b/src/Zilf/Interpreter/Values/ZilAdecl.cs @@ -29,38 +29,34 @@ namespace Zilf.Interpreter.Values [BuiltinType(StdAtom.ADECL, PrimType.VECTOR)] sealed class ZilAdecl : ZilObject, IStructure { - [NotNull] public ZilObject First; - [NotNull] public ZilObject Second; /// has the wrong number of elements. [ChtypeMethod] - public ZilAdecl([NotNull] ZilVector vector) + public ZilAdecl(ZilVector vector) { if (vector.GetLength() != 2) throw new InterpreterError(InterpreterMessages._0_Must_Have_1_Element1s, "vector coerced to ADECL", 2); - First = vector[0]; - Second = vector[1]; + First = vector[0]!; + Second = vector[1]!; } - public ZilAdecl([NotNull] ZilObject first, [NotNull] ZilObject second) + public ZilAdecl(ZilObject first, ZilObject second) { First = first ?? throw new ArgumentNullException(nameof(first)); Second = second ?? throw new ArgumentNullException(nameof(second)); } - public void Deconstruct([NotNull] out ZilObject first, [NotNull] out ZilObject second) + public void Deconstruct(out ZilObject first, out ZilObject second) { first = this.First; second = this.Second; } - public override bool StructurallyEquals(ZilObject obj) - { - return obj is ZilAdecl other && other.First.StructurallyEquals(First) && other.Second.StructurallyEquals(Second); - } + public override bool StructurallyEquals(ZilObject? obj) => + obj is ZilAdecl other && other.First.StructurallyEquals(First) && other.Second.StructurallyEquals(Second); public override string ToString() { @@ -78,22 +74,16 @@ namespace Zilf.Interpreter.Values return ":..."; } - protected override string ToStringContextImpl(Context ctx, bool friendly) - { - return First.ToStringContext(ctx, friendly) + ":" + Second.ToStringContext(ctx, friendly); - } + protected override string ToStringContextImpl(Context ctx, bool friendly) => + First.ToStringContext(ctx, friendly) + ":" + Second.ToStringContext(ctx, friendly); public override StdAtom StdTypeAtom => StdAtom.ADECL; public override PrimType PrimType => PrimType.VECTOR; - [NotNull] - public override ZilObject GetPrimitive(Context ctx) - { - return new ZilVector(First, Second); - } + public override ZilObject GetPrimitive(Context ctx) => new ZilVector(First, Second); - protected override ZilResult EvalImpl(Context ctx, LocalEnvironment environment, ZilAtom originalType) + protected override ZilResult EvalImpl(Context ctx, LocalEnvironment? environment, ZilAtom? originalType) { var result = First.Eval(ctx, environment); if (!result.ShouldPass()) @@ -105,38 +95,23 @@ namespace Zilf.Interpreter.Values #region IStructure Members - [NotNull] - public ZilObject GetFirst() - { - return First; - } + public ZilObject GetFirst() => First; - public IStructure GetRest(int skip) + public IStructure? GetRest(int skip) { - switch (skip) + return skip switch { - case 0: - return this; - - case 1: - return new ZilVector(Second); - - default: - return null; - } + 0 => (IStructure)this, + 1 => new ZilVector(Second), + _ => null, + }; } /// Always thrown. - public IStructure GetBack(int skip) - { - throw new NotSupportedException(); - } + public IStructure? GetBack(int skip) => throw new NotSupportedException(); /// Always thrown. - public IStructure GetTop() - { - throw new NotSupportedException(); - } + public IStructure GetTop() => throw new NotSupportedException(); /// Always thrown. public void Grow(int end, int beginning, ZilObject defaultValue) @@ -147,22 +122,16 @@ namespace Zilf.Interpreter.Values public bool IsEmpty => false; /// is out of range. - [CanBeNull] public ZilObject this[int index] { get { - switch (index) + return index switch { - case 0: - return First; - - case 1: - return Second; - - default: - return null; - } + 0 => First, + 1 => Second, + _ => null! + }; } set { @@ -184,15 +153,9 @@ namespace Zilf.Interpreter.Values } } - public int GetLength() - { - return 2; - } + public int GetLength() => 2; - public int? GetLength(int limit) - { - return 2 <= limit ? 2 : (int?)null; - } + public int? GetLength(int limit) => 2 <= limit ? 2 : (int?)null; #endregion @@ -202,9 +165,6 @@ namespace Zilf.Interpreter.Values yield return Second; } - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } } \ No newline at end of file diff --git a/src/Zilf/Interpreter/Values/ZilAsoc.cs b/src/Zilf/Interpreter/Values/ZilAsoc.cs index 454cf90..343bab4 100644 --- a/src/Zilf/Interpreter/Values/ZilAsoc.cs +++ b/src/Zilf/Interpreter/Values/ZilAsoc.cs @@ -16,6 +16,7 @@ * along with ZILF. If not, see . */ +using System.Diagnostics.CodeAnalysis; using Zilf.Language; using Zilf.Diagnostics; using Zilf.Interpreter.Values.Tied; @@ -36,7 +37,7 @@ namespace Zilf.Interpreter.Values readonly AsocResult[] results; readonly int index; - public ZilAsoc([NotNull] AsocResult[] results, int index) + public ZilAsoc(AsocResult[] results, int index) { this.results = results; this.index = index; @@ -44,7 +45,10 @@ namespace Zilf.Interpreter.Values /// Always thrown. [ChtypeMethod] - public static ZilAsoc FromList([NotNull] Context ctx, [NotNull] ZilListBase list) => + [DoesNotReturn] + [SuppressMessage("Style", "IDE0060:Remove unused parameter")] + [SuppressMessage("Performance", "CA1801:Unused parameter")] + public static ZilAsoc FromList(Context ctx, ZilListBase list) => throw new InterpreterError(InterpreterMessages.CHTYPE_To_0_Not_Supported, "ASOC"); public ZilObject Item => results[index].Item; @@ -59,8 +63,7 @@ namespace Zilf.Interpreter.Values x => x.Value); } - [CanBeNull] - public ZilAsoc GetNext() + public ZilAsoc? GetNext() { return index + 1 < results.Length ? new ZilAsoc(results, index + 1) : null; } diff --git a/src/Zilf/Interpreter/Values/ZilAtom.cs b/src/Zilf/Interpreter/Values/ZilAtom.cs index ff0cb7d..b846878 100644 --- a/src/Zilf/Interpreter/Values/ZilAtom.cs +++ b/src/Zilf/Interpreter/Values/ZilAtom.cs @@ -29,10 +29,9 @@ namespace Zilf.Interpreter.Values [BuiltinType(StdAtom.ATOM, PrimType.ATOM)] class ZilAtom : ZilObject { - [CanBeNull] - ObList list; + ObList? list; - public ZilAtom([NotNull] string text, [CanBeNull] ObList list, StdAtom stdAtom) + public ZilAtom(string text, ObList? list, StdAtom stdAtom) { if (string.IsNullOrEmpty(text)) throw new ArgumentException("Value cannot be null or empty.", nameof(text)); @@ -42,16 +41,13 @@ namespace Zilf.Interpreter.Values StdAtom = stdAtom; } - [NotNull] [ChtypeMethod] // we can't construct a new atom since it wouldn't be equal to the old one - public static ZilAtom FromAtom([NotNull] ZilAtom other) => other; + public static ZilAtom FromAtom(ZilAtom other) => other; - [NotNull] public string Text { get; } - [CanBeNull] - public ObList ObList + public ObList? ObList { get => list; @@ -80,8 +76,7 @@ namespace Zilf.Interpreter.Values /// The parsed atom. /// This method does not strip backslashes from . /// No OBLIST path. - [NotNull] - public static ZilAtom Parse([NotNull] string text, [NotNull] Context ctx) + public static ZilAtom Parse(string text, Context ctx) { ZilAtom result; var idx = text.IndexOf("!-", StringComparison.Ordinal); @@ -93,7 +88,7 @@ namespace Zilf.Interpreter.Values if (!(pathspec is IEnumerable zos)) throw new InterpreterError(InterpreterMessages.No_OBLIST_Path); - ObList insertList = null; + ObList? insertList = null; var gotDefault = false; foreach (var obj in zos) @@ -148,7 +143,7 @@ namespace Zilf.Interpreter.Values return result; } - bool NeedsObListTrailer([ItemNotNull] [NotNull] [InstantHandle] IEnumerable obListPath) + bool NeedsObListTrailer([InstantHandle] IEnumerable obListPath) { // if this atom can be found by looking up its name in the oblist path, no trailer is needed. // thus, the trailer is only needed if (1) looking up that name returns a different atom first @@ -210,7 +205,7 @@ namespace Zilf.Interpreter.Values var oblistAtom = ctx.GetStdAtom(StdAtom.OBLIST); var oblistPath = ctx.GetLocalVal(oblistAtom) as IStructure; - var name = this; + ZilAtom? name = this; var oblist = ObList; if (oblist == null) @@ -245,7 +240,6 @@ namespace Zilf.Interpreter.Values public override PrimType PrimType => PrimType.ATOM; - [NotNull] public override ZilObject GetPrimitive(Context ctx) => this; } } \ No newline at end of file diff --git a/src/Zilf/Interpreter/Values/ZilChannel.cs b/src/Zilf/Interpreter/Values/ZilChannel.cs index 15e132b..2bc77ac 100644 --- a/src/Zilf/Interpreter/Values/ZilChannel.cs +++ b/src/Zilf/Interpreter/Values/ZilChannel.cs @@ -17,6 +17,7 @@ */ using System; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Text; using Zilf.Language; @@ -35,7 +36,10 @@ namespace Zilf.Interpreter.Values { /// Always thrown. [ChtypeMethod] - public static ZilChannel FromVector([NotNull] Context ctx, [NotNull] ZilVector vector) => + [DoesNotReturn] + [SuppressMessage("Style", "IDE0060:Remove unused parameter")] + [SuppressMessage("Performance", "CA1801:Unused parameter")] + public static ZilChannel FromVector(Context ctx, ZilVector vector) => throw new InterpreterError(InterpreterMessages.CHTYPE_To_0_Not_Supported, "CHANNEL"); public override StdAtom StdTypeAtom => StdAtom.CHANNEL; @@ -56,7 +60,7 @@ namespace Zilf.Interpreter.Values { readonly FileAccess fileAccess; readonly string path; - Stream stream; + Stream? stream; public ZilFileChannel(string path, FileAccess fileAccess) { @@ -64,17 +68,12 @@ namespace Zilf.Interpreter.Values this.fileAccess = fileAccess; } - public override string ToString() - { - return $"#CHANNEL [{(fileAccess == FileAccess.Read ? "READ" : "NONE")} {ZilString.Quote(path)}]"; - } + public override string ToString() => + $"#CHANNEL [{(fileAccess == FileAccess.Read ? "READ" : "NONE")} {ZilString.Quote(path)}]"; - [NotNull] - public override ZilObject GetPrimitive([NotNull] Context ctx) - { - return new ZilVector(ctx.GetStdAtom(fileAccess == FileAccess.Read ? StdAtom.READ : StdAtom.NONE), + public override ZilObject GetPrimitive(Context ctx) => + new ZilVector(ctx.GetStdAtom(fileAccess == FileAccess.Read ? StdAtom.READ : StdAtom.NONE), ZilString.FromString(path)); - } public override void Reset(Context ctx) { @@ -84,29 +83,24 @@ namespace Zilf.Interpreter.Values public override void Close() { - if (stream != null) + if (stream == null) + return; + + try + { + stream.Close(); + } + finally { - try - { - stream.Close(); - } - finally - { - stream = null; - } + stream = null; } } public override long? GetFileLength() { - if (stream == null) - { - return null; - } - try { - return stream.Length; + return stream?.Length; } catch (NotSupportedException) { @@ -124,20 +118,11 @@ namespace Zilf.Interpreter.Values return result == -1 ? (char?)null : (char)result; } - public override bool WriteChar(char c) - { - return false; - } + public override bool WriteChar(char c) => false; - public override int WriteNewline() - { - return 0; - } + public override int WriteNewline() => 0; - public override int WriteString(string s) - { - return 0; - } + public override int WriteString(string s) => 0; } [BuiltinAlternate(typeof(ZilChannel))] @@ -152,20 +137,13 @@ namespace Zilf.Interpreter.Values throw new ArgumentException("Only Write mode is supported", nameof(fileAccess)); } - [NotNull] public string String => sb.ToString(); - public override string ToString() - { - return $"#CHANNEL [PRINT STRING {ZilString.Quote(sb.ToString())}]"; - } + public override string ToString() => $"#CHANNEL [PRINT STRING {ZilString.Quote(sb.ToString())}]"; - [NotNull] - public override ZilObject GetPrimitive([NotNull] Context ctx) - { - return new ZilVector(ctx.GetStdAtom(StdAtom.PRINT), ctx.GetStdAtom(StdAtom.STRING), + public override ZilObject GetPrimitive(Context ctx) => + new ZilVector(ctx.GetStdAtom(StdAtom.PRINT), ctx.GetStdAtom(StdAtom.STRING), ZilString.FromString(sb.ToString())); - } public override void Reset(Context ctx) { @@ -177,15 +155,9 @@ namespace Zilf.Interpreter.Values // nada } - public override long? GetFileLength() - { - return null; - } + public override long? GetFileLength() => null; - public override char? ReadChar() - { - return null; - } + public override char? ReadChar() => null; public override bool WriteChar(char c) { @@ -199,7 +171,7 @@ namespace Zilf.Interpreter.Values return 1; } - public override int WriteString([NotNull] string s) + public override int WriteString(string s) { sb.Append(s); return s.Length; @@ -216,16 +188,9 @@ namespace Zilf.Interpreter.Values throw new ArgumentException("Only Write mode is supported", nameof(fileAccess)); } - public override string ToString() - { - return "#CHANNEL [PRINT CONSOLE]"; - } + public override string ToString() => "#CHANNEL [PRINT CONSOLE]"; - [NotNull] - public override ZilObject GetPrimitive([NotNull] Context ctx) - { - return new ZilVector(ctx.GetStdAtom(StdAtom.PRINT), ctx.GetStdAtom(StdAtom.CONSOLE)); - } + public override ZilObject GetPrimitive(Context ctx) => new ZilVector(ctx.GetStdAtom(StdAtom.PRINT), ctx.GetStdAtom(StdAtom.CONSOLE)); public override void Reset(Context ctx) { @@ -237,15 +202,9 @@ namespace Zilf.Interpreter.Values // nada } - public override long? GetFileLength() - { - return null; - } + public override long? GetFileLength() => null; - public override char? ReadChar() - { - return null; - } + public override char? ReadChar() => null; public override bool WriteChar(char c) { @@ -259,7 +218,7 @@ namespace Zilf.Interpreter.Values return Environment.NewLine.Length; } - public override int WriteString([NotNull] string s) + public override int WriteString(string s) { Console.Write(s); return s.Length; diff --git a/src/Zilf/Interpreter/Values/ZilChar.cs b/src/Zilf/Interpreter/Values/ZilChar.cs index 5cf50c4..7ef58c8 100644 --- a/src/Zilf/Interpreter/Values/ZilChar.cs +++ b/src/Zilf/Interpreter/Values/ZilChar.cs @@ -36,13 +36,11 @@ namespace Zilf.Interpreter.Values this.value = value; } - [NotNull] [ChtypeMethod] - public static ZilChar FromFix([NotNull] ZilFix fix) => new ZilChar(fix.Value); + public static ZilChar FromFix(ZilFix fix) => new ZilChar(fix.Value); public char Char => (char)value; - [NotNull] public override string ToString() { return "!\\" + Char; @@ -57,13 +55,9 @@ namespace Zilf.Interpreter.Values public override PrimType PrimType => PrimType.FIX; - [NotNull] public override ZilObject GetPrimitive(Context ctx) => new ZilFix(value); - public override bool ExactlyEquals(ZilObject obj) - { - return obj is ZilChar other && other.value == value; - } + public override bool ExactlyEquals(ZilObject? obj) => obj is ZilChar other && other.value == value; public override int GetHashCode() => value; } diff --git a/src/Zilf/Interpreter/Values/ZilDecl.cs b/src/Zilf/Interpreter/Values/ZilDecl.cs index cdeffba..c0b1316 100644 --- a/src/Zilf/Interpreter/Values/ZilDecl.cs +++ b/src/Zilf/Interpreter/Values/ZilDecl.cs @@ -28,14 +28,13 @@ namespace Zilf.Interpreter.Values [BuiltinType(StdAtom.DECL, PrimType.LIST)] class ZilDecl : ZilListBase { - public ZilDecl([ItemNotNull] [NotNull] IEnumerable sequence) + public ZilDecl(IEnumerable sequence) : base(sequence) { } - [NotNull] [ChtypeMethod] - public static ZilDecl FromList([NotNull] ZilListBase list) => new ZilDecl(list); + public static ZilDecl FromList(ZilListBase list) => new ZilDecl(list); public override StdAtom StdTypeAtom => StdAtom.DECL; @@ -46,7 +45,7 @@ namespace Zilf.Interpreter.Values while (!list.IsEmpty) { - if (!list.StartsWith(out ZilList atoms, out ZilObject decl)) + if (!list.StartsWith(out ZilList? atoms, out ZilObject? decl)) break; if (!atoms.All(a => a is ZilAtom)) @@ -58,8 +57,7 @@ namespace Zilf.Interpreter.Values yield return new KeyValuePair(atom, decl); } - list = list.GetRest(2); - Debug.Assert(list != null); + list = list.GetRest(2)!; } if (!list.IsEmpty) diff --git a/src/Zilf/Interpreter/Values/ZilEnvironment.cs b/src/Zilf/Interpreter/Values/ZilEnvironment.cs index 968592e..75262da 100644 --- a/src/Zilf/Interpreter/Values/ZilEnvironment.cs +++ b/src/Zilf/Interpreter/Values/ZilEnvironment.cs @@ -17,9 +17,9 @@ */ using System; +using System.Diagnostics.CodeAnalysis; using Zilf.Language; using Zilf.Diagnostics; -using JetBrains.Annotations; namespace Zilf.Interpreter.Values { @@ -30,7 +30,11 @@ namespace Zilf.Interpreter.Values readonly WeakReference env; [ChtypeMethod] - public static ZilEnvironment FromAtom([NotNull] Context ctx, [NotNull] ZilAtom atom) => + [DoesNotReturn] + [SuppressMessage("Style", "IDE0060:Remove unused parameter")] + [SuppressMessage("Performance", "CA1801:Unused parameter")] + + public static ZilEnvironment FromAtom(Context ctx, ZilAtom atom) => throw new InterpreterError(InterpreterMessages.CHTYPE_To_0_Not_Supported, "ENVIRONMENT"); public ZilEnvironment(LocalEnvironment env, ZilAtom name) @@ -39,7 +43,7 @@ namespace Zilf.Interpreter.Values this.name = name; } - public override bool ExactlyEquals(ZilObject obj) + public override bool ExactlyEquals(ZilObject? obj) { if (obj is ZilEnvironment other && env.TryGetTarget(out var thisTarget) && @@ -68,7 +72,6 @@ namespace Zilf.Interpreter.Values public override ZilObject GetPrimitive(Context ctx) => name; - [NotNull] public LocalEnvironment LocalEnvironment => env.TryGetTarget(out var result) ? result diff --git a/src/Zilf/Interpreter/Values/ZilEvalMacro.cs b/src/Zilf/Interpreter/Values/ZilEvalMacro.cs index 8e13cd9..cd7ef72 100644 --- a/src/Zilf/Interpreter/Values/ZilEvalMacro.cs +++ b/src/Zilf/Interpreter/Values/ZilEvalMacro.cs @@ -36,8 +36,7 @@ namespace Zilf.Interpreter.Values /// has the wrong number or types of elements. [ChtypeMethod] - [NotNull] - public static ZilEvalMacro FromList([NotNull] Context ctx, [NotNull] ZilListBase list) + public static ZilEvalMacro FromList(Context ctx, ZilListBase list) { if (list.First == null || list.Rest == null || list.Rest.First != null) { @@ -101,11 +100,9 @@ namespace Zilf.Interpreter.Values } /// The contained value is not an applicable type. - public ZilResult Expand([NotNull] Context ctx, [NotNull] ZilObject[] args) + public ZilResult Expand(Context ctx, ZilObject[] args) { - var applicable = WrappedValue.AsApplicable(ctx); - - if (applicable == null) + if (!WrappedValue.IsApplicable(ctx, out var applicable)) throw new InterpreterError(InterpreterMessages.Not_An_Applicable_Type_0, WrappedValue.GetTypeAtom(ctx)); var result = ctx.ExecuteInMacroEnvironment( @@ -115,11 +112,9 @@ namespace Zilf.Interpreter.Values } /// The contained value is not an applicable type. - public ZilResult ExpandNoEval([NotNull] Context ctx, [NotNull] ZilObject[] args) + public ZilResult ExpandNoEval(Context ctx, ZilObject[] args) { - var applicable = WrappedValue.AsApplicable(ctx); - - if (applicable == null) + if (!WrappedValue.IsApplicable(ctx, out var applicable)) throw new InterpreterError(InterpreterMessages.Not_An_Applicable_Type_0, WrappedValue.GetTypeAtom(ctx)); var result = ctx.ExecuteInMacroEnvironment( @@ -128,9 +123,7 @@ namespace Zilf.Interpreter.Values return result.ShouldPass() ? result : MakeSpliceExpandable((ZilObject)result); } - public override bool StructurallyEquals(ZilObject obj) - { - return obj is ZilEvalMacro other && other.WrappedValue.StructurallyEquals(WrappedValue); - } + public override bool StructurallyEquals(ZilObject? obj) => + obj is ZilEvalMacro other && other.WrappedValue.StructurallyEquals(WrappedValue); } } \ No newline at end of file diff --git a/src/Zilf/Interpreter/Values/ZilFSubr.cs b/src/Zilf/Interpreter/Values/ZilFSubr.cs index ca0a3fa..373bd3e 100644 --- a/src/Zilf/Interpreter/Values/ZilFSubr.cs +++ b/src/Zilf/Interpreter/Values/ZilFSubr.cs @@ -25,18 +25,16 @@ namespace Zilf.Interpreter.Values [BuiltinType(StdAtom.FSUBR, PrimType.STRING)] sealed class ZilFSubr : ZilSubr { - public ZilFSubr([NotNull] string name, [NotNull] SubrDelegate handler) + public ZilFSubr(string name, SubrDelegate handler) : base(name, handler) { } [ChtypeMethod] - [NotNull] - public new static ZilFSubr FromString([NotNull] Context ctx, [NotNull] ZilString str) => + public new static ZilFSubr FromString(Context ctx, ZilString str) => FromString(ctx, str.ToStringContext(ctx, true)); - [NotNull] - public new static ZilFSubr FromString([NotNull] Context ctx, [NotNull] string name) + public new static ZilFSubr FromString(Context ctx, string name) { var del = ctx.GetSubrDelegate(name); if (del != null) @@ -46,7 +44,6 @@ namespace Zilf.Interpreter.Values throw new InterpreterError(InterpreterMessages.Unrecognized_0_1, "FSUBR name", name); } - [NotNull] public override string ToString() => $"#FSUBR \"{name}\""; public override StdAtom StdTypeAtom => StdAtom.FSUBR; diff --git a/src/Zilf/Interpreter/Values/ZilFalse.cs b/src/Zilf/Interpreter/Values/ZilFalse.cs index 739724c..dc95918 100644 --- a/src/Zilf/Interpreter/Values/ZilFalse.cs +++ b/src/Zilf/Interpreter/Values/ZilFalse.cs @@ -25,7 +25,7 @@ namespace Zilf.Interpreter.Values sealed class ZilFalse : ZilListBase { [ChtypeMethod] - public ZilFalse([NotNull] ZilListBase value) + public ZilFalse(ZilListBase value) : base(value) { } public override StdAtom StdTypeAtom => StdAtom.FALSE; diff --git a/src/Zilf/Interpreter/Values/ZilFix.cs b/src/Zilf/Interpreter/Values/ZilFix.cs index 7f6df67..9da7c29 100644 --- a/src/Zilf/Interpreter/Values/ZilFix.cs +++ b/src/Zilf/Interpreter/Values/ZilFix.cs @@ -37,7 +37,7 @@ namespace Zilf.Interpreter.Values } [ChtypeMethod] - public ZilFix([NotNull] ZilFix other) + public ZilFix(ZilFix other) : this(other.value) { } @@ -50,13 +50,9 @@ namespace Zilf.Interpreter.Values public override PrimType PrimType => PrimType.FIX; - [NotNull] public override ZilObject GetPrimitive(Context ctx) => this; - public override bool ExactlyEquals(ZilObject obj) - { - return obj is ZilFix other && other.value == value; - } + public override bool ExactlyEquals(ZilObject? obj) => obj is ZilFix other && other.value == value; public override int GetHashCode() => value.GetHashCode(); @@ -65,8 +61,8 @@ namespace Zilf.Interpreter.Values [SuppressMessage("ReSharper", "ConvertIfStatementToReturnStatement")] public ZilResult Apply(Context ctx, ZilObject[] args) { - if (EvalSequence(ctx, args).TryToZilObjectArray(out args, out var zr)) - return ApplyNoEval(ctx, args); + if (EvalSequence(ctx, args).TryToZilObjectArray(out var evaluatedArgs, out var zr)) + return ApplyNoEval(ctx, evaluatedArgs); return zr; } diff --git a/src/Zilf/Interpreter/Values/ZilForm.cs b/src/Zilf/Interpreter/Values/ZilForm.cs index 094b970..2b853d9 100644 --- a/src/Zilf/Interpreter/Values/ZilForm.cs +++ b/src/Zilf/Interpreter/Values/ZilForm.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Zilf.Diagnostics; using Zilf.Language; @@ -29,7 +30,7 @@ namespace Zilf.Interpreter.Values [BuiltinType(StdAtom.FORM, PrimType.LIST)] sealed class ZilForm : ZilListBase { - public ZilForm([NotNull] IEnumerable sequence) + public ZilForm(IEnumerable sequence) : base(sequence) { } @@ -37,23 +38,21 @@ namespace Zilf.Interpreter.Values public ZilForm(ZilObject first, ZilListoidBase rest) : base(first, rest) { } - [NotNull] - public override ISourceLine SourceLine + [System.Diagnostics.CodeAnalysis.NotNull] + public override ISourceLine? SourceLine { get => base.SourceLine ?? SourceLines.Unknown; set => base.SourceLine = value; } - [NotNull] [ChtypeMethod] - public static ZilForm FromList([NotNull] ZilListBase list) => new ZilForm(list.First, list.Rest); + public static ZilForm FromList(ZilListBase list) => new ZilForm(list.First!, list.Rest!); protected override string OpenBracket => "<"; protected override string CloseBracket => ">"; - [NotNull] - string ToString([NotNull] Func convert) + string ToString(Func convert) { if (Recursion.TryLock(this)) { @@ -64,7 +63,7 @@ namespace Zilf.Interpreter.Values { Debug.Assert(Rest != null); - var arg = Rest.First; + var arg = Rest.First!; switch (firstAtom.StdAtom) { @@ -92,18 +91,18 @@ namespace Zilf.Interpreter.Values public override string ToString() { - return ToString(zo => zo?.ToString()); + return ToString(zo => zo.ToString()); } protected override string ToStringContextImpl(Context ctx, bool friendly) { - return ToString(zo => zo?.ToStringContext(ctx, friendly)); + return ToString(zo => zo.ToStringContext(ctx, friendly)); } public override StdAtom StdTypeAtom => StdAtom.FORM; /// The form's first element is an atom that has no local or global value, or a non-applicable type. - protected override ZilResult EvalImpl(Context ctx, LocalEnvironment environment, ZilAtom originalType) + protected override ZilResult EvalImpl(Context ctx, LocalEnvironment? environment, ZilAtom? originalType) { if (environment != null) { @@ -118,16 +117,18 @@ namespace Zilf.Interpreter.Values Debug.Assert(Rest != null); - using (var frame = ctx.PushFrame(this)) + using var frame = ctx.PushFrame(this); + using (DiagnosticContext.Push(SourceLine, frame)) { ZilObject target; if (First is ZilAtom fa) { - target = ctx.GetGlobalVal(fa) ?? ctx.GetLocalVal(fa); - if (target == null) - throw new InterpreterError(this, InterpreterMessages.Calling_Unassigned_Atom_0, - fa.ToStringContext(ctx, false)); + target = ctx.GetGlobalVal(fa) ?? + ctx.GetLocalVal(fa) ?? + throw new InterpreterError(this, + InterpreterMessages.Calling_Unassigned_Atom_0, + fa.ToStringContext(ctx, false)); } else { @@ -138,8 +139,7 @@ namespace Zilf.Interpreter.Values target = (ZilObject)result; } - var applicable = target.AsApplicable(ctx); - if (applicable != null) + if (target.IsApplicable(ctx, out var applicable)) { return applicable.Apply(ctx, Rest.ToArray()); } @@ -154,7 +154,7 @@ namespace Zilf.Interpreter.Values if (First == null || Rest == null) return this; - ZilObject target; + ZilObject? target; bool usedGlobal, usedLocal; switch (First) { @@ -200,7 +200,7 @@ namespace Zilf.Interpreter.Values : usedLocal ? ctx.ChangeType(First, ctx.GetStdAtom(StdAtom.LVAL)) : First; - if (this.Matches(out ZilObject _, out ZilObject structure, out ZilObject item)) + if (this.Matches(out ZilObject _, out ZilObject? structure, out ZilObject? item)) { // <1 FOO BAR> => First = ctx.GetStdAtom(StdAtom.PUT); @@ -219,14 +219,11 @@ namespace Zilf.Interpreter.Values return this; } - [NotNull] - static ZilForm DeepRewriteSourceInfo([NotNull] ZilForm other, [NotNull] ISourceLine src) - { - return new ZilForm(DeepRewriteSourceInfoContents(other, src)) { SourceLine = src }; - } + static ZilForm DeepRewriteSourceInfo(ZilForm other, ISourceLine? src) => + new ZilForm(DeepRewriteSourceInfoContents(other, src)) { SourceLine = src }; static IEnumerable DeepRewriteSourceInfoContents( - [ItemNotNull] [NotNull] IEnumerable contents, [NotNull] ISourceLine src) + IEnumerable contents, ISourceLine? src) { foreach (var item in contents) { @@ -242,12 +239,12 @@ namespace Zilf.Interpreter.Values } [ContractAnnotation("=> true, atom: notnull; => false, atom: null")] - public override bool IsLVAL(out ZilAtom atom) => IsTwoElementFormWithStdAtom(StdAtom.LVAL, out atom); + public override bool IsLVAL([NotNullWhen(true)] out ZilAtom? atom) => IsTwoElementFormWithStdAtom(StdAtom.LVAL, out atom); [ContractAnnotation("=> true, atom: notnull; => false, atom: null")] - public override bool IsGVAL(out ZilAtom atom) => IsTwoElementFormWithStdAtom(StdAtom.GVAL, out atom); + public override bool IsGVAL([NotNullWhen(true)] out ZilAtom? atom) => IsTwoElementFormWithStdAtom(StdAtom.GVAL, out atom); - bool IsTwoElementFormWithStdAtom(StdAtom stdAtom, [CanBeNull] out ZilAtom atom) + bool IsTwoElementFormWithStdAtom(StdAtom stdAtom, out ZilAtom? atom) { if (First is ZilAtom head && head.StdAtom == stdAtom) @@ -265,13 +262,16 @@ namespace Zilf.Interpreter.Values return false; } - public override bool ExactlyEquals(ZilObject other) + public override bool ExactlyEquals(ZilObject? other) { if (ReferenceEquals(this, other)) return true; - return (IsLVAL(out var myAtom) && other.IsLVAL(out var theirAtom) || - IsGVAL(out myAtom) && other.IsGVAL(out theirAtom)) && + if (other == null) + return false; + + return ((IsLVAL(out var myAtom) && other.IsLVAL(out var theirAtom)) || + (IsGVAL(out myAtom) && other.IsGVAL(out theirAtom))) && myAtom == theirAtom; } diff --git a/src/Zilf/Interpreter/Values/ZilFunction.cs b/src/Zilf/Interpreter/Values/ZilFunction.cs index beb6c8c..1c133f0 100644 --- a/src/Zilf/Interpreter/Values/ZilFunction.cs +++ b/src/Zilf/Interpreter/Values/ZilFunction.cs @@ -29,33 +29,30 @@ namespace Zilf.Interpreter.Values [BuiltinType(StdAtom.FUNCTION, PrimType.LIST)] class ZilFunction : ZilTiedListBase, IApplicable { - [NotNull] readonly ArgSpec argspec; - [NotNull] readonly ZilObject[] body; /// is invalid. - public ZilFunction([CanBeNull] ZilAtom name, [CanBeNull] ZilAtom activationAtom, - [NotNull] [ItemNotNull] IEnumerable argspec, ZilDecl decl, - [ItemNotNull] [NotNull] IEnumerable body) + public ZilFunction(ZilAtom? name, ZilAtom? activationAtom, + IEnumerable argspec, ZilDecl decl, + IEnumerable body) : this("", name, activationAtom, argspec, decl, body) { } // TODO: convert to static method; caller parameter doesn't belong here /// is invalid. - public ZilFunction([NotNull] string caller, [CanBeNull] ZilAtom name, [CanBeNull] ZilAtom activationAtom, - [NotNull] [ItemNotNull] IEnumerable argspec, ZilDecl decl, - [ItemNotNull] [NotNull] IEnumerable body) + public ZilFunction(string caller, ZilAtom? name, ZilAtom? activationAtom, + IEnumerable argspec, ZilDecl? decl, + IEnumerable body) { this.argspec = ArgSpec.Parse(caller, name, activationAtom, argspec, decl); this.body = body.ToArray(); } [ChtypeMethod] - [NotNull] - public static ZilFunction FromList([NotNull] Context ctx, [NotNull] ZilListBase list) + public static ZilFunction FromList(Context ctx, ZilListBase list) { var functionSubr = ctx.GetSubrDelegate("FUNCTION"); Debug.Assert(functionSubr != null); @@ -68,10 +65,8 @@ namespace Zilf.Interpreter.Values .WithCatchAll(x => x.BodyAsList); } - [NotNull] public ZilList ArgSpecAsList => argspec.ToZilList(); - [NotNull] public ZilList BodyAsList => new ZilList(body); public override StdAtom StdTypeAtom => StdAtom.FUNCTION; @@ -80,35 +75,38 @@ namespace Zilf.Interpreter.Values public ZilResult ApplyNoEval(Context ctx, ZilObject[] args) => ApplyImpl(ctx, args, false); - ZilResult ApplyImpl([NotNull] Context ctx, [ItemNotNull] [NotNull] ZilObject[] args, bool eval) + ZilResult ApplyImpl(Context ctx, ZilObject[] args, bool eval) { - using (var application = argspec.BeginApply(ctx, args, eval)) + using var application = argspec.BeginApply(ctx, args, eval); + + if (application.EarlyResult != null) + return application.EarlyResult.Value; + + var activation = application.Activation; + do { - if (application.EarlyResult != null) - return application.EarlyResult.Value; + var result = EvalProgram(ctx, body); + + if (activation == null) + return result; - var activation = application.Activation; - do + if (result.IsReturn(activation, out var value)) { - var result = EvalProgram(ctx, body); - if (result.IsReturn(activation, out var value)) - { - argspec.ValidateResult(ctx, value); - return value; - } - - if (result.IsAgain(activation)) - { - // repeat - continue; - } + argspec.ValidateResult(ctx, value); + return value; + } - return result; - } while (true); - } + if (result.IsAgain(activation)) + { + // repeat + continue; + } + + return result; + } while (true); } - public override bool StructurallyEquals(ZilObject obj) + public override bool StructurallyEquals(ZilObject? obj) { if (!(obj is ZilFunction other)) return false; diff --git a/src/Zilf/Interpreter/Values/ZilHashBase.cs b/src/Zilf/Interpreter/Values/ZilHashBase.cs index b0ba240..c1a2fdb 100644 --- a/src/Zilf/Interpreter/Values/ZilHashBase.cs +++ b/src/Zilf/Interpreter/Values/ZilHashBase.cs @@ -37,17 +37,13 @@ namespace Zilf.Interpreter.Values public sealed override int GetHashCode() => type.GetHashCode() ^ primValue.GetHashCode(); - public sealed override bool ExactlyEquals(ZilObject other) - { - return other is ZilHashBase hash && hash.type == type && - ((ZilObject)(object)hash.primValue).ExactlyEquals((ZilObject)(object)primValue); - } + public sealed override bool ExactlyEquals(ZilObject? other) => + other is ZilHashBase hash && hash.type == type && + ((ZilObject)(object)hash.primValue).ExactlyEquals((ZilObject)(object)primValue); - public sealed override bool StructurallyEquals(ZilObject other) - { - return other is ZilHashBase hash && hash.type == type && - ((ZilObject)(object)hash.primValue).StructurallyEquals((ZilObject)(object)primValue); - } + public sealed override bool StructurallyEquals(ZilObject? other) => + other is ZilHashBase hash && hash.type == type && + ((ZilObject)(object)hash.primValue).StructurallyEquals((ZilObject)(object)primValue); public ZilAtom Type => type; diff --git a/src/Zilf/Interpreter/Values/ZilLink.cs b/src/Zilf/Interpreter/Values/ZilLink.cs index 490a140..7f6f7d7 100644 --- a/src/Zilf/Interpreter/Values/ZilLink.cs +++ b/src/Zilf/Interpreter/Values/ZilLink.cs @@ -16,6 +16,7 @@ * along with ZILF. If not, see . */ +using System.Diagnostics.CodeAnalysis; using JetBrains.Annotations; using Zilf.Language; using Zilf.Diagnostics; @@ -25,7 +26,7 @@ namespace Zilf.Interpreter.Values [BuiltinType(StdAtom.LINK, PrimType.ATOM)] sealed class ZilLink : ZilAtom { - public ZilLink([NotNull] string pname, ObList list) + public ZilLink(string pname, ObList list) : base(pname, list, StdAtom.None) { } @@ -33,9 +34,15 @@ namespace Zilf.Interpreter.Values public override StdAtom StdTypeAtom => StdAtom.LINK; [ChtypeMethod] + [DoesNotReturn] + [SuppressMessage("Style", "IDE0060:Remove unused parameter")] + [SuppressMessage("Performance", "CA1801:Unused parameter")] public new static ZilLink FromAtom(ZilAtom atom) => throw new InterpreterError(InterpreterMessages.CHTYPE_To_0_Not_Supported, "LINK"); + [DoesNotReturn] + [SuppressMessage("Style", "IDE0060:Remove unused parameter")] + [SuppressMessage("Performance", "CA1801:Unused parameter")] public override ZilObject GetPrimitive(Context ctx) => throw new InterpreterError(InterpreterMessages.CHTYPE_Away_From_0_Not_Supported, "LINK"); } diff --git a/src/Zilf/Interpreter/Values/ZilList.cs b/src/Zilf/Interpreter/Values/ZilList.cs index 28ec027..5031eb1 100644 --- a/src/Zilf/Interpreter/Values/ZilList.cs +++ b/src/Zilf/Interpreter/Values/ZilList.cs @@ -17,31 +17,30 @@ */ using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using Zilf.Language; -using JetBrains.Annotations; namespace Zilf.Interpreter.Values { [BuiltinType(StdAtom.LIST, PrimType.LIST)] sealed class ZilList : ZilListBase { - public ZilList([NotNull] IEnumerable sequence) + public ZilList(IEnumerable sequence) : base(sequence) { } - public ZilList(ZilObject first, ZilListoidBase rest) + public ZilList([NotNullIfNotNull("rest")] ZilObject? first, [NotNullIfNotNull("first")] ZilListoidBase? rest) : base(first, rest) { } - [NotNull] [ChtypeMethod] - public static ZilList FromList([NotNull] ZilListBase list) => new ZilList(list.First, list.Rest); + public static ZilList FromList(ZilListBase list) => new ZilList(list.First, list.Rest); public override StdAtom StdTypeAtom => StdAtom.LIST; protected override string OpenBracket => "("; - protected override ZilResult EvalImpl(Context ctx, LocalEnvironment environment, ZilAtom originalType) + protected override ZilResult EvalImpl(Context ctx, LocalEnvironment? environment, ZilAtom? originalType) { var result = EvalSequence(ctx, this, environment).ToZilListResult(SourceLine); if (result.ShouldPass()) diff --git a/src/Zilf/Interpreter/Values/ZilListBase.cs b/src/Zilf/Interpreter/Values/ZilListBase.cs index 6fb1db9..983729c 100644 --- a/src/Zilf/Interpreter/Values/ZilListBase.cs +++ b/src/Zilf/Interpreter/Values/ZilListBase.cs @@ -20,17 +20,16 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using JetBrains.Annotations; namespace Zilf.Interpreter.Values { [BuiltinPrimType(PrimType.LIST)] abstract class ZilListBase : ZilListoidBase { - ZilObject first; - ZilListoidBase rest; + ZilObject? first; + ZilListoidBase? rest; - public sealed override ZilObject First + public sealed override ZilObject? First { get => first; @@ -46,7 +45,7 @@ namespace Zilf.Interpreter.Values } } - public sealed override ZilListoidBase Rest + public sealed override ZilListoidBase? Rest { get => rest; @@ -62,24 +61,23 @@ namespace Zilf.Interpreter.Values } } - protected ZilListBase([NotNull] IEnumerable sequence) + protected ZilListBase(IEnumerable sequence) { - using (var tor = sequence.GetEnumerator()) + using var tor = sequence.GetEnumerator(); + + if (tor.MoveNext()) { - if (tor.MoveNext()) - { - first = tor.Current; - rest = MakeRest(tor); - } - else - { - first = null; - rest = null; - } + first = tor.Current; + rest = MakeRest(tor); + } + else + { + first = null; + rest = null; } } - protected ZilListBase([CanBeNull] ZilObject first, [CanBeNull] ZilListoidBase rest) + protected ZilListBase(ZilObject? first, ZilListoidBase? rest) { Debug.Assert((first == null) == (rest == null)); @@ -87,28 +85,22 @@ namespace Zilf.Interpreter.Values this.rest = rest; } - [NotNull] - protected static ZilList MakeRest([NotNull] IEnumerator tor) + protected static ZilList MakeRest(IEnumerator tor) { - if (tor.MoveNext()) - { - var cur = tor.Current; - var newRest = MakeRest(tor); - return new ZilList(cur, newRest); - } + if (!tor.MoveNext()) + return new ZilList(null, null); - return new ZilList(null, null); + var cur = tor.Current; + var newRest = MakeRest(tor); + return new ZilList(cur, newRest); } public sealed override bool IsEmpty => First == null; - [NotNull] protected virtual string OpenBracket => $"#{StdTypeAtom} ("; - [NotNull] protected virtual string CloseBracket => ")"; - [NotNull] public override string ToString() { if (Recursion.TryLock(this)) @@ -141,41 +133,29 @@ namespace Zilf.Interpreter.Values return OpenBracket + "..." + CloseBracket; } - [NotNull] - public sealed override ZilObject GetPrimitive(Context ctx) - { - return GetType() == typeof(ZilList) ? this : new ZilList(First, Rest); - } + public sealed override ZilObject GetPrimitive(Context ctx) => + GetType() == typeof(ZilList) ? this : new ZilList(First, Rest); - protected override ZilResult EvalImpl(Context ctx, LocalEnvironment environment, ZilAtom originalType) - { - return originalType != null ? ctx.ChangeType(this, originalType) : this; - } + protected override ZilResult EvalImpl(Context ctx, LocalEnvironment? environment, ZilAtom? originalType) => + originalType != null ? ctx.ChangeType(this, originalType) : this; public sealed override IEnumerator GetEnumerator() { - ZilListoidBase r = this; + ZilListoidBase? r = this; - while (r.First != null) + while (r.IsCons(out var f, out r)) { - yield return r.First; - r = r.Rest; - Debug.Assert(r != null); + yield return f; } } - public override bool ExactlyEquals(ZilObject obj) - { - return ReferenceEquals(obj, this) || - obj is ZilListBase other && other.StdTypeAtom == StdTypeAtom && IsEmpty && other.IsEmpty; - } + public override bool ExactlyEquals(ZilObject? obj) => + ReferenceEquals(obj, this) || + (obj is ZilListBase other && other.StdTypeAtom == StdTypeAtom && IsEmpty && other.IsEmpty); - public override int GetHashCode() - { - return IsEmpty ? StdTypeAtom.GetHashCode() : base.GetHashCode(); - } + public override int GetHashCode() => IsEmpty ? StdTypeAtom.GetHashCode() : base.GetHashCode(); - public sealed override bool StructurallyEquals(ZilObject obj) + public sealed override bool StructurallyEquals(ZilObject? obj) { if (ReferenceEquals(obj, this)) return true; @@ -185,6 +165,7 @@ namespace Zilf.Interpreter.Values if (First == null) return other.First == null; + if (!First.StructurallyEquals(other.First)) return false; @@ -194,9 +175,9 @@ namespace Zilf.Interpreter.Values return Rest.StructurallyEquals(other.Rest); } - public sealed override ZilListoidBase GetRest(int skip) + public sealed override ZilListoidBase? GetRest(int skip) { - ZilListoidBase result = this; + ZilListoidBase? result = this; while (skip-- > 0 && result != null) result = result.Rest; return result; @@ -207,11 +188,12 @@ namespace Zilf.Interpreter.Values get { var rested = GetRest(index); - return rested?.GetFirst(); + return rested?.GetFirst()!; } + set { - if (GetRest(index) is ZilListoidBase rested && !rested.IsEmpty) + if (GetRest(index) is { } rested && !rested.IsEmpty) { rested.First = value; } @@ -226,19 +208,18 @@ namespace Zilf.Interpreter.Values public sealed override int? GetLength(int limit) { - using (var tor = GetEnumerator()) - { - int count = 0; + using var tor = GetEnumerator(); - while (tor.MoveNext()) - { - count++; - if (count > limit) - return null; - } + int count = 0; - return count; + while (tor.MoveNext()) + { + count++; + if (count > limit) + return null; } + + return count; } } } \ No newline at end of file diff --git a/src/Zilf/Interpreter/Values/ZilListoidBase.cs b/src/Zilf/Interpreter/Values/ZilListoidBase.cs index a217270..bde5592 100644 --- a/src/Zilf/Interpreter/Values/ZilListoidBase.cs +++ b/src/Zilf/Interpreter/Values/ZilListoidBase.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using JetBrains.Annotations; namespace Zilf.Interpreter.Values @@ -26,12 +27,13 @@ namespace Zilf.Interpreter.Values [BuiltinPrimType(PrimType.LIST)] abstract class ZilListoidBase : ZilObject, IStructure { - [CanBeNull] - public abstract ZilObject First { get; set; } - [CanBeNull] - public abstract ZilListoidBase Rest { get; set; } + [NotNullIfNotNull(nameof(Rest)), DisallowNull] + public abstract ZilObject? First { get; set; } - public void Deconstruct([NotNull] out ZilObject first, [NotNull] out ZilListoidBase rest) + [NotNullIfNotNull(nameof(First)), DisallowNull] + public abstract ZilListoidBase? Rest { get; set; } + + public void Deconstruct(out ZilObject first, out ZilListoidBase rest) { if (IsEmpty) throw new InvalidOperationException("Cannot deconstruct an empty list"); @@ -46,7 +48,7 @@ namespace Zilf.Interpreter.Values [ContractAnnotation("=> true, first: notnull, rest: notnull")] [ContractAnnotation("=> false, first: null, rest: null")] - public bool IsCons([CanBeNull] out ZilObject first, [CanBeNull] out ZilListoidBase rest) + public bool IsCons([NotNullWhen(true)] out ZilObject? first, [NotNullWhen(true)] out ZilListoidBase? rest) { (first, rest) = (this.First, this.Rest); Debug.Assert(first == null && rest == null || first != null && rest != null); @@ -61,16 +63,15 @@ namespace Zilf.Interpreter.Values System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); - public ZilObject GetFirst() => First; - IStructure IStructure.GetRest(int skip) => GetRest(skip); - [CanBeNull] - public abstract ZilListoidBase GetRest(int skip); - public IStructure GetBack(int skip) => throw new NotSupportedException(); + public ZilObject? GetFirst() => First; + IStructure? IStructure.GetRest(int skip) => GetRest(skip); + public abstract ZilListoidBase? GetRest(int skip); + public IStructure? GetBack(int skip) => throw new NotSupportedException(); public IStructure GetTop() => throw new NotSupportedException(); public void Grow(int end, int beginning, ZilObject defaultValue) => throw new NotSupportedException(); - [CanBeNull] + [MaybeNull] public abstract ZilObject this[int index] { get; set; } public abstract int GetLength(); public abstract int? GetLength(int limit); @@ -79,14 +80,13 @@ namespace Zilf.Interpreter.Values /// Enumerates the items of the list, yielding a final instead of repeating if the list is recursive. /// /// - [ItemCanBeNull] [System.Diagnostics.Contracts.Pure] - public IEnumerable EnumerateNonRecursive() + public IEnumerable EnumerateNonRecursive() { var seen = new HashSet(ReferenceEqualityComparer.Instance); var list = this; - while (!list.IsEmpty) + while (list.IsCons(out var first, out var rest)) { if (seen.Contains(list)) { @@ -95,13 +95,11 @@ namespace Zilf.Interpreter.Values } seen.Add(list); - yield return list.First; - list = list.Rest; - Debug.Assert(list != null); + yield return first; + list = rest; } } - [NotNull] public ZilList AsZilList() { if (this is ZilList list) diff --git a/src/Zilf/Interpreter/Values/ZilMacroResult.cs b/src/Zilf/Interpreter/Values/ZilMacroResult.cs index 2762678..74ccf1c 100644 --- a/src/Zilf/Interpreter/Values/ZilMacroResult.cs +++ b/src/Zilf/Interpreter/Values/ZilMacroResult.cs @@ -17,16 +17,23 @@ */ using System; -using JetBrains.Annotations; using Zilf.Compiler; using Zilf.Language; namespace Zilf.Interpreter.Values { - class WrappedMacroResultException : Exception + public sealed class WrappedMacroResultException : Exception { public WrappedMacroResultException() - : base("Macro result was not unwrapped before usage") + : this("Macro result was not unwrapped before usage") + { + } + + public WrappedMacroResultException(string message) : base(message) + { + } + + public WrappedMacroResultException(string message, Exception innerException) : base(message, innerException) { } } @@ -56,22 +63,22 @@ namespace Zilf.Interpreter.Values [BuiltinMeta] sealed class ZilMacroResult : ZilObject { - public ZilMacroResult([NotNull] ZilObject inner) + public ZilMacroResult(ZilObject inner) { this.Inner = inner; } public ZilObject Inner { get; } - public override ISourceLine SourceLine + public override ISourceLine? SourceLine { get => Inner.SourceLine; set => Inner.SourceLine = value; } - public override bool ExactlyEquals(ZilObject other) => throw new WrappedMacroResultException(); + public override bool ExactlyEquals(ZilObject? other) => throw new WrappedMacroResultException(); public override int GetHashCode() => throw new WrappedMacroResultException(); - public override bool StructurallyEquals(ZilObject other) => throw new WrappedMacroResultException(); + public override bool StructurallyEquals(ZilObject? other) => throw new WrappedMacroResultException(); public override string ToString() => throw new WrappedMacroResultException(); protected override string ToStringContextImpl(Context ctx, bool friendly) => @@ -82,13 +89,13 @@ namespace Zilf.Interpreter.Values public override PrimType PrimType => throw new WrappedMacroResultException(); public override ZilObject GetPrimitive(Context ctx) => throw new WrappedMacroResultException(); - protected override ZilResult EvalImpl(Context ctx, LocalEnvironment environment, ZilAtom originalType) => + protected override ZilResult EvalImpl(Context ctx, LocalEnvironment? environment, ZilAtom? originalType) => throw new WrappedMacroResultException(); public override ZilResult Expand(Context ctx) => this; public override bool IsTrue => throw new WrappedMacroResultException(); - public override bool IsLVAL(out ZilAtom atom) => throw new WrappedMacroResultException(); - public override bool IsGVAL(out ZilAtom atom) => throw new WrappedMacroResultException(); + public override bool IsLVAL(out ZilAtom? atom) => throw new WrappedMacroResultException(); + public override bool IsGVAL(out ZilAtom? atom) => throw new WrappedMacroResultException(); } } diff --git a/src/Zilf/Interpreter/Values/ZilObject.cs b/src/Zilf/Interpreter/Values/ZilObject.cs index f3e72e5..1750f1a 100644 --- a/src/Zilf/Interpreter/Values/ZilObject.cs +++ b/src/Zilf/Interpreter/Values/ZilObject.cs @@ -32,10 +32,9 @@ namespace Zilf.Interpreter.Values /// /// Gets or sets a value indicating the object's source code location. /// - public virtual ISourceLine SourceLine { get; set; } + public virtual ISourceLine? SourceLine { get; set; } - [NotNull] - public static IEnumerable ExpandTemplateToken([NotNull] ZilObject selector, [CanBeNull, ItemNotNull] ZilObject[] templateParams) + public static IEnumerable ExpandTemplateToken(ZilObject selector, ZilObject[]? templateParams) { if (templateParams == null) throw new InterpreterError(InterpreterMessages.Templates_Cannot_Be_Used_Here); @@ -73,7 +72,7 @@ namespace Zilf.Interpreter.Values /// PRIMTYPE LIST, they may also both be empty. /// /// - public virtual bool ExactlyEquals(ZilObject other) + public virtual bool ExactlyEquals([NotNullWhen(true)] ZilObject? other) { return ReferenceEquals(this, other); } @@ -90,7 +89,7 @@ namespace Zilf.Interpreter.Values /// =? to the corresponding element in the other. /// /// - public virtual bool StructurallyEquals([CanBeNull] ZilObject other) + public virtual bool StructurallyEquals([NotNullWhen(true)] ZilObject? other) { return Equals(other); } @@ -101,7 +100,7 @@ namespace Zilf.Interpreter.Values /// The other object. /// if is a and is ==? to this object; /// otherwise . - public sealed override bool Equals(object obj) + public sealed override bool Equals([NotNullWhen(true)] object? obj) { return obj is ZilObject other && ExactlyEquals(other); } @@ -113,7 +112,7 @@ namespace Zilf.Interpreter.Values /// The second object to compare. /// if the objects are identical; otherwise . /// This silences a ReSharper warning that shouldn't be suppressed completely. - public static bool operator ==([CanBeNull] ZilObject left, [CanBeNull] ZilObject right) + public static bool operator ==(ZilObject? left, ZilObject? right) { return ReferenceEquals(left, right); } @@ -125,7 +124,7 @@ namespace Zilf.Interpreter.Values /// The second object to compare. /// if the objects are identical; otherwise . /// This silences a ReSharper warning that shouldn't be suppressed completely. - public static bool operator !=([CanBeNull] ZilObject left, [CanBeNull] ZilObject right) + public static bool operator !=(ZilObject? left, ZilObject? right) { return !ReferenceEquals(left, right); } @@ -156,8 +155,7 @@ namespace Zilf.Interpreter.Values /// and use the built-in formatting. /// A string representation of the object. /// If a PRINTTYPE is used, has no effect. - [NotNull] - public string ToStringContext([NotNull] Context ctx, bool friendly, bool ignorePrintType = false) + public string ToStringContext(Context ctx, bool friendly, bool ignorePrintType = false) { if (!ignorePrintType) { @@ -179,8 +177,7 @@ namespace Zilf.Interpreter.Values /// A string representation of the object. /// This method is not affected by PRINTTYPE, which is handled /// by . - [NotNull] - protected virtual string ToStringContextImpl([NotNull] Context ctx, bool friendly) + protected virtual string ToStringContextImpl(Context ctx, bool friendly) { return ToString(); } @@ -190,9 +187,8 @@ namespace Zilf.Interpreter.Values /// /// The current context. /// The type atom. - [NotNull] [System.Diagnostics.Contracts.Pure] - public virtual ZilAtom GetTypeAtom([NotNull] Context ctx) + public virtual ZilAtom GetTypeAtom(Context ctx) { var stdAtom = StdTypeAtom; return ctx.GetStdAtom(stdAtom); @@ -226,7 +222,7 @@ namespace Zilf.Interpreter.Values /// or to use the current environment. /// The result of evaluating this object, which may be the same object. [SuppressMessage("ReSharper", "ConvertIfStatementToReturnStatement")] - public ZilResult Eval([NotNull] Context ctx, [CanBeNull] LocalEnvironment environment = null) + public ZilResult Eval(Context ctx, LocalEnvironment? environment = null) { var del = ctx.GetEvalTypeDelegate(GetTypeAtom(ctx)); @@ -254,7 +250,7 @@ namespace Zilf.Interpreter.Values /// use the knowledge of the original type to return a different result; for example, /// returns a list /// CHTYPEd to the original type. - internal ZilResult EvalAsOtherType([NotNull] Context ctx, [NotNull] ZilAtom originalType) + internal ZilResult EvalAsOtherType(Context ctx, ZilAtom originalType) { return EvalImpl(ctx, null, originalType); } @@ -277,8 +273,8 @@ namespace Zilf.Interpreter.Values /// type as a parameter. EvalImpl may use this to produce an object of the appropriate type; /// for example, see . /// - protected virtual ZilResult EvalImpl([NotNull] Context ctx, [CanBeNull] LocalEnvironment environment, - [CanBeNull] ZilAtom originalType) + protected virtual ZilResult EvalImpl(Context ctx, LocalEnvironment? environment, + ZilAtom? originalType) { return this; } @@ -289,7 +285,7 @@ namespace Zilf.Interpreter.Values /// The current context. /// The result of expanding this object, or the same object if this is /// not a macro invocation. - public virtual ZilResult Expand([NotNull] Context ctx) + public virtual ZilResult Expand(Context ctx) { return this; } @@ -305,7 +301,7 @@ namespace Zilf.Interpreter.Values /// Set to the referenced atom, or null. /// True if the object is an LVAL. [ContractAnnotation("=> false, atom: null; => true, atom: notnull")] - public virtual bool IsLVAL([CanBeNull] out ZilAtom atom) + public virtual bool IsLVAL([NotNullWhen(true)] out ZilAtom? atom) { atom = null; return false; @@ -317,7 +313,7 @@ namespace Zilf.Interpreter.Values /// Set to the referenced atom, or null. /// True if the object is a GVAL. [ContractAnnotation("=> false, atom: null; => true, atom: notnull")] - public virtual bool IsGVAL([CanBeNull] out ZilAtom atom) + public virtual bool IsGVAL([NotNullWhen(true)] out ZilAtom? atom) { atom = null; return false; @@ -329,9 +325,9 @@ namespace Zilf.Interpreter.Values /// The current context. /// The expressions to evaluate. /// The value of the last expression evaluated. - public static ZilResult EvalProgram([NotNull] Context ctx, [NotNull] [ItemNotNull] ZilObject[] prog) + public static ZilResult EvalProgram(Context ctx, ZilObject[] prog) { - ZilResult result = null; + ZilResult result = ctx.FALSE; foreach (var zo in prog) { @@ -343,9 +339,8 @@ namespace Zilf.Interpreter.Values return result; } - [NotNull] - public static IEnumerable ExpandOrEvalWithSplice([NotNull] Context ctx, [NotNull] ZilObject obj, - [CanBeNull] LocalEnvironment environment) + public static IEnumerable ExpandOrEvalWithSplice(Context ctx, ZilObject obj, + LocalEnvironment? environment) { if (obj is IMayExpandBeforeEvaluation expandBefore && expandBefore.ShouldExpandBeforeEvaluation) return expandBefore.ExpandBeforeEvaluation(ctx, environment); @@ -369,15 +364,13 @@ namespace Zilf.Interpreter.Values /// or to use the current environment. /// A sequence of evaluation results. /// The values obtained by expanding segment references are not evaluated in turn. - [NotNull] - public static IEnumerable EvalSequence([NotNull] Context ctx, [ItemNotNull] [NotNull] IEnumerable sequence, - [CanBeNull] LocalEnvironment environment = null) + public static IEnumerable EvalSequence(Context ctx, IEnumerable sequence, + LocalEnvironment? environment = null) { return sequence.SelectMany(zo => ExpandOrEvalWithSplice(ctx, zo, environment)); } - [NotNull] - protected static IEnumerable ExpandWithSplice([NotNull] Context ctx, [NotNull] ZilObject obj) + protected static IEnumerable ExpandWithSplice(Context ctx, ZilObject obj) { if (obj is IMayExpandBeforeEvaluation expandBefore && expandBefore.ShouldExpandBeforeEvaluation) return expandBefore.ExpandBeforeEvaluation(ctx, ctx.LocalEnvironment); @@ -391,9 +384,8 @@ namespace Zilf.Interpreter.Values return Enumerable.Repeat(result, 1); } - [NotNull] - protected static string SequenceToString([NotNull] IEnumerable items, - [NotNull] string start, [NotNull] string end, [NotNull] Func convert) + protected static string SequenceToString(IEnumerable items, + string start, string end, Func convert) { var sb = new StringBuilder(); sb.Append(start); diff --git a/src/Zilf/Interpreter/Values/ZilOffset.cs b/src/Zilf/Interpreter/Values/ZilOffset.cs index c68e04e..17fb7b1 100644 --- a/src/Zilf/Interpreter/Values/ZilOffset.cs +++ b/src/Zilf/Interpreter/Values/ZilOffset.cs @@ -35,7 +35,7 @@ namespace Zilf.Interpreter.Values /// has the wrong number or types of elements. [ChtypeMethod] - public ZilOffset([NotNull] ZilVector vector) + public ZilOffset(ZilVector vector) { if (vector.GetLength() != 3) throw new InterpreterError(InterpreterMessages._0_Must_Have_1_Element1s, "vector coerced to OFFSET", 3); @@ -44,18 +44,18 @@ namespace Zilf.Interpreter.Values throw new InterpreterError(InterpreterMessages.Element_0_Of_1_Must_Be_2, 1, "vector coerced to OFFSET", "a FIX"); Index = indexFix.Value; - StructurePattern = vector[1]; - ValuePattern = vector[2]; + StructurePattern = vector[1]!; + ValuePattern = vector[2]!; } - public ZilOffset(int index, [NotNull] ZilObject structurePattern, [NotNull] ZilObject valuePattern) + public ZilOffset(int index, ZilObject structurePattern, ZilObject valuePattern) { Index = index; StructurePattern = structurePattern ?? throw new ArgumentNullException(nameof(structurePattern)); ValuePattern = valuePattern ?? throw new ArgumentNullException(nameof(valuePattern)); } - public override bool StructurallyEquals(ZilObject obj) + public override bool StructurallyEquals(ZilObject? obj) { return obj is ZilOffset other && other.Index == Index && @@ -74,7 +74,7 @@ namespace Zilf.Interpreter.Values public override string ToString() { - string MaybeQuote(ZilObject zo) + static string MaybeQuote(ZilObject zo) { return zo is ZilAtom ? "'" + zo : zo.ToString(); } @@ -118,7 +118,6 @@ namespace Zilf.Interpreter.Values public override PrimType PrimType => PrimType.VECTOR; - [NotNull] public override ZilObject GetPrimitive(Context ctx) { return new ZilVector(new ZilFix(Index), StructurePattern, ValuePattern); @@ -126,82 +125,58 @@ namespace Zilf.Interpreter.Values #region IStructure Members - [NotNull] public ZilObject GetFirst() { return new ZilFix(Index); } - public IStructure GetRest(int skip) + public IStructure? GetRest(int skip) { - switch (skip) + return skip switch { - case 0: - return this; - - case 1: - return new ZilVector(StructurePattern, ValuePattern); - - case 2: - return new ZilVector(ValuePattern); - - default: - return null; - } + 0 => (IStructure)this, + 1 => new ZilVector(StructurePattern, ValuePattern), + 2 => new ZilVector(ValuePattern), + _ => null + }; } /// Always thrown. - public IStructure GetBack(int skip) - { - throw new NotSupportedException(); - } + [DoesNotReturn] + public IStructure? GetBack(int skip) => throw new NotSupportedException(); /// Always thrown. - public IStructure GetTop() - { - throw new NotSupportedException(); - } + [DoesNotReturn] + public IStructure GetTop() => throw new NotSupportedException(); /// Always thrown. - public void Grow(int end, int beginning, ZilObject defaultValue) - { - throw new NotSupportedException(); - } + [DoesNotReturn] + public void Grow(int end, int beginning, ZilObject defaultValue) => throw new NotSupportedException(); public bool IsEmpty => false; /// Always thrown. + [MaybeNull] public ZilObject this[int index] { get { - switch (index) + return index switch { - case 0: - return new ZilFix(Index); - - case 1: - return StructurePattern; - - case 2: - return ValuePattern; - - default: - return null; - } + 0 => new ZilFix(Index), + 1 => StructurePattern, + 2 => ValuePattern, + _ => null! + }; } + + [DoesNotReturn] set => throw new InterpreterError(InterpreterMessages.OFFSET_Is_Immutable); } - public int GetLength() - { - return 2; - } + public int GetLength() => 2; - public int? GetLength(int limit) - { - return 3 <= limit ? 3 : (int?)null; - } + public int? GetLength(int limit) => 3 <= limit ? 3 : (int?)null; #endregion @@ -212,16 +187,13 @@ namespace Zilf.Interpreter.Values yield return ValuePattern; } - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); [SuppressMessage("ReSharper", "ConvertIfStatementToReturnStatement")] public ZilResult Apply(Context ctx, ZilObject[] args) { - if (EvalSequence(ctx, args).TryToZilObjectArray(out args, out var zr)) - return ApplyNoEval(ctx, args); + if (EvalSequence(ctx, args).TryToZilObjectArray(out var args2, out var zr)) + return ApplyNoEval(ctx, args2); return zr; } diff --git a/src/Zilf/Interpreter/Values/ZilSegment.cs b/src/Zilf/Interpreter/Values/ZilSegment.cs index f5a1ffc..27afe65 100644 --- a/src/Zilf/Interpreter/Values/ZilSegment.cs +++ b/src/Zilf/Interpreter/Values/ZilSegment.cs @@ -19,6 +19,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using Zilf.Language; using Zilf.Diagnostics; using System.Linq; @@ -29,10 +30,9 @@ namespace Zilf.Interpreter.Values [BuiltinType(StdAtom.SEGMENT, PrimType.LIST)] class ZilSegment : ZilObject, IStructure, IMayExpandBeforeEvaluation { - [NotNull] readonly ZilForm form; - public ZilSegment([NotNull] ZilObject obj) + public ZilSegment(ZilObject obj) { if (obj is ZilForm objForm) form = objForm; @@ -40,9 +40,8 @@ namespace Zilf.Interpreter.Values throw new ArgumentException("Segment must be based on a FORM"); } - [NotNull] [ChtypeMethod] - public static ZilSegment FromList([NotNull] ZilListBase list) + public static ZilSegment FromList(ZilListBase list) { if (!(list is ZilForm form)) { @@ -52,10 +51,8 @@ namespace Zilf.Interpreter.Values return new ZilSegment(form); } - [NotNull] public ZilForm Form => form; - [NotNull] public override string ToString() => "!" + form; public override StdAtom StdTypeAtom => StdAtom.SEGMENT; @@ -64,24 +61,23 @@ namespace Zilf.Interpreter.Values public bool ShouldExpandBeforeEvaluation => true; - [NotNull] public override ZilObject GetPrimitive(Context ctx) => new ZilList(form); - protected override ZilResult EvalImpl(Context ctx, LocalEnvironment environment, ZilAtom originalType) => + protected override ZilResult EvalImpl(Context ctx, LocalEnvironment? environment, ZilAtom? originalType) => throw new InterpreterError(InterpreterMessages.A_SEGMENT_Can_Only_Be_Evaluated_Inside_A_Structure); - public override bool StructurallyEquals(ZilObject obj) => + public override bool StructurallyEquals(ZilObject? obj) => obj is ZilSegment other && other.form.StructurallyEquals(form); public override int GetHashCode() => form.GetHashCode(); #region IStructure Members - public ZilObject GetFirst() => form.GetFirst(); + public ZilObject? GetFirst() => form.GetFirst(); - public IStructure GetRest(int skip) => form.GetRest(skip); + public IStructure? GetRest(int skip) => form.GetRest(skip); - public IStructure GetBack(int skip) => throw new NotSupportedException(); + public IStructure? GetBack(int skip) => throw new NotSupportedException(); public IStructure GetTop() => throw new NotSupportedException(); @@ -90,7 +86,6 @@ namespace Zilf.Interpreter.Values public bool IsEmpty => form.IsEmpty; - [CanBeNull] public ZilObject this[int index] { get => form[index]; @@ -107,7 +102,7 @@ namespace Zilf.Interpreter.Values IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public IEnumerable ExpandBeforeEvaluation([NotNull] Context ctx, LocalEnvironment env) + public IEnumerable ExpandBeforeEvaluation(Context ctx, LocalEnvironment? env) { var result = Form.Eval(ctx, env); diff --git a/src/Zilf/Interpreter/Values/ZilSplice.cs b/src/Zilf/Interpreter/Values/ZilSplice.cs index 4fb1f06..1de571f 100644 --- a/src/Zilf/Interpreter/Values/ZilSplice.cs +++ b/src/Zilf/Interpreter/Values/ZilSplice.cs @@ -28,7 +28,7 @@ namespace Zilf.Interpreter.Values bool spliceable; [ChtypeMethod] - public ZilSplice([NotNull] ZilListoidBase other) + public ZilSplice(ZilListoidBase other) : base(other.First, other.Rest) { } diff --git a/src/Zilf/Interpreter/Values/ZilString.cs b/src/Zilf/Interpreter/Values/ZilString.cs index 65f7075..4a8a0f4 100644 --- a/src/Zilf/Interpreter/Values/ZilString.cs +++ b/src/Zilf/Interpreter/Values/ZilString.cs @@ -19,6 +19,8 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; using System.Text; using Zilf.Language; using Zilf.Diagnostics; @@ -30,21 +32,16 @@ namespace Zilf.Interpreter.Values [BuiltinType(StdAtom.STRING, PrimType.STRING)] abstract class ZilString : ZilObject, IStructure { - [NotNull] public abstract string Text { get; set; } - [NotNull] [ChtypeMethod] - public static ZilString FromString([NotNull] ZilString other) => new OriginalString(other.Text); + public static ZilString FromString(ZilString other) => new OriginalString(other.Text); - [NotNull] - public static ZilString FromString([NotNull] string text) => new OriginalString(text); + public static ZilString FromString(string text) => new OriginalString(text); - [NotNull] public sealed override string ToString() => Quote(Text); - [NotNull] - public static string Quote([NotNull] string text) + public static string Quote(string text) { var sb = new StringBuilder(text.Length + 2); sb.Append('"'); @@ -72,7 +69,7 @@ namespace Zilf.Interpreter.Values protected sealed override string ToStringContextImpl(Context ctx, bool friendly) => friendly ? Text : ToString(); - public override bool ExactlyEquals(ZilObject obj) => (obj as ZilString)?.Text.Equals(Text) ?? false; + public override bool ExactlyEquals(ZilObject? obj) => (obj as ZilString)?.Text.Equals(Text) ?? false; public override int GetHashCode() => Text.GetHashCode(); @@ -82,12 +79,11 @@ namespace Zilf.Interpreter.Values public abstract ZilObject this[int index] { get; set; } - [NotNull] public sealed override ZilObject GetPrimitive(Context ctx) => this; - public abstract ZilObject GetFirst(); - public abstract IStructure GetRest(int skip); - public abstract IStructure GetBack(int skip); + public abstract ZilObject? GetFirst(); + public abstract IStructure? GetRest(int skip); + public abstract IStructure? GetBack(int skip); public abstract IStructure GetTop(); public abstract bool IsEmpty { get; } public abstract int GetLength(); @@ -104,24 +100,24 @@ namespace Zilf.Interpreter.Values [BuiltinAlternate(typeof(ZilString))] sealed class OriginalString : ZilString { - public OriginalString([NotNull] string text) + public OriginalString(string text) { Text = text; } public override string Text { get; set; } - public override ZilObject GetFirst() + public override ZilObject? GetFirst() { return Text.Length > 0 ? new ZilChar(Text[0]) : null; } - public override IStructure GetRest(int skip) + public override IStructure? GetRest(int skip) { return skip <= Text.Length ? new OffsetString(this, skip) : null; } - public override IStructure GetBack(int skip) + public override IStructure? GetBack(int skip) { return skip == 0 ? this : null; } @@ -130,14 +126,14 @@ namespace Zilf.Interpreter.Values public override bool IsEmpty => Text.Length == 0; - [CanBeNull] + [MaybeNull] public override ZilObject this[int index] { get { if (index >= 0 && index < Text.Length) return new ZilChar(Text[index]); - return null; + return null!; } set { @@ -164,8 +160,7 @@ namespace Zilf.Interpreter.Values public override IEnumerator GetEnumerator() { - foreach (var c in Text) - yield return new ZilChar(c); + return Text.Select(c => new ZilChar(c)).Cast().GetEnumerator(); } } @@ -187,7 +182,7 @@ namespace Zilf.Interpreter.Values set => orig.Text = orig.Text.Substring(0, offset) + value; } - public override bool StructurallyEquals(ZilObject obj) + public override bool StructurallyEquals(ZilObject? obj) { if (obj is OffsetString other && ReferenceEquals(other.orig, orig) && other.offset == offset) return true; @@ -195,26 +190,19 @@ namespace Zilf.Interpreter.Values return base.StructurallyEquals(obj); } - public override ZilObject GetFirst() - { - return offset < orig.Text.Length ? new ZilChar(orig.Text[offset]) : null; - } + public override ZilObject? GetFirst() => offset < orig.Text.Length ? new ZilChar(orig.Text[offset]) : null; - public override IStructure GetRest(int skip) - { - return offset <= orig.Text.Length - skip ? new OffsetString(orig, offset + skip) : null; - } + public override IStructure? GetRest(int skip) => + offset <= orig.Text.Length - skip ? new OffsetString(orig, offset + skip) : null; - public override IStructure GetBack(int skip) - { - return offset >= skip ? new OffsetString(orig, offset - skip) : null; - } + public override IStructure? GetBack(int skip) => + offset >= skip ? new OffsetString(orig, offset - skip) : null; public override IStructure GetTop() => orig; public override bool IsEmpty => offset >= orig.Text.Length; - [CanBeNull] + [MaybeNull] public override ZilObject this[int index] { get @@ -222,7 +210,7 @@ namespace Zilf.Interpreter.Values index += offset; if (index >= 0 && index < orig.Text.Length) return new ZilChar(orig.Text[index]); - return null; + return null!; } set { @@ -245,10 +233,7 @@ namespace Zilf.Interpreter.Values } } - public override int GetLength() - { - return Math.Max(orig.Text.Length - offset, 0); - } + public override int GetLength() => Math.Max(orig.Text.Length - offset, 0); public override int? GetLength(int limit) { @@ -258,8 +243,7 @@ namespace Zilf.Interpreter.Values public override IEnumerator GetEnumerator() { - for (int i = offset; i < orig.Text.Length; i++) - yield return new ZilChar(orig.Text[i]); + return orig.Text.Skip(offset).Select(c => new ZilChar(c)).Cast().GetEnumerator(); } } } diff --git a/src/Zilf/Interpreter/Values/ZilStructuredHash.cs b/src/Zilf/Interpreter/Values/ZilStructuredHash.cs index ef4ca95..c620d10 100644 --- a/src/Zilf/Interpreter/Values/ZilStructuredHash.cs +++ b/src/Zilf/Interpreter/Values/ZilStructuredHash.cs @@ -18,6 +18,7 @@ using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace Zilf.Interpreter.Values { @@ -32,14 +33,15 @@ namespace Zilf.Interpreter.Values public IEnumerator GetEnumerator() => primValue.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public ZilObject GetFirst() => primValue.GetFirst(); - public IStructure GetRest(int skip) => primValue.GetRest(skip); - public IStructure GetBack(int skip) => primValue.GetBack(skip); + public ZilObject? GetFirst() => primValue.GetFirst(); + public IStructure? GetRest(int skip) => primValue.GetRest(skip); + public IStructure? GetBack(int skip) => primValue.GetBack(skip); public IStructure GetTop() => primValue.GetTop(); + [MaybeNull] public ZilObject this[int index] { - get => primValue[index]; + get => primValue[index]!; set => primValue[index] = value; } diff --git a/src/Zilf/Interpreter/Values/ZilSubr.cs b/src/Zilf/Interpreter/Values/ZilSubr.cs index 7dd7bf9..d88120a 100644 --- a/src/Zilf/Interpreter/Values/ZilSubr.cs +++ b/src/Zilf/Interpreter/Values/ZilSubr.cs @@ -26,25 +26,21 @@ namespace Zilf.Interpreter.Values [BuiltinType(StdAtom.SUBR, PrimType.STRING)] class ZilSubr : ZilObject, IApplicable { - [NotNull] protected readonly string name; - [NotNull] protected readonly SubrDelegate handler; - public ZilSubr([NotNull] string name, [NotNull] SubrDelegate handler) + public ZilSubr(string name, SubrDelegate handler) { this.name = name; this.handler = handler; } [ChtypeMethod] - [NotNull] - public static ZilSubr FromString([NotNull] Context ctx, [NotNull] ZilString str) => + public static ZilSubr FromString(Context ctx, ZilString str) => FromString(ctx, str.ToStringContext(ctx, true)); - [NotNull] - public static ZilSubr FromString([NotNull] Context ctx, [NotNull] string name) + public static ZilSubr FromString(Context ctx, string name) { var del = ctx.GetSubrDelegate(name); if (del != null) @@ -54,14 +50,12 @@ namespace Zilf.Interpreter.Values throw new InterpreterError(InterpreterMessages.Unrecognized_0_1, "SUBR name", name); } - [NotNull] public override string ToString() => $"#SUBR \"{name}\""; public override StdAtom StdTypeAtom => StdAtom.SUBR; public override PrimType PrimType => PrimType.STRING; - [NotNull] public override ZilObject GetPrimitive(Context ctx) => ZilString.FromString(name); public virtual ZilResult Apply(Context ctx, ZilObject[] args) @@ -80,7 +74,7 @@ namespace Zilf.Interpreter.Values public ZilResult ApplyNoEval(Context ctx, ZilObject[] args) => handler(name, ctx, args); - public override bool ExactlyEquals(ZilObject obj) + public override bool ExactlyEquals(ZilObject? obj) { return obj is ZilSubr other && diff --git a/src/Zilf/Interpreter/Values/ZilVector.cs b/src/Zilf/Interpreter/Values/ZilVector.cs index 7e60fca..15eb65d 100644 --- a/src/Zilf/Interpreter/Values/ZilVector.cs +++ b/src/Zilf/Interpreter/Values/ZilVector.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Zilf.Language; using JetBrains.Annotations; @@ -31,33 +32,25 @@ namespace Zilf.Interpreter.Values class VectorStorage { - [NotNull] ZilObject[] items; public VectorStorage() - : this(new ZilObject[0]) + : this(Array.Empty()) { } public int BaseOffset { get; private set; } - public VectorStorage([NotNull] ZilObject[] items) + public VectorStorage(ZilObject[] items) { this.items = items; } - [NotNull] - public IEnumerable GetSequence(int offset) - { - return items.Skip(offset + BaseOffset); - } + public IEnumerable GetSequence(int offset) => items.Skip(offset + BaseOffset); - public int GetLength(int offset) - { - return items.Length - offset - BaseOffset; - } + public int GetLength(int offset) => items.Length - offset - BaseOffset; - public ZilObject GetItem(int offset, int index) + public ZilObject? GetItem(int offset, int index) { try { @@ -117,24 +110,24 @@ namespace Zilf.Interpreter.Values } [ChtypeMethod] - public ZilVector([NotNull] ZilVector other) + public ZilVector(ZilVector other) : this(other.storage, other.offset) { } - ZilVector([NotNull] VectorStorage storage, int offset) + ZilVector(VectorStorage storage, int offset) { this.storage = storage; this.offset = offset; } - public ZilVector([NotNull] params ZilObject[] items) + public ZilVector(params ZilObject[] items) { storage = new VectorStorage(items); offset = 0; } - public override bool StructurallyEquals(ZilObject obj) + public override bool StructurallyEquals(ZilObject? obj) { return obj is ZilVector other && this.SequenceStructurallyEqual(other); } @@ -175,13 +168,12 @@ namespace Zilf.Interpreter.Values public override PrimType PrimType => PrimType.VECTOR; - [NotNull] public override ZilObject GetPrimitive(Context ctx) { return this; } - protected override ZilResult EvalImpl(Context ctx, LocalEnvironment environment, ZilAtom originalType) + protected override ZilResult EvalImpl(Context ctx, LocalEnvironment? environment, ZilAtom? originalType) { var result = EvalSequence(ctx, this, environment).ToZilVectorResult(SourceLine); if (result.ShouldPass()) @@ -192,43 +184,25 @@ namespace Zilf.Interpreter.Values #region IEnumerable Members - public IEnumerator GetEnumerator() - { - return storage.GetSequence(offset).GetEnumerator(); - } + public IEnumerator GetEnumerator() => storage.GetSequence(offset).GetEnumerator(); #endregion #region IEnumerable Members - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); #endregion #region IStructure Members - public ZilObject GetFirst() - { - return storage.GetItem(offset, 0); - } + public ZilObject? GetFirst() => storage.GetItem(offset, 0); - public IStructure GetRest(int skip) - { - return skip > GetLength() ? null : new ZilVector(storage, offset + skip); - } + public IStructure? GetRest(int skip) => skip > GetLength() ? null : new ZilVector(storage, offset + skip); - public IStructure GetBack(int skip) - { - return offset + storage.BaseOffset >= skip ? new ZilVector(storage, offset - skip) : null; - } + public IStructure? GetBack(int skip) => offset + storage.BaseOffset >= skip ? new ZilVector(storage, offset - skip) : null; - public IStructure GetTop() - { - return offset == -storage.BaseOffset ? this : new ZilVector(storage, -storage.BaseOffset); - } + public IStructure GetTop() => offset == -storage.BaseOffset ? this : new ZilVector(storage, -storage.BaseOffset); public void Grow(int end, int beginning, ZilObject defaultValue) { @@ -238,9 +212,10 @@ namespace Zilf.Interpreter.Values public bool IsEmpty => storage.GetLength(offset) <= 0; /// is out of range. + [MaybeNull] public ZilObject this[int index] { - get => storage.GetItem(offset, index); + get => storage.GetItem(offset, index)!; set => storage.PutItem(offset, index, value); } diff --git a/src/Zilf/Interpreter/WeakCountingSet.cs b/src/Zilf/Interpreter/WeakCountingSet.cs index 6ca9b5e..d10bdec 100644 --- a/src/Zilf/Interpreter/WeakCountingSet.cs +++ b/src/Zilf/Interpreter/WeakCountingSet.cs @@ -30,11 +30,17 @@ namespace Zilf.Interpreter { public WeakReference Ref; public int Count; + + public Cell(T value) + { + Ref = new WeakReference(value); + Count = 1; + } } readonly Dictionary> buckets = new Dictionary>(); - public void Add([NotNull] T value) + public void Add(T value) { var hashCode = value.GetHashCode(); @@ -55,29 +61,29 @@ namespace Zilf.Interpreter buckets.Add(hashCode, bucket); } - bucket.Add(new Cell { Ref = new WeakReference(value), Count = 1 }); + bucket.Add(new Cell(value)); } - public void Remove([NotNull] T value) + public void Remove(T value) { var hashCode = value.GetHashCode(); - if (buckets.TryGetValue(hashCode, out var bucket)) + if (!buckets.TryGetValue(hashCode, out var bucket)) + return; + + for (int i = 0; i < bucket.Count; i++) { - for (int i = 0; i < bucket.Count; i++) - { - var cell = bucket[i]; + var cell = bucket[i]; - if (cell.Ref.TryGetTarget(out var existingValue) && existingValue.Equals(value)) - { - cell.Count--; + if (!cell.Ref.TryGetTarget(out var existingValue) || !existingValue.Equals(value)) + continue; - if (cell.Count <= 0) - bucket.RemoveAt(i); + cell.Count--; - return; - } - } + if (cell.Count <= 0) + bucket.RemoveAt(i); + + return; } } diff --git a/src/Zilf/Interpreter/ZilResult.cs b/src/Zilf/Interpreter/ZilResult.cs index 10c34e1..1af15b7 100644 --- a/src/Zilf/Interpreter/ZilResult.cs +++ b/src/Zilf/Interpreter/ZilResult.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; @@ -31,8 +32,8 @@ namespace Zilf.Interpreter struct ZilResult { private readonly Outcome outcome; - private readonly ZilObject value; - private readonly ZilActivation activation; + private readonly ZilObject? value; + private readonly ZilActivation? activation; public enum Outcome : byte { @@ -44,7 +45,7 @@ namespace Zilf.Interpreter MapStop = 5, } - private ZilResult(Outcome outcome, ZilObject value, ZilActivation activation) + private ZilResult(Outcome outcome, ZilObject? value, ZilActivation? activation) { this.outcome = outcome; this.value = value; @@ -72,35 +73,17 @@ namespace Zilf.Interpreter return sb.ToString(); } - public static implicit operator ZilResult(ZilObject value) - { - return new ZilResult(Outcome.Value, value, null); - } + public static implicit operator ZilResult(ZilObject value) => new ZilResult(Outcome.Value, value, null); - public static ZilResult MapRet([NotNull] ZilObject[] values) - { - return new ZilResult(Outcome.MapRet, new ZilVector(values), null); - } + public static ZilResult MapRet(ZilObject[] values) => new ZilResult(Outcome.MapRet, new ZilVector(values), null); - public static ZilResult MapStop([NotNull] ZilObject[] values) - { - return new ZilResult(Outcome.MapStop, new ZilVector(values), null); - } + public static ZilResult MapStop(ZilObject[] values) => new ZilResult(Outcome.MapStop, new ZilVector(values), null); - public static ZilResult MapLeave(ZilObject value) - { - return new ZilResult(Outcome.MapLeave, value, null); - } + public static ZilResult MapLeave(ZilObject value) => new ZilResult(Outcome.MapLeave, value, null); - public static ZilResult Return(ZilActivation activation, ZilObject value) - { - return new ZilResult(Outcome.Return, value, activation); - } + public static ZilResult Return(ZilActivation activation, ZilObject value) => new ZilResult(Outcome.Return, value, activation); - public static ZilResult Again(ZilActivation activation) - { - return new ZilResult(Outcome.Again, null, activation); - } + public static ZilResult Again(ZilActivation activation) => new ZilResult(Outcome.Again, null, activation); /// /// Extracts the value, if this result is a simple value, or throws an exception. @@ -110,7 +93,7 @@ namespace Zilf.Interpreter public static explicit operator ZilObject(ZilResult result) { if (result.outcome == Outcome.Value) - return result.value; + return result.value!; throw new InterpreterError(InterpreterMessages.Misplaced_0, result.outcome.ToString().ToUpperInvariant()); } @@ -121,7 +104,7 @@ namespace Zilf.Interpreter return ShouldPass(null, ref dummy); } - public bool ShouldPass([CanBeNull] ZilActivation currentActivation, ref ZilResult resultToPass) + public bool ShouldPass(ZilActivation? currentActivation, ref ZilResult resultToPass) { switch (outcome) { @@ -129,6 +112,7 @@ namespace Zilf.Interpreter return false; case Outcome.Return when currentActivation != null && activation == currentActivation: + Debug.Assert(value != null); resultToPass = value; return true; @@ -141,37 +125,35 @@ namespace Zilf.Interpreter [SuppressMessage("ReSharper", "ParameterHidesMember")] public bool IsMapControl(out Outcome outcome, out ZilObject value) { + Debug.Assert(this.value != null); + outcome = this.outcome; value = this.value; - switch (this.outcome) + return this.outcome switch { - case Outcome.MapLeave: - case Outcome.MapRet: - case Outcome.MapStop: - return true; - - default: - return false; - } + Outcome.MapLeave => true, + Outcome.MapRet => true, + Outcome.MapStop => true, + _ => false + }; } [SuppressMessage("ReSharper", "ParameterHidesMember")] public bool IsReturn(ZilActivation currentActivation, out ZilObject value) { + Debug.Assert(this.value != null); value = this.value; return outcome == Outcome.Return && activation == currentActivation; } public bool IsAgain(ZilActivation currentActivation) => outcome == Outcome.Again && activation == currentActivation; - - public bool IsNull => outcome == Outcome.Value && value == null; } static class ZilResultSequenceExtensions { - public static IEnumerable Trim([NotNull] this IEnumerable inputs) + public static IEnumerable Trim(this IEnumerable inputs) { foreach (var i in inputs) { @@ -182,32 +164,31 @@ namespace Zilf.Interpreter } } - [NotNull] - public static IEnumerable AsResultSequence([NotNull] this IEnumerable inputs) + public static IEnumerable AsResultSequence(this IEnumerable inputs) { return inputs.Select(i => i); } - public static ZilResult ToZilVectorResult([NotNull] this IEnumerable inputs, ISourceLine sourceLine) + public static ZilResult ToZilVectorResult(this IEnumerable inputs, ISourceLine? sourceLine) { var array = inputs.Trim().ToArray(); - if (array.Length > 0 && array[array.Length - 1].ShouldPass()) - return array[array.Length - 1]; + if (array.Length > 0 && array[^1].ShouldPass()) + return array[^1]; return new ZilVector(Array.ConvertAll(array, i => (ZilObject)i)) { SourceLine = sourceLine }; } - public static ZilResult ToZilListResult([NotNull] this IEnumerable inputs, ISourceLine sourceLine) + public static ZilResult ToZilListResult(this IEnumerable inputs, ISourceLine? sourceLine) { var array = inputs.Trim().ToArray(); - if (array.Length > 0 && array[array.Length - 1].ShouldPass()) - return array[array.Length - 1]; + if (array.Length > 0 && array[^1].ShouldPass()) + return array[^1]; return new ZilList(array.Select(i => (ZilObject)i)) { SourceLine = sourceLine }; } [ContractAnnotation("=> false, array: null; => true, array: notnull")] - public static bool TryToZilObjectArray([NotNull] this IEnumerable inputs, [CanBeNull] out ZilObject[] array, out ZilResult result) + public static bool TryToZilObjectArray(this IEnumerable inputs, [NotNullWhen(true)] out ZilObject[]? array, out ZilResult result) { List list; if (inputs is ICollection coll) @@ -236,7 +217,7 @@ namespace Zilf.Interpreter return true; } - public static bool SequenceStructurallyEqual([NotNull] this IEnumerable first, [NotNull] IEnumerable second) + public static bool SequenceStructurallyEqual(this IEnumerable first, IEnumerable second) { #pragma warning disable ZILF0005 // Comparing ZilObjects with Equals return first.SequenceEqual(second, StructuralEqualityComparer.Instance); diff --git a/src/Zilf/Language/AtomAttribute.cs b/src/Zilf/Language/AtomAttribute.cs index ad985a2..105f1d8 100644 --- a/src/Zilf/Language/AtomAttribute.cs +++ b/src/Zilf/Language/AtomAttribute.cs @@ -24,12 +24,11 @@ namespace Zilf.Language [AttributeUsage(AttributeTargets.Field)] sealed class AtomAttribute : Attribute { - public AtomAttribute([NotNull] string name) + public AtomAttribute(string name) { Name = name; } - [NotNull] public string Name { get; } } } \ No newline at end of file diff --git a/src/Zilf/Language/CompilerError.cs b/src/Zilf/Language/CompilerError.cs index 54e2eae..81d6394 100644 --- a/src/Zilf/Language/CompilerError.cs +++ b/src/Zilf/Language/CompilerError.cs @@ -32,60 +32,57 @@ namespace Zilf.Language { } - public CompilerError(int code, [ItemNotNull] params object[] messageArgs) + public CompilerError(int code, params object[]? messageArgs) : this(DiagnosticContext.Current.SourceLine, code, messageArgs) { } - public CompilerError([CanBeNull] ISourceLine sourceLine, int code) + public CompilerError(ISourceLine? sourceLine, int code) : this(sourceLine, code, null) { } - public CompilerError([CanBeNull] ISourceLine sourceLine, int code, [ItemNotNull] params object[] messageArgs) + public CompilerError(ISourceLine? sourceLine, int code, params object[]? messageArgs) : base(MakeDiagnostic(sourceLine, code, messageArgs)) { } - public CompilerError([NotNull] IProvideSourceLine sourceLine, int code) + public CompilerError(IProvideSourceLine sourceLine, int code) : this(sourceLine, code, null) { } - public CompilerError([NotNull] IProvideSourceLine node, int code, params object[] messageArgs) + public CompilerError(IProvideSourceLine node, int code, params object[]? messageArgs) : base(MakeDiagnostic(node.SourceLine, code, messageArgs)) { } [UsedImplicitly] - public CompilerError([NotNull] Diagnostic diagnostic) + public CompilerError(Diagnostic diagnostic) : base(diagnostic) { } - protected CompilerError([NotNull] SerializationInfo si, StreamingContext sc) + protected CompilerError(SerializationInfo si, StreamingContext sc) : base(si, sc) { } - [NotNull] - public static CompilerError WrongArgCount([NotNull] string name, [NotNull] IEnumerable ranges, + public static CompilerError WrongArgCount(string name, IEnumerable ranges, int? acceptableVersion = null) { ArgCountHelpers.FormatArgCount(ranges, out var cs); return WrongArgCount(name, cs, acceptableVersion); } - [NotNull] - public static CompilerError WrongArgCount([NotNull] string name, ArgCountRange range, + public static CompilerError WrongArgCount(string name, ArgCountRange range, int? acceptableVersion = null) { ArgCountHelpers.FormatArgCount(range, out var cs); return WrongArgCount(name, cs, acceptableVersion); } - [NotNull] - static CompilerError WrongArgCount([NotNull] string name, CountableString cs, int? acceptableVersion) + static CompilerError WrongArgCount(string name, CountableString cs, int? acceptableVersion) { var error = new CompilerError(CompilerMessages._0_Requires_1_Argument1s, name, cs); @@ -99,5 +96,21 @@ namespace Zilf.Language return error; } + + public CompilerError() + { + } + + protected CompilerError(string message) : base(message) + { + } + + protected CompilerError(string message, Exception innerException) : base(message, innerException) + { + } + + protected CompilerError(ISourceLine src, string message) : base(src, message) + { + } } } \ No newline at end of file diff --git a/src/Zilf/Language/CompilerFatal.cs b/src/Zilf/Language/CompilerFatal.cs index 3e1ccaa..a36332c 100644 --- a/src/Zilf/Language/CompilerFatal.cs +++ b/src/Zilf/Language/CompilerFatal.cs @@ -31,7 +31,7 @@ namespace Zilf.Language { } - public CompilerFatal(int code, [ItemNotNull] params object[] messageArgs) + public CompilerFatal(int code, params object[]? messageArgs) : this(DiagnosticContext.Current.SourceLine, code, messageArgs) { } @@ -41,30 +41,42 @@ namespace Zilf.Language { } - public CompilerFatal(ISourceLine sourceLine, int code, [ItemNotNull] params object[] messageArgs) + public CompilerFatal(ISourceLine sourceLine, int code, params object[]? messageArgs) : base(MakeDiagnostic(sourceLine, code, messageArgs)) { } - public CompilerFatal([NotNull] IProvideSourceLine sourceLine, int code) - : this(sourceLine, code, null) + public CompilerFatal(IProvideSourceLine sourceLine, int code) + : this(sourceLine, code, null) { } - public CompilerFatal([NotNull] IProvideSourceLine node, int code, params object[] messageArgs) + public CompilerFatal(IProvideSourceLine node, int code, params object[]? messageArgs) : base(MakeDiagnostic(node.SourceLine, code, messageArgs)) { } [UsedImplicitly] - public CompilerFatal([NotNull] Diagnostic diagnostic) + public CompilerFatal(Diagnostic diagnostic) : base(diagnostic) { } - protected CompilerFatal([NotNull] SerializationInfo si, StreamingContext sc) + protected CompilerFatal(SerializationInfo si, StreamingContext sc) : base(si, sc) { } + + public CompilerFatal() + { + } + + protected CompilerFatal(string message) : base(message) + { + } + + protected CompilerFatal(string message, Exception innerException) : base(message, innerException) + { + } } } \ No newline at end of file diff --git a/src/Zilf/Language/Decl.cs b/src/Zilf/Language/Decl.cs index e46b3b3..8b283bc 100644 --- a/src/Zilf/Language/Decl.cs +++ b/src/Zilf/Language/Decl.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; @@ -31,8 +32,7 @@ namespace Zilf.Language { interface IProvideStructureForDeclCheck { - [NotNull] - IStructure GetStructureForDeclCheck([NotNull] Context ctx); + IStructure GetStructureForDeclCheck(Context ctx); } /// @@ -43,43 +43,90 @@ namespace Zilf.Language { const int DiagnosticCode = InterpreterMessages.Expected_0_To_Match_DECL_1_But_Got_2; - public DeclCheckError([NotNull] Context ctx, [NotNull] ZilObject value, [NotNull] ZilObject pattern, - [NotNull] string usage) + public DeclCheckError(Context ctx, ZilObject value, ZilObject pattern, + string usage) : base(DiagnosticCode, usage, pattern.ToStringContext(ctx, false), value.ToStringContext(ctx, false)) { } - public DeclCheckError([NotNull] IProvideSourceLine src, [NotNull] Context ctx, [NotNull] ZilObject value, - [NotNull] ZilObject pattern, string usage) + public DeclCheckError(IProvideSourceLine src, Context ctx, ZilObject value, + ZilObject pattern, string usage) : base(src, DiagnosticCode, usage, pattern.ToStringContext(ctx, false), value.ToStringContext(ctx, false)) { } [StringFormatMethod("usageFormat")] - public DeclCheckError([NotNull] Context ctx, [NotNull] ZilObject value, [NotNull] ZilObject pattern, - [NotNull] string usageFormat, [NotNull] object arg0) + public DeclCheckError(Context ctx, ZilObject value, ZilObject pattern, + string usageFormat, object arg0) : this(ctx, value, pattern, string.Format(usageFormat, arg0)) { } [StringFormatMethod("usageFormat")] - public DeclCheckError([NotNull] IProvideSourceLine src, [NotNull] Context ctx, [NotNull] ZilObject value, - [NotNull] ZilObject pattern, [NotNull] string usageFormat, [NotNull] object arg0) + public DeclCheckError(IProvideSourceLine src, Context ctx, ZilObject value, + ZilObject pattern, string usageFormat, object arg0) : this(src, ctx, value, pattern, string.Format(usageFormat, arg0)) { } - protected DeclCheckError([NotNull] SerializationInfo si, StreamingContext sc) + protected DeclCheckError(SerializationInfo si, StreamingContext sc) : base(si, sc) { } + + [EditorBrowsable(EditorBrowsableState.Advanced)] + public DeclCheckError() + { + } + + [EditorBrowsable(EditorBrowsableState.Advanced)] + public DeclCheckError(string message) : base(message) + { + } + + [EditorBrowsable(EditorBrowsableState.Advanced)] + public DeclCheckError(string message, Exception innerException) : base(message, innerException) + { + } + + public DeclCheckError(int code) : base(code) + { + } + + public DeclCheckError(int code, params object[] messageArgs) : base(code, messageArgs) + { + } + + public DeclCheckError(ISourceLine sourceLine, int code) : base(sourceLine, code) + { + } + + public DeclCheckError(ISourceLine sourceLine, int code, params object[] messageArgs) : base(sourceLine, code, messageArgs) + { + } + + public DeclCheckError(IProvideSourceLine sourceLine, int code) : base(sourceLine, code) + { + } + + public DeclCheckError(IProvideSourceLine node, int code, params object[] messageArgs) : base(node, code, messageArgs) + { + } + + public DeclCheckError(Diagnostic diagnostic) : base(diagnostic) + { + } + + protected DeclCheckError(ISourceLine src, string message) : base(src, message) + { + } } static class Decl { /// The syntax is incorrect. [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] - public static bool Check([NotNull] Context ctx, [NotNull] ZilObject value, [NotNull] ZilObject pattern, + public static bool Check(Context ctx, ZilObject value, ZilObject pattern, bool ignoreErrors = false) { switch (pattern) @@ -95,7 +142,7 @@ namespace Zilf.Language return value.IsApplicable(ctx); case StdAtom.STRUCTURED: - return (value is IStructure); + return value is IStructure; case StdAtom.TUPLE: // special case @@ -156,7 +203,7 @@ namespace Zilf.Language } } - static bool CheckFormOrSegment([NotNull] Context ctx, [NotNull] ZilObject value, [NotNull] ZilForm form, + static bool CheckFormOrSegment(Context ctx, ZilObject value, ZilForm form, bool segment, bool ignoreErrors) { var (first, rest) = form; @@ -201,34 +248,38 @@ namespace Zilf.Language } [ContractAnnotation("=> true, decl: notnull; => false, decl: null")] - static bool IsNonCircularAlias([NotNull] Context ctx, [NotNull] ZilAtom atom, out ZilObject decl) + static bool IsNonCircularAlias(Context ctx, ZilAtom atom, [NotNullWhen(true)] out ZilObject? decl) { var seen = new HashSet(); var declAtom = ctx.GetStdAtom(StdAtom.DECL); - ZilObject value; - do + ZilAtom? atm = atom; + + while (true) { - seen.Add(atom); + seen.Add(atm); - value = ctx.GetProp(atom, declAtom); - atom = value as ZilAtom; - } while (atom != null && !seen.Contains(atom)); + var value = ctx.GetProp(atm, declAtom); + atm = value as ZilAtom; + + if (atm == null) + { + // noncircular, or not an alias + decl = value; + return value != null; + } + + if (!seen.Contains(atm)) + continue; - if (atom != null) - { // circular decl = null; return false; } - - // noncircular, or not an alias - decl = value; - return value != null; } - static bool CheckElements([NotNull] Context ctx, [NotNull] IStructure structure, - [NotNull] ZilListoidBase elements, bool segment, bool ignoreErrors) + static bool CheckElements(Context ctx, IStructure structure, + ZilListoidBase elements, bool segment, bool ignoreErrors) { foreach (var subpattern in elements) { @@ -248,17 +299,17 @@ namespace Zilf.Language i = 1; while (!structure.IsEmpty) { - first = structure.GetFirst(); + first = structure.GetFirst()!; Debug.Assert(first != null); - if (!Check(ctx, first, vector[i])) + if (!Check(ctx, first, vector[i]!)) return false; i++; if (i >= len) i = 1; - structure = structure.GetRest(1); + structure = structure.GetRest(1)!; Debug.Assert(structure != null); } @@ -279,13 +330,13 @@ namespace Zilf.Language if (structure.IsEmpty) break; - first = structure.GetFirst(); + first = structure.GetFirst()!; Debug.Assert(first != null); - if (!Check(ctx, first, vector[i])) + if (!Check(ctx, first, vector[i]!)) break; - structure = structure.GetRest(1); + structure = structure.GetRest(1)!; Debug.Assert(structure != null); } @@ -304,13 +355,13 @@ namespace Zilf.Language if (structure.IsEmpty) return false; - first = structure.GetFirst(); + first = structure.GetFirst()!; Debug.Assert(first != null); - if (!Check(ctx, first, vector[j])) + if (!Check(ctx, first, vector[j]!)) return false; - structure = structure.GetRest(1); + structure = structure.GetRest(1)!; Debug.Assert(structure != null); } } @@ -331,13 +382,13 @@ namespace Zilf.Language if (structure.IsEmpty) return false; - first = structure.GetFirst(); + first = structure.GetFirst()!; Debug.Assert(first != null); if (!Check(ctx, first, subpattern)) return false; - structure = structure.GetRest(1); + structure = structure.GetRest(1)!; Debug.Assert(structure != null); } diff --git a/src/Zilf/Language/FileSourceLine.cs b/src/Zilf/Language/FileSourceLine.cs index 4f7217e..16ac279 100644 --- a/src/Zilf/Language/FileSourceLine.cs +++ b/src/Zilf/Language/FileSourceLine.cs @@ -22,13 +22,12 @@ namespace Zilf.Language { sealed class FileSourceLine : ISourceLine { - public FileSourceLine([NotNull] string filename, int line) + public FileSourceLine(string filename, int line) { FileName = filename; Line = line; } - [NotNull] public string SourceInfo => $"{FileName}:{Line}"; public string FileName { get; } diff --git a/src/Zilf/Language/IProvideSourceLine.cs b/src/Zilf/Language/IProvideSourceLine.cs index fdec630..3eea120 100644 --- a/src/Zilf/Language/IProvideSourceLine.cs +++ b/src/Zilf/Language/IProvideSourceLine.cs @@ -20,7 +20,7 @@ namespace Zilf.Language { interface IProvideSourceLine { - ISourceLine SourceLine { get; } + ISourceLine? SourceLine { get; } } interface ISettableSourceLine diff --git a/src/Zilf/Language/InterpreterError.cs b/src/Zilf/Language/InterpreterError.cs index 4739561..920fb33 100644 --- a/src/Zilf/Language/InterpreterError.cs +++ b/src/Zilf/Language/InterpreterError.cs @@ -26,67 +26,59 @@ namespace Zilf.Language [Serializable] class InterpreterError : ZilError { - [Obsolete("Use a constructor that takes a diagnostic code.")] - public InterpreterError([NotNull] string message) - : base(message) + public InterpreterError(int code) + : this(code, null) { } - [Obsolete("Use a constructor that takes a diagnostic code.")] - public InterpreterError([NotNull] string message, Exception innerException) - : base(message, innerException) + public InterpreterError(int code, params object[]? messageArgs) + : this(DiagnosticContext.Current.SourceLine, code, messageArgs) { } - [Obsolete("Use a constructor that takes a diagnostic code.")] - public InterpreterError(ISourceLine src, [NotNull] string message) - : base(src, message) + public InterpreterError(ISourceLine? sourceLine, int code) + : this(sourceLine, code, null) { } - [Obsolete("Use a constructor that takes a diagnostic code.")] - public InterpreterError([NotNull] IProvideSourceLine node, [NotNull] string message) - : base(node.SourceLine, message) + public InterpreterError(ISourceLine? sourceLine, int code, params object[]? messageArgs) + : base(MakeDiagnostic(sourceLine, code, messageArgs)) { } - public InterpreterError(int code) - : this(code, null) + public InterpreterError(IProvideSourceLine? sourceLine, int code) + : this(sourceLine, code, null) { } - public InterpreterError(int code, params object[] messageArgs) - : this(DiagnosticContext.Current.SourceLine, code, messageArgs) + public InterpreterError(IProvideSourceLine? node, int code, params object[]? messageArgs) + : base(MakeDiagnostic(node?.SourceLine, code, messageArgs)) { } - public InterpreterError(ISourceLine sourceLine, int code) - : this(sourceLine, code, null) + public InterpreterError(Diagnostic diagnostic) + : base(diagnostic) { } - public InterpreterError(ISourceLine sourceLine, int code, params object[] messageArgs) - : base(MakeDiagnostic(sourceLine, code, messageArgs)) + protected InterpreterError(SerializationInfo si, StreamingContext sc) + : base(si, sc) { } - public InterpreterError([NotNull] IProvideSourceLine sourceLine, int code) - : this(sourceLine, code, null) + protected InterpreterError(string message) : base(message) { } - public InterpreterError([NotNull] IProvideSourceLine node, int code, params object[] messageArgs) - : base(MakeDiagnostic(node.SourceLine, code, messageArgs)) + protected InterpreterError(string message, Exception innerException) : base(message, innerException) { } - public InterpreterError([NotNull] Diagnostic diagnostic) - : base(diagnostic) + protected InterpreterError(ISourceLine src, string message) : base(src, message) { } - protected InterpreterError([NotNull] SerializationInfo si, StreamingContext sc) - : base(si, sc) + protected InterpreterError() : base() { } } diff --git a/src/Zilf/Language/Parser.cs b/src/Zilf/Language/Parser.cs index 4341689..b538605 100644 --- a/src/Zilf/Language/Parser.cs +++ b/src/Zilf/Language/Parser.cs @@ -29,13 +29,11 @@ namespace Zilf.Language { sealed class CharBuffer { - [NotNull] readonly IEnumerator source; - [NotNull] readonly Stack heldChars = new Stack(2); char? curChar; - public CharBuffer([NotNull] IEnumerable source) + public CharBuffer(IEnumerable source) { this.source = source.GetEnumerator(); } @@ -70,22 +68,45 @@ namespace Zilf.Language protected ParserException(string message, Exception innerException) : base(message, innerException) { } - protected ParserException([NotNull] SerializationInfo info, StreamingContext context) + protected ParserException(SerializationInfo info, StreamingContext context) : base(info, context) { } + + public ParserException() : base() + { + } + + public ParserException(string message) : base(message) + { + } } [Serializable] sealed class ExpectedButFound : ParserException { - public ExpectedButFound(string expected, string actual, [CanBeNull] Exception innerException = null) + public ExpectedButFound(string expected, string actual, Exception innerException) : base($"expected {expected} but found {actual}", innerException) { } - ExpectedButFound([NotNull] SerializationInfo info, StreamingContext context) + public ExpectedButFound(string expected, string actual) + : base($"expected {expected} but found {actual}") { } + + ExpectedButFound(SerializationInfo info, StreamingContext context) : base(info, context) { } + + private ExpectedButFound(string message, Exception innerException) : base(message, innerException) + { + } + + public ExpectedButFound() + { + } + + public ExpectedButFound(string message) : base(message) + { + } } [Serializable] @@ -93,36 +114,41 @@ namespace Zilf.Language { const string DefaultRadix = "decimal"; - public ParsedNumberOverflowed(string number, string radix = DefaultRadix, [CanBeNull] Exception innerException = null) + public ParsedNumberOverflowed(string number, string radix, Exception innerException) : base($"{radix} number '{number}' cannot be represented in 32 bits", innerException) { } - public ParsedNumberOverflowed(string number, [CanBeNull] Exception innerException) + public ParsedNumberOverflowed(string number, string radix = DefaultRadix) + : base($"{radix} number '{number}' cannot be represented in 32 bits") { } + + public ParsedNumberOverflowed(string number, Exception innerException) : this(number, DefaultRadix, innerException) { } - ParsedNumberOverflowed([NotNull] SerializationInfo info, StreamingContext context) + ParsedNumberOverflowed(SerializationInfo info, StreamingContext context) : base(info, context) { } + + public ParsedNumberOverflowed() : base() + { + } + + public ParsedNumberOverflowed(string message) : base(message) + { + } } interface IParserSite { - [NotNull] - ZilAtom ParseAtom([NotNull] string text); + ZilAtom ParseAtom(string text); - [NotNull] - ZilAtom GetTypeAtom([NotNull] ZilObject zo); + ZilAtom GetTypeAtom(ZilObject zo); - [NotNull] - ZilObject ChangeType([NotNull] ZilObject zo, [NotNull] ZilAtom type); + ZilObject ChangeType(ZilObject zo, ZilAtom type); - [NotNull] - ZilObject Evaluate([NotNull] ZilObject zo); + ZilObject Evaluate(ZilObject zo); - [CanBeNull] - ZilObject GetGlobalVal([NotNull] ZilAtom atom); + ZilObject? GetGlobalVal(ZilAtom atom); - [NotNull] string CurrentFilePath { get; } } @@ -231,22 +257,22 @@ namespace Zilf.Language sealed class Parser { readonly IParserSite site; - readonly ISourceLine srcOverride; - readonly ZilObject[] templateParams; + readonly ISourceLine? srcOverride; + readonly ZilObject[]? templateParams; readonly Queue heldObjects = new Queue(); int line = 1; - public Parser([NotNull] IParserSite site) - : this(site, (ISourceLine)null, null) + public Parser(IParserSite site) + : this(site, (ISourceLine?)null, null) { } - public Parser([NotNull] IParserSite site, params ZilObject[] templateParams) + public Parser(IParserSite site, params ZilObject[] templateParams) : this(site, null, templateParams) { } - public Parser([NotNull] IParserSite site, ISourceLine srcOverride, params ZilObject[] templateParams) + public Parser(IParserSite site, ISourceLine? srcOverride, params ZilObject[]? templateParams) { this.site = site; this.srcOverride = srcOverride; @@ -255,14 +281,12 @@ namespace Zilf.Language public int Line => line; - [NotNull] - public IEnumerable Parse([NotNull] IEnumerable chars) + public IEnumerable Parse(IEnumerable chars) { return Parse(new CharBuffer(chars)); } - [NotNull] - IEnumerable Parse([NotNull] CharBuffer chars) + IEnumerable Parse(CharBuffer chars) { while (true) { @@ -290,7 +314,7 @@ namespace Zilf.Language } } - ParserOutput ParseOne(CharBuffer chars, [NotNull] out ISourceLine sourceLine) + ParserOutput ParseOne(CharBuffer chars, out ISourceLine sourceLine) { if (heldObjects.Count > 0) { @@ -349,7 +373,7 @@ namespace Zilf.Language } } - ParserOutput ParseOneNonAdecl(CharBuffer chars, [NotNull] out ISourceLine sourceLine) + ParserOutput ParseOneNonAdecl(CharBuffer chars, out ISourceLine sourceLine) { try { @@ -595,7 +619,7 @@ namespace Zilf.Language } } - bool SkipWhitespace([NotNull] CharBuffer chars) + bool SkipWhitespace(CharBuffer chars) { while (true) { @@ -654,8 +678,7 @@ namespace Zilf.Language } } - [CanBeNull] - ZilObject ParseCurrentAtomOrNumber([NotNull] CharBuffer chars) + ZilObject ParseCurrentAtomOrNumber(CharBuffer chars) { var sb = new StringBuilder(); @@ -770,11 +793,10 @@ namespace Zilf.Language // must be an atom var atom = site.ParseAtom(sb.ToString()); - return atom is ZilLink ? site.GetGlobalVal(atom) : atom; + return atom is ZilLink && site.GetGlobalVal(atom) is ZilObject zo ? zo : atom; } - [NotNull] - ZilString ParseCurrentString([NotNull] CharBuffer chars) + ZilString ParseCurrentString(CharBuffer chars) { var sb = new StringBuilder(); @@ -816,7 +838,6 @@ namespace Zilf.Language throw new ExpectedButFound("'\"'", ""); } - [NotNull] static string KetWanted(char ket1, char? ket2) { return ket2 == null @@ -824,8 +845,7 @@ namespace Zilf.Language : $"'{ket1.Rebang()}' or '{((char)ket2).Rebang()}'"; } - [NotNull] - T ParseCurrentStructure([NotNull] CharBuffer chars, char ket1, char? ket2, [NotNull] Func, T> build) + T ParseCurrentStructure(CharBuffer chars, char ket1, char? ket2, Func, T> build) { var items = new List(); @@ -960,7 +980,6 @@ namespace Zilf.Language } } - [NotNull] public static string Rebang(this char ch) { if (ch >= 128 && ch < 256) diff --git a/src/Zilf/Language/Signatures/AdeclPart.cs b/src/Zilf/Language/Signatures/AdeclPart.cs index 415dd68..6cea9b9 100644 --- a/src/Zilf/Language/Signatures/AdeclPart.cs +++ b/src/Zilf/Language/Signatures/AdeclPart.cs @@ -23,15 +23,13 @@ namespace Zilf.Language.Signatures { sealed class AdeclPart : SignaturePart { - public AdeclPart([NotNull] SignaturePart left, [NotNull] SignaturePart right) + public AdeclPart(SignaturePart left, SignaturePart right) { Left = left; Right = right; } - [NotNull] public SignaturePart Left { get; } - [NotNull] public SignaturePart Right { get; } public override void Accept(ISignatureVisitor visitor) => visitor.Visit(this); diff --git a/src/Zilf/Language/Signatures/AlternativesPart.cs b/src/Zilf/Language/Signatures/AlternativesPart.cs index 9541bba..e7e9f3a 100644 --- a/src/Zilf/Language/Signatures/AlternativesPart.cs +++ b/src/Zilf/Language/Signatures/AlternativesPart.cs @@ -25,16 +25,14 @@ namespace Zilf.Language.Signatures { sealed class AlternativesPart : SignaturePart { - AlternativesPart([ItemNotNull] [NotNull] IReadOnlyList alternatives) + AlternativesPart(IReadOnlyList alternatives) { Alternatives = alternatives; } - [ItemNotNull] - [NotNull] public IReadOnlyList Alternatives { get; } - public static SignaturePart From([NotNull] [ItemNotNull] IEnumerable parts) + public static SignaturePart From(IEnumerable parts) { var alts = parts.SelectMany(ExpandAlternatives).ToArray(); @@ -51,7 +49,6 @@ namespace Zilf.Language.Signatures } } - [NotNull] static IEnumerable ExpandAlternatives(SignaturePart p) { return p is AlternativesPart ap ? ap.Alternatives : Enumerable.Repeat(p, 1); diff --git a/src/Zilf/Language/Signatures/AnyPart.cs b/src/Zilf/Language/Signatures/AnyPart.cs index adb43a3..ee36d8a 100644 --- a/src/Zilf/Language/Signatures/AnyPart.cs +++ b/src/Zilf/Language/Signatures/AnyPart.cs @@ -23,7 +23,7 @@ namespace Zilf.Language.Signatures { sealed class AnyPart : SignaturePart { - public AnyPart([NotNull] string name) + public AnyPart(string name) { Name = name; } diff --git a/src/Zilf/Language/Signatures/ConstrainedPart.cs b/src/Zilf/Language/Signatures/ConstrainedPart.cs index caa931f..6e933de 100644 --- a/src/Zilf/Language/Signatures/ConstrainedPart.cs +++ b/src/Zilf/Language/Signatures/ConstrainedPart.cs @@ -23,17 +23,15 @@ namespace Zilf.Language.Signatures { class ConstrainedPart : SignaturePart { - [NotNull] public SignaturePart Inner { get; } - ConstrainedPart([NotNull] SignaturePart inner, [NotNull] Constraint constraint) + ConstrainedPart(SignaturePart inner, Constraint constraint) { Inner = inner; Constraint = constraint; } - [NotNull] - public static SignaturePart From([NotNull] SignaturePart inner, [NotNull] Constraint constraint) + public static SignaturePart From(SignaturePart inner, Constraint constraint) { var newConstraint = inner.Constraint.And(constraint); return new ConstrainedPart(inner is ConstrainedPart icp ? icp.Inner : inner, newConstraint); diff --git a/src/Zilf/Language/Signatures/Constraint.cs b/src/Zilf/Language/Signatures/Constraint.cs index 012a907..350e847 100644 --- a/src/Zilf/Language/Signatures/Constraint.cs +++ b/src/Zilf/Language/Signatures/Constraint.cs @@ -28,7 +28,7 @@ namespace Zilf.Language.Signatures { interface IConstraint { - bool Allows([NotNull] [ProvidesContext] Context ctx, [NotNull] ZilObject arg); + bool Allows([ProvidesContext] Context ctx, ZilObject arg); } interface IConstraintVisitor @@ -36,9 +36,9 @@ namespace Zilf.Language.Signatures void VisitAnyObjectConstraint(); void VisitApplicableConstraint(); void VisitBooleanConstraint(); - void VisitConjunctionConstraint([ItemNotNull] [NotNull] [InstantHandle] IEnumerable parts); - void VisitDeclConstraint([NotNull] ZilObject pattern); - void VisitDisjunctionConstraint([ItemNotNull] [NotNull] [InstantHandle] IEnumerable alts); + void VisitConjunctionConstraint([InstantHandle] IEnumerable parts); + void VisitDeclConstraint(ZilObject pattern); + void VisitDisjunctionConstraint([InstantHandle] IEnumerable alts); void VisitForbiddenConstraint(); void VisitPrimTypeConstraint(PrimType primType); void VisitStructuredConstraint(); @@ -52,14 +52,11 @@ namespace Zilf.Language.Signatures public static readonly Constraint Applicable = new ApplicableConstraint(); public static readonly Constraint Boolean = new BooleanConstraint(); - [NotNull] public static Constraint OfType(StdAtom typeAtom) => new TypeConstraint(typeAtom); - [NotNull] public static Constraint OfPrimType(PrimType primtype) => new PrimTypeConstraint(primtype); - [NotNull] - public static Constraint FromDecl([NotNull] [ProvidesContext] Context ctx, [NotNull] ZilObject pattern) + public static Constraint FromDecl([ProvidesContext] Context ctx, ZilObject pattern) { switch (pattern) { @@ -82,9 +79,9 @@ namespace Zilf.Language.Signatures case StdAtom.None: break; - // XXX may need to combine this with a contents constraint - //default: - // return OfType(head.StdAtom); + // XXX may need to combine this with a contents constraint + //default: + // return OfType(head.StdAtom); } } break; @@ -113,8 +110,7 @@ namespace Zilf.Language.Signatures return new DeclConstraint(pattern); } - [NotNull] - public Constraint And([NotNull] Constraint other) + public Constraint And(Constraint other) { switch (CompareImpl(other) ?? Invert(other.CompareImpl(this))) { @@ -129,8 +125,7 @@ namespace Zilf.Language.Signatures } } - [NotNull] - public Constraint Or([NotNull] Constraint other) + public Constraint Or(Constraint other) { switch (CompareImpl(other) ?? Invert(other.CompareImpl(this))) { @@ -145,16 +140,16 @@ namespace Zilf.Language.Signatures } } - protected CompareOutcome? CompareTo([NotNull] Constraint other) + protected CompareOutcome? CompareTo(Constraint other) { return CompareImpl(other) ?? Invert(other.CompareImpl(this)); } - protected abstract CompareOutcome? CompareImpl([NotNull] Constraint other); + protected abstract CompareOutcome? CompareImpl(Constraint other); public abstract bool Allows([ProvidesContext] Context ctx, ZilObject arg); public abstract override string ToString(); - public abstract void Accept([NotNull] IConstraintVisitor visitor); + public abstract void Accept(IConstraintVisitor visitor); protected enum CompareOutcome { @@ -179,8 +174,7 @@ namespace Zilf.Language.Signatures } } - [NotNull] - static string EnglishList([ItemNotNull] [NotNull] IEnumerable items, [NotNull] string connector) + static string EnglishList(IEnumerable items, string connector) { var array = items.ToArray(); @@ -432,9 +426,8 @@ namespace Zilf.Language.Signatures Constraints = constraints; } - [NotNull] - public static Conjunction From([NotNull] Constraint left, - [NotNull] Constraint right) + public static Conjunction From(Constraint left, + Constraint right) { var parts = new List(); @@ -549,9 +542,8 @@ namespace Zilf.Language.Signatures Constraints = constraints; } - [NotNull] - public static Disjunction From([NotNull] Constraint left, - [NotNull] Constraint right) + public static Disjunction From(Constraint left, + Constraint right) { var parts = new List(); diff --git a/src/Zilf/Language/Signatures/FormPart.cs b/src/Zilf/Language/Signatures/FormPart.cs index a5739b7..5f9383d 100644 --- a/src/Zilf/Language/Signatures/FormPart.cs +++ b/src/Zilf/Language/Signatures/FormPart.cs @@ -25,12 +25,11 @@ namespace Zilf.Language.Signatures { sealed class FormPart : StructurePart { - FormPart([ItemNotNull, NotNull] IReadOnlyList parts) : base(parts) + FormPart(IReadOnlyList parts) : base(parts) { } - [NotNull] - public static SignaturePart From([NotNull] [ItemNotNull] IEnumerable parts) + public static SignaturePart From(IEnumerable parts) { var elements = parts.SelectMany(SequencePart.ExpandSequenceParts).ToArray(); diff --git a/src/Zilf/Language/Signatures/ISignaturePart.cs b/src/Zilf/Language/Signatures/ISignaturePart.cs index 86f6680..5aefdfc 100644 --- a/src/Zilf/Language/Signatures/ISignaturePart.cs +++ b/src/Zilf/Language/Signatures/ISignaturePart.cs @@ -23,16 +23,14 @@ namespace Zilf.Language.Signatures { interface ISignaturePart { - [CanBeNull] - ICustomAttributeProvider Source { get; } + ICustomAttributeProvider? Source { get; } - [NotNull] IConstraint Constraint { get; } - string Name { get; } + string? Name { get; } int MinArgs { get; } int? MaxArgs { get; } - void Accept([NotNull] ISignatureVisitor visitor); + void Accept(ISignatureVisitor visitor); } } \ No newline at end of file diff --git a/src/Zilf/Language/Signatures/ISignatureVisitor.cs b/src/Zilf/Language/Signatures/ISignatureVisitor.cs index 7d741f1..28752f0 100644 --- a/src/Zilf/Language/Signatures/ISignatureVisitor.cs +++ b/src/Zilf/Language/Signatures/ISignatureVisitor.cs @@ -22,16 +22,16 @@ namespace Zilf.Language.Signatures { interface ISignatureVisitor { - void Visit([NotNull] AdeclPart part); - void Visit([NotNull] AlternativesPart part); - void Visit([NotNull] AnyPart part); - void Visit([NotNull] ConstrainedPart part); - void Visit([NotNull] FormPart part); - void Visit([NotNull] ListPart part); - void Visit([NotNull] LiteralPart part); - void Visit([NotNull] OptionalPart part); - void Visit([NotNull] QuotedPart part); - void Visit([NotNull] SequencePart part); - void Visit([NotNull] VarArgsPart part); + void Visit(AdeclPart part); + void Visit(AlternativesPart part); + void Visit(AnyPart part); + void Visit(ConstrainedPart part); + void Visit(FormPart part); + void Visit(ListPart part); + void Visit(LiteralPart part); + void Visit(OptionalPart part); + void Visit(QuotedPart part); + void Visit(SequencePart part); + void Visit(VarArgsPart part); } } diff --git a/src/Zilf/Language/Signatures/JsonDescriber.cs b/src/Zilf/Language/Signatures/JsonDescriber.cs index 11aed32..de83cd8 100644 --- a/src/Zilf/Language/Signatures/JsonDescriber.cs +++ b/src/Zilf/Language/Signatures/JsonDescriber.cs @@ -20,7 +20,6 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; -using JetBrains.Annotations; using Newtonsoft.Json.Linq; using Zilf.Interpreter; using Zilf.Interpreter.Values; @@ -29,17 +28,21 @@ namespace Zilf.Language.Signatures { static class VisitingExtensions { - public static T AcceptForValue([NotNull] this ISignaturePart part, [NotNull] SignatureVisitorWithValue visitor) + public static T AcceptForValue(this ISignaturePart part, SignatureVisitorWithValue visitor) + where T : class { - return visitor.Run(part); + var result = visitor.Run(part); + System.Diagnostics.Debug.Assert(result != null); + return result; } } abstract class SignatureVisitorWithValue : ISignatureVisitor + where T : class { - T result; + T? result; - internal T Run([NotNull] ISignaturePart part) + internal T? Run(ISignaturePart part) { part.Accept(this); PostProcess(part, ref result); @@ -47,22 +50,22 @@ namespace Zilf.Language.Signatures } [SuppressMessage("ReSharper", "UnusedParameter.Global")] - protected virtual void PostProcess([NotNull] ISignaturePart part, ref T pendingResult) + protected virtual void PostProcess(ISignaturePart part, ref T? pendingResult) { // by default, nada } - protected abstract T Visit([NotNull] AdeclPart part); - protected abstract T Visit([NotNull] AlternativesPart part); - protected abstract T Visit([NotNull] AnyPart part); - protected abstract T Visit([NotNull] ConstrainedPart part); - protected abstract T Visit([NotNull] FormPart part); - protected abstract T Visit([NotNull] ListPart part); - protected abstract T Visit([NotNull] LiteralPart part); - protected abstract T Visit([NotNull] OptionalPart part); - protected abstract T Visit([NotNull] QuotedPart part); - protected abstract T Visit([NotNull] SequencePart part); - protected abstract T Visit([NotNull] VarArgsPart part); + protected abstract T Visit(AdeclPart part); + protected abstract T Visit(AlternativesPart part); + protected abstract T Visit(AnyPart part); + protected abstract T Visit(ConstrainedPart part); + protected abstract T Visit(FormPart part); + protected abstract T Visit(ListPart part); + protected abstract T Visit(LiteralPart part); + protected abstract T Visit(OptionalPart part); + protected abstract T Visit(QuotedPart part); + protected abstract T Visit(SequencePart part); + protected abstract T Visit(VarArgsPart part); #region ISignatureVisitor implementation @@ -89,8 +92,7 @@ namespace Zilf.Language.Signatures { } - [NotNull] - public static JObject Describe([NotNull] ISignature signature) + public static JObject Describe(ISignature signature) { var parts = signature.Parts.Select(p => p.AcceptForValue(Instance)); var result = new JObject @@ -130,15 +132,14 @@ namespace Zilf.Language.Signatures return result; } - protected override void PostProcess(ISignaturePart part, ref JObject pendingResult) + protected override void PostProcess(ISignaturePart part, ref JObject? pendingResult) { - if (part.Name != null) + if (pendingResult != null && part.Name != null) { pendingResult["name"] = part.Name; } } - [NotNull] protected override JObject Visit(VarArgsPart part) { var result = new JObject { ["$rest"] = part.Inner.AcceptForValue(this) }; @@ -149,7 +150,6 @@ namespace Zilf.Language.Signatures return result; } - [NotNull] protected override JObject Visit(AdeclPart part) { return new JObject @@ -159,7 +159,6 @@ namespace Zilf.Language.Signatures }; } - [NotNull] protected override JObject Visit(AlternativesPart part) { return new JObject @@ -168,13 +167,11 @@ namespace Zilf.Language.Signatures }; } - [NotNull] protected override JObject Visit(AnyPart part) { return new JObject(); } - [NotNull] protected override JObject Visit(ConstrainedPart part) { var result = part.Inner.AcceptForValue(this); @@ -182,7 +179,6 @@ namespace Zilf.Language.Signatures return result; } - [NotNull] protected override JObject Visit(FormPart part) { return new JObject @@ -192,7 +188,6 @@ namespace Zilf.Language.Signatures }; } - [NotNull] protected override JObject Visit(ListPart part) { return new JObject @@ -202,19 +197,16 @@ namespace Zilf.Language.Signatures }; } - [NotNull] protected override JObject Visit(LiteralPart part) { return new JObject { ["$literal"] = part.Text }; } - [NotNull] protected override JObject Visit(OptionalPart part) { return new JObject { ["$opt"] = part.Inner.AcceptForValue(this) }; } - [NotNull] protected override JObject Visit(QuotedPart part) { var result = part.Inner.AcceptForValue(this); @@ -222,7 +214,6 @@ namespace Zilf.Language.Signatures return result; } - [NotNull] protected override JObject Visit(SequencePart part) { return new JObject @@ -233,14 +224,14 @@ namespace Zilf.Language.Signatures class ConstraintDescriber : IConstraintVisitor { - public static JObject Describe([NotNull] Constraint constraint) + public static JObject? Describe(Constraint constraint) { var describer = new ConstraintDescriber(); constraint.Accept(describer); return describer.result; } - JObject result; + JObject? result; public void VisitAnyObjectConstraint() { diff --git a/src/Zilf/Language/Signatures/ListPart.cs b/src/Zilf/Language/Signatures/ListPart.cs index 1969fa5..bda41dd 100644 --- a/src/Zilf/Language/Signatures/ListPart.cs +++ b/src/Zilf/Language/Signatures/ListPart.cs @@ -24,12 +24,11 @@ namespace Zilf.Language.Signatures { sealed class ListPart : StructurePart { - ListPart([ItemNotNull, NotNull] IReadOnlyList parts) : base(parts) + ListPart(IReadOnlyList parts) : base(parts) { } - [NotNull] - public static SignaturePart From([NotNull] [ItemNotNull] IEnumerable parts) + public static SignaturePart From(IEnumerable parts) { return new ListPart(parts.SelectMany(SequencePart.ExpandSequenceParts).ToArray()); } diff --git a/src/Zilf/Language/Signatures/LiteralPart.cs b/src/Zilf/Language/Signatures/LiteralPart.cs index 632c958..e815cc6 100644 --- a/src/Zilf/Language/Signatures/LiteralPart.cs +++ b/src/Zilf/Language/Signatures/LiteralPart.cs @@ -24,16 +24,14 @@ namespace Zilf.Language.Signatures { sealed class LiteralPart : SignaturePart { - [NotNull] public string Text { get; } - LiteralPart([NotNull] string text) + LiteralPart(string text) { Text = text; } - [NotNull] - public static SignaturePart From([NotNull] string text) + public static SignaturePart From(string text) { return new LiteralPart(text); } diff --git a/src/Zilf/Language/Signatures/OptionalPart.cs b/src/Zilf/Language/Signatures/OptionalPart.cs index e5326bb..e8ddd92 100644 --- a/src/Zilf/Language/Signatures/OptionalPart.cs +++ b/src/Zilf/Language/Signatures/OptionalPart.cs @@ -23,16 +23,14 @@ namespace Zilf.Language.Signatures { sealed class OptionalPart : SignaturePart { - [NotNull] public SignaturePart Inner { get; } - OptionalPart([NotNull] SignaturePart inner) + OptionalPart(SignaturePart inner) { Inner = inner; } - [NotNull] - public static SignaturePart From([NotNull] SignaturePart inner) + public static SignaturePart From(SignaturePart inner) { switch (inner) { diff --git a/src/Zilf/Language/Signatures/PlainDescriber.cs b/src/Zilf/Language/Signatures/PlainDescriber.cs index 584485b..11334ce 100644 --- a/src/Zilf/Language/Signatures/PlainDescriber.cs +++ b/src/Zilf/Language/Signatures/PlainDescriber.cs @@ -19,24 +19,22 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using JetBrains.Annotations; using Zilf.Interpreter; using Zilf.Interpreter.Values; namespace Zilf.Language.Signatures { + [System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1308:Normalize strings to uppercase", Justification = "Not normalizing.")] class PlainDescriber : ISignatureVisitor, IConstraintVisitor { - [NotNull] readonly StringBuilder sb; - PlainDescriber([NotNull] StringBuilder sb) + PlainDescriber(StringBuilder sb) { this.sb = sb; } - [NotNull] - public static string Describe([NotNull] ISignature signature) + public static string Describe(ISignature signature) { var sb = new StringBuilder(); var visitor = new PlainDescriber(sb); @@ -44,8 +42,7 @@ namespace Zilf.Language.Signatures return sb.ToString(); } - [NotNull] - static string Describe([NotNull] ISignaturePart part) + static string Describe(ISignaturePart part) { var sb = new StringBuilder(); var visitor = new PlainDescriber(sb); @@ -53,8 +50,7 @@ namespace Zilf.Language.Signatures return sb.ToString(); } - [NotNull] - static string Describe([NotNull] Constraint constraint) + static string Describe(Constraint constraint) { var sb = new StringBuilder(); var visitor = new PlainDescriber(sb); @@ -62,7 +58,7 @@ namespace Zilf.Language.Signatures return sb.ToString(); } - void VisitWithDelimiter([ItemNotNull] [NotNull] IEnumerable parts, [NotNull] string delimiter) + void VisitWithDelimiter(IEnumerable parts, string delimiter) { bool first = true; diff --git a/src/Zilf/Language/Signatures/QuotedPart.cs b/src/Zilf/Language/Signatures/QuotedPart.cs index 63432a3..1ac9d84 100644 --- a/src/Zilf/Language/Signatures/QuotedPart.cs +++ b/src/Zilf/Language/Signatures/QuotedPart.cs @@ -24,16 +24,14 @@ namespace Zilf.Language.Signatures { sealed class QuotedPart : SignaturePart { - [NotNull] public SignaturePart Inner { get; } - QuotedPart([NotNull] SignaturePart inner) + QuotedPart(SignaturePart inner) { Inner = inner; } - [NotNull] - public static SignaturePart From([NotNull] SignaturePart inner) + public static SignaturePart From(SignaturePart inner) { if (inner is AlternativesPart ap) { diff --git a/src/Zilf/Language/Signatures/SequencePart.cs b/src/Zilf/Language/Signatures/SequencePart.cs index 3224d29..2ed649c 100644 --- a/src/Zilf/Language/Signatures/SequencePart.cs +++ b/src/Zilf/Language/Signatures/SequencePart.cs @@ -25,16 +25,14 @@ namespace Zilf.Language.Signatures { sealed class SequencePart : SignaturePart { - [ItemNotNull] - [NotNull] public IReadOnlyList Parts { get; } - SequencePart([ItemNotNull] [NotNull] IReadOnlyList seqParts) + SequencePart(IReadOnlyList seqParts) { Parts = seqParts; } - public static SignaturePart From([NotNull] [ItemNotNull] IEnumerable parts) + public static SignaturePart From(IEnumerable parts) { var seqParts = parts.SelectMany(ExpandSequenceParts).ToArray(); @@ -51,7 +49,6 @@ namespace Zilf.Language.Signatures } } - [NotNull] public static IEnumerable ExpandSequenceParts(SignaturePart p) { return p is SequencePart sp ? sp.Parts : Enumerable.Repeat(p, 1); diff --git a/src/Zilf/Language/Signatures/SignatureBuilder.cs b/src/Zilf/Language/Signatures/SignatureBuilder.cs index fbc650c..0b266a5 100644 --- a/src/Zilf/Language/Signatures/SignatureBuilder.cs +++ b/src/Zilf/Language/Signatures/SignatureBuilder.cs @@ -29,8 +29,7 @@ namespace Zilf.Language.Signatures { #region Basics - [NotNull] - public static SignaturePart MaybeConvertDecl([NotNull] ParamDescAttribute attr) + public static SignaturePart MaybeConvertDecl(ParamDescAttribute attr) { if (string.IsNullOrWhiteSpace(attr.Description) || attr.Description.Contains(" ")) throw new ArgumentException($"Unexpected param description: {attr.Description}"); @@ -38,22 +37,13 @@ namespace Zilf.Language.Signatures return Identifier(attr.Description); } - [NotNull] - public static SignaturePart Quote([NotNull] SignaturePart second) - { - return QuotedPart.From(second); - } + public static SignaturePart Quote(SignaturePart second) => QuotedPart.From(second); static readonly Regex orDeclRegex = new Regex(@"^]+)\s*)+>$"); - [CanBeNull] - public static SignaturePart MaybeConvertDecl([NotNull] DeclAttribute decl) - { - return MaybeConvertDecl(decl.Pattern); - } + public static SignaturePart? MaybeConvertDecl(DeclAttribute decl) => MaybeConvertDecl(decl.Pattern); - [CanBeNull] - public static SignaturePart MaybeConvertDecl([NotNull] string pattern) + public static SignaturePart? MaybeConvertDecl(string pattern) { // TODO: this should parse the instead of doing a hacky regex match @@ -74,70 +64,56 @@ namespace Zilf.Language.Signatures var alts = captures.Select(c => MaybeConvertDecl(c.Value)).ToArray(); if (alts.Length > 0 && alts.All(a => a != null)) { - return Alternatives(alts); + return Alternatives(alts!); } return null; } - [NotNull] - public static SignaturePart VarArgs([NotNull] SignaturePart inner, bool isRequired) - { - return VarArgsPart.From(inner, isRequired); - } + public static SignaturePart VarArgs(SignaturePart inner, bool isRequired) => + VarArgsPart.From(inner, isRequired); - [NotNull] - public static SignaturePart Optional([NotNull] SignaturePart inner) - { - return OptionalPart.From(inner); - } + public static SignaturePart Optional(SignaturePart inner) => OptionalPart.From(inner); - [NotNull] - public static SignaturePart List([ItemNotNull] [NotNull] IEnumerable parts, [CanBeNull] string name = null) + public static SignaturePart List(IEnumerable parts, string? name = null) { var result = ListPart.From(parts); result.Name = name; return result; } - [NotNull] - public static SignaturePart Form([ItemNotNull] [NotNull] IEnumerable parts, [CanBeNull] string name = null) + public static SignaturePart Form(IEnumerable parts, string? name = null) { var result = FormPart.From(parts); result.Name = name; return result; } - [NotNull] - public static SignaturePart Identifier([NotNull] string name) + public static SignaturePart Identifier(string name) { return new AnyPart(name); } - [NotNull] - public static SignaturePart Adecl([NotNull] SignaturePart left, [NotNull] SignaturePart right, [CanBeNull] string name = null) + public static SignaturePart Adecl(SignaturePart left, SignaturePart right, string? name = null) { return new AdeclPart(left, right) { Name = name }; } - [NotNull] - public static SignaturePart Alternatives([ItemNotNull] [NotNull] IEnumerable parts, [CanBeNull] string name = null) + public static SignaturePart Alternatives(IEnumerable parts, string? name = null) { var result = AlternativesPart.From(parts); result.Name = name; return result; } - [NotNull] - public static SignaturePart Sequence([ItemNotNull] [NotNull] IEnumerable parts, [CanBeNull] string name = null) + public static SignaturePart Sequence(IEnumerable parts, string? name = null) { var result = SequencePart.From(parts); result.Name = name; return result; } - [NotNull] - public static SignaturePart Constrained([NotNull] SignaturePart inner, [NotNull] Constraint constraint) + public static SignaturePart Constrained(SignaturePart inner, Constraint constraint) { return ConstrainedPart.From(inner, constraint); } diff --git a/src/Zilf/Language/Signatures/SignaturePart.cs b/src/Zilf/Language/Signatures/SignaturePart.cs index 5a8ffda..a3e0223 100644 --- a/src/Zilf/Language/Signatures/SignaturePart.cs +++ b/src/Zilf/Language/Signatures/SignaturePart.cs @@ -25,21 +25,16 @@ namespace Zilf.Language.Signatures { abstract class SignaturePart : ISignaturePart { - public ICustomAttributeProvider Source => null; - public string Name { get; set; } + public ICustomAttributeProvider? Source => null; + public string? Name { get; set; } - [NotNull] public abstract Constraint Constraint { get; } public abstract int MinArgs { get; } public abstract int? MaxArgs { get; } public abstract void Accept(ISignatureVisitor visitor); - [NotNull] - [ItemNotNull] protected abstract IEnumerable GetChildren(); - [NotNull] - [ItemNotNull] public IEnumerable GetDescendants() { return GetChildren().Concat(GetChildren().SelectMany(c => c.GetDescendants())); diff --git a/src/Zilf/Language/Signatures/StructurePart.cs b/src/Zilf/Language/Signatures/StructurePart.cs index 5c2c1b8..004fd99 100644 --- a/src/Zilf/Language/Signatures/StructurePart.cs +++ b/src/Zilf/Language/Signatures/StructurePart.cs @@ -23,11 +23,9 @@ namespace Zilf.Language.Signatures { abstract class StructurePart : SignaturePart { - [ItemNotNull] - [NotNull] public IReadOnlyList Parts { get; } - protected StructurePart([ItemNotNull] [NotNull] IReadOnlyList parts) + protected StructurePart(IReadOnlyList parts) { Parts = parts; } diff --git a/src/Zilf/Language/Signatures/SubrSignature.Builder.cs b/src/Zilf/Language/Signatures/SubrSignature.Builder.cs index 2826ce4..7f36cb6 100644 --- a/src/Zilf/Language/Signatures/SubrSignature.Builder.cs +++ b/src/Zilf/Language/Signatures/SubrSignature.Builder.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; @@ -31,10 +32,12 @@ namespace Zilf.Language.Signatures { partial class SubrSignature { - static readonly object[] EmptyObjectArray = new object[0]; + static readonly object[] EmptyObjectArray = Array.Empty(); - [NotNull] - public static ISignature FromMethodInfo([NotNull] MethodInfo methodInfo, bool isFSubr) + [SuppressMessage("Style", "IDE0060:Remove unused parameter")] + [SuppressMessage("Performance", "CA1801:Unused parameter")] + [SuppressMessage("Redundancy", "RCS1163:Unused parameter.")] + public static ISignature FromMethodInfo(MethodInfo methodInfo, bool isFSubr) { if (methodInfo == null) throw new ArgumentNullException(nameof(methodInfo)); @@ -53,27 +56,27 @@ namespace Zilf.Language.Signatures return new SubrSignature(paramSigParts.ToArray()); } - [NotNull] - static SignaturePart ConvertSubrParam([NotNull] ParameterInfo pi) + static SignaturePart ConvertSubrParam(ParameterInfo pi) { var (isOptional, defaultValue) = CheckOptional(pi); return ConvertForSubr( pi.ParameterType, - Hyphenate(pi.Name), + Hyphenate(pi.Name!), pi.GetCustomAttributes(false), isOptional, defaultValue); } - [NotNull] + [SuppressMessage("Style", "IDE0060:Remove unused parameter")] + [SuppressMessage("Redundancy", "RCS1163:Unused parameter.")] + [SuppressMessage("Performance", "CA1801:Unused parameter")] static SignaturePart ConvertForSubr( - [NotNull] Type paramType, - [NotNull] string name, + Type paramType, + string name, // ReSharper disable once SuggestBaseTypeForParameter - [NotNull] [ItemNotNull] object[] attrs, + object[] attrs, bool isOptional, - // ReSharper disable once UnusedParameter.Local - object defaultValue) + object? defaultValue) { // [Either], [Required], and [Decl] go on the parameter var isRequired = attrs.OfType().Any(); @@ -105,7 +108,7 @@ namespace Zilf.Language.Signatures nameof(ZilSequenceParamAttribute) + ": pick at most one"); } - SignaturePart elemPart = null; + SignaturePart? elemPart = null; if (eitherAttr != null) { @@ -148,46 +151,34 @@ namespace Zilf.Language.Signatures return elemPart; } - [NotNull] - static SignaturePart ConvertEither([NotNull] [ItemNotNull] [InstantHandle] IEnumerable altTypes, [NotNull] string name) + static SignaturePart ConvertEither([InstantHandle] IEnumerable altTypes, string name) { var alts = from t in altTypes select ConvertForSubr(t, name, EmptyObjectArray, false, null); return SignatureBuilder.Alternatives(alts, name); } - [NotNull] - static SignaturePart ConvertStruct([NotNull] Type structType, [NotNull] ZilStructuredParamAttribute attr, [NotNull] string name) + static SignaturePart ConvertStruct(Type structType, ZilStructuredParamAttribute attr, string name) { // TODO: cache the result var parts = ConvertFields(structType).ToList(); - switch (attr.TypeAtom) + return attr.TypeAtom switch { - case StdAtom.ADECL: - return SignatureBuilder.Adecl(parts[0], parts[1], name); - - case StdAtom.FORM: - return SignatureBuilder.Form(parts, name); - - case StdAtom.LIST: - return SignatureBuilder.List(parts, name); - - default: - throw new UnhandledCaseException(attr.TypeAtom.ToString()); - } + StdAtom.ADECL => SignatureBuilder.Adecl(parts[0], parts[1], name), + StdAtom.FORM => SignatureBuilder.Form(parts, name), + StdAtom.LIST => SignatureBuilder.List(parts, name), + _ => throw new UnhandledCaseException(attr.TypeAtom.ToString()) + }; } - [NotNull] - static SignaturePart ConvertSequence([NotNull] Type seqType, [NotNull] string name) + static SignaturePart ConvertSequence(Type seqType, string name) { // TODO: cache the result? return SignatureBuilder.Sequence(ConvertFields(seqType), name); } - [NotNull] - [ItemNotNull] - static IEnumerable ConvertFields([NotNull] Type structOrSeqType) + static IEnumerable ConvertFields(Type structOrSeqType) { return structOrSeqType.GetFields() .OrderBy(f => Marshal.OffsetOf(structOrSeqType, f.Name).ToInt64()) @@ -213,8 +204,7 @@ namespace Zilf.Language.Signatures { typeof(bool), Constraint.Boolean } }; - [NotNull] - static SignaturePart ConstrainByType([NotNull] SignaturePart part, [NotNull] Type elementType) + static SignaturePart ConstrainByType(SignaturePart part, Type elementType) { System.Diagnostics.Debug.Assert(!elementType.IsArray); @@ -237,14 +227,14 @@ namespace Zilf.Language.Signatures // find an appropriate type or primtype constraint for the element type if (!StandardTypeConstraints.TryGetValue(elementType, out var constraint)) { - BuiltinPrimTypeAttribute primTypeAttr; + BuiltinPrimTypeAttribute? primTypeAttr; if ((primTypeAttr = elementType.GetCustomAttribute(false)) != null) { constraint = Constraint.OfPrimType(primTypeAttr.PrimType); } else { - BuiltinTypeAttribute typeAttr; + BuiltinTypeAttribute? typeAttr; if ((typeAttr = elementType.GetCustomAttribute(false)) != null) { constraint = Constraint.OfType(typeAttr.Name); @@ -260,7 +250,7 @@ namespace Zilf.Language.Signatures return isOptional ? SignatureBuilder.Optional(part) : part; } - static (bool isOptional, object defaultValue) CheckOptional([NotNull] ParameterInfo pi) + static (bool isOptional, object? defaultValue) CheckOptional(ParameterInfo pi) { var zilOptAttr = pi.GetCustomAttribute(false); @@ -268,27 +258,33 @@ namespace Zilf.Language.Signatures return (pi.IsOptional, pi.HasDefaultValue ? pi.DefaultValue : null); if (pi.IsOptional) + { throw new InvalidOperationException( $"Expected {nameof(ZilOptionalAttribute)} or {nameof(pi.IsOptional)}, not both"); + } return (true, zilOptAttr.Default); } - static (bool isOptional, object defaultValue) CheckOptional([NotNull] MemberInfo fi) + static (bool isOptional, object? defaultValue) CheckOptional(MemberInfo fi) { var zilOptAttr = fi.GetCustomAttribute(false); return (zilOptAttr != null, zilOptAttr?.Default); } - static (bool isArray, Type elementOrNonArrayType) CheckArray([NotNull] Type maybeArrayType) + static (bool isArray, Type elementOrNonArrayType) CheckArray(Type maybeArrayType) { - return maybeArrayType.IsArray - ? (true, maybeArrayType.GetElementType()) - : (false, maybeArrayType); + if (maybeArrayType.IsArray) + { + var elementType = maybeArrayType.GetElementType(); + System.Diagnostics.Debug.Assert(elementType != null); + return (true, elementType); + } + + return (false, maybeArrayType); } - [NotNull] - static string Hyphenate([NotNull] string s) + static string Hyphenate(string s) { var sb = new StringBuilder(s.Length); sb.Append(char.ToLowerInvariant(s[0])); diff --git a/src/Zilf/Language/Signatures/SubrSignature.cs b/src/Zilf/Language/Signatures/SubrSignature.cs index d5dbe65..9ababff 100644 --- a/src/Zilf/Language/Signatures/SubrSignature.cs +++ b/src/Zilf/Language/Signatures/SubrSignature.cs @@ -24,13 +24,11 @@ namespace Zilf.Language.Signatures { sealed partial class SubrSignature : ISignature { - [NotNull] - [ItemNotNull] public IReadOnlyList Parts { get; } public int MinArgs { get; } public int? MaxArgs { get; } - SubrSignature([NotNull] [ItemNotNull] IReadOnlyList parts) + SubrSignature(IReadOnlyList parts) { Parts = parts; diff --git a/src/Zilf/Language/Signatures/VarArgsPart.cs b/src/Zilf/Language/Signatures/VarArgsPart.cs index 8fd06ed..c066416 100644 --- a/src/Zilf/Language/Signatures/VarArgsPart.cs +++ b/src/Zilf/Language/Signatures/VarArgsPart.cs @@ -23,19 +23,17 @@ namespace Zilf.Language.Signatures { sealed class VarArgsPart : SignaturePart { - [NotNull] public SignaturePart Inner { get; } public bool Required { get; } - VarArgsPart([NotNull] SignaturePart inner, bool isRequired) + VarArgsPart(SignaturePart inner, bool isRequired) { Inner = inner; Required = isRequired; } - [NotNull] - public static SignaturePart From([NotNull] SignaturePart inner, bool isRequired) + public static SignaturePart From(SignaturePart inner, bool isRequired) { switch (inner) { @@ -47,7 +45,7 @@ namespace Zilf.Language.Signatures inner = op.Inner; break; } - + return new VarArgsPart(inner, isRequired); } diff --git a/src/Zilf/Language/Signatures/ZBuiltinSignature.cs b/src/Zilf/Language/Signatures/ZBuiltinSignature.cs index 5d606ef..ae53084 100644 --- a/src/Zilf/Language/Signatures/ZBuiltinSignature.cs +++ b/src/Zilf/Language/Signatures/ZBuiltinSignature.cs @@ -46,8 +46,7 @@ namespace Zilf.Language.Signatures ReturnPart = returnPart; } - [NotNull] - public static ISignature FromBuiltinSpec([NotNull] BuiltinSpec spec) + public static ISignature FromBuiltinSpec(BuiltinSpec spec) { var pis = spec.Method.GetParameters(); @@ -102,15 +101,13 @@ namespace Zilf.Language.Signatures } } - [NotNull] - static SignaturePart ConvertWithHandler([NotNull] ParameterTypeHandler handler, - [NotNull] ParameterInfo pi) + static SignaturePart ConvertWithHandler(ParameterTypeHandler handler, + ParameterInfo pi) { return ApplyParamAttributes(handler.ToSignaturePart(pi), pi); } - [NotNull] - static SignaturePart ApplyParamAttributes([NotNull] SignaturePart part, [NotNull] ParameterInfo pi) + static SignaturePart ApplyParamAttributes(SignaturePart part, ParameterInfo pi) { // TODO: also handle VariableAttribute? diff --git a/src/Zilf/Language/SourceLines.cs b/src/Zilf/Language/SourceLines.cs index ccd8cd6..94536af 100644 --- a/src/Zilf/Language/SourceLines.cs +++ b/src/Zilf/Language/SourceLines.cs @@ -22,13 +22,9 @@ namespace Zilf.Language { static class SourceLines { - [NotNull] public static readonly ISourceLine Unknown = new StringSourceLine(""); - [NotNull] public static readonly ISourceLine Chtyped = new StringSourceLine(""); - [NotNull] public static readonly ISourceLine MakeGval = new StringSourceLine(""); - [NotNull] public static readonly ISourceLine TopLevel = new StringSourceLine(""); } } \ No newline at end of file diff --git a/src/Zilf/Language/SyntaxError.cs b/src/Zilf/Language/SyntaxError.cs deleted file mode 100644 index 6cc8043..0000000 --- a/src/Zilf/Language/SyntaxError.cs +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright 2010-2018 Jesse McGrew - * - * This file is part of ZILF. - * - * ZILF is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ZILF is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ZILF. If not, see . - */ - -using System; -using System.Runtime.Serialization; -using Zilf.Diagnostics; -using JetBrains.Annotations; - -namespace Zilf.Language -{ - [Serializable] - class SyntaxError : InterpreterError - { - public SyntaxError([NotNull] string filename, int line, [NotNull] string message) - : base(new FileSourceLine(filename, line), InterpreterMessages.Syntax_Error_0, message) - { - } - - protected SyntaxError([NotNull] SerializationInfo si, StreamingContext sc) - : base(si, sc) - { - } - } -} \ No newline at end of file diff --git a/src/Zilf/Language/ZilError.cs b/src/Zilf/Language/ZilError.cs index 99a5ed1..d23307b 100644 --- a/src/Zilf/Language/ZilError.cs +++ b/src/Zilf/Language/ZilError.cs @@ -17,6 +17,8 @@ */ using System; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Runtime.Serialization; using System.Text; using Zilf.Diagnostics; @@ -28,12 +30,17 @@ namespace Zilf.Language [Serializable] public abstract class ZilErrorBase : Exception { + protected ZilErrorBase() + { } protected ZilErrorBase(string message) : base(message) { } protected ZilErrorBase(string message, Exception innerException) : base(message, innerException) { } - protected ZilErrorBase([NotNull] SerializationInfo info, StreamingContext context) + protected ZilErrorBase(SerializationInfo info, StreamingContext context) : base(info, context) { + Diagnostic = (Diagnostic?)info.GetValue("Diagnostic", typeof(Diagnostic)) ?? + throw new ArgumentException("Diagnostic is missing"); + SourceLine = (ISourceLine?)info.GetValue("SourceLine", typeof(ISourceLine)); } public override void GetObjectData(SerializationInfo info, StreamingContext context) @@ -44,8 +51,8 @@ namespace Zilf.Language info.AddValue("SourceLine", SourceLine); } - public Diagnostic Diagnostic { get; protected set; } - protected ISourceLine SourceLine { get; set; } + public Diagnostic? Diagnostic { get; protected set; } + protected ISourceLine? SourceLine { get; set; } } [Serializable] @@ -61,13 +68,18 @@ namespace Zilf.Language { } - protected ZilError([NotNull] SerializationInfo info, StreamingContext context) + protected ZilError(SerializationInfo info, StreamingContext context) : base(info, context) { } + + protected ZilError() + { + } } [Serializable] + [SuppressMessage("ReSharper", "UnusedMember.Global")] public abstract class ZilFatal : ZilErrorBase { protected ZilFatal(string message) @@ -75,20 +87,30 @@ namespace Zilf.Language { } - protected ZilFatal([NotNull] SerializationInfo info, StreamingContext context) + protected ZilFatal(SerializationInfo info, StreamingContext context) : base(info, context) { } + + protected ZilFatal() + { + } + + protected ZilFatal(string message, Exception innerException) : base(message, innerException) + { + } } static class ZilErrorBaseExtensions { - [NotNull] - public static T Combine([NotNull] this T mainError, [NotNull] T subError) + public static T Combine(this T mainError, T subError) where T : ZilErrorBase { + if (mainError.Diagnostic == null || subError.Diagnostic == null) + return subError; + var newDiag = mainError.Diagnostic.WithSubDiagnostics(subError.Diagnostic); - return (T)Activator.CreateInstance(typeof(T), newDiag); + return (T)Activator.CreateInstance(typeof(T), newDiag)!; } } @@ -97,47 +119,50 @@ namespace Zilf.Language abstract class ZilError : ZilError where TMessageSet : class { - protected ZilError([NotNull] string message) + protected ZilError(string message) : base(message) { SourceLine = DiagnosticContext.Current.SourceLine; Diagnostic = MakeLegacyDiagnostic(SourceLine, message); } - protected ZilError([NotNull] string message, Exception innerException) + protected ZilError(string message, Exception innerException) : base(message, innerException) { SourceLine = DiagnosticContext.Current.SourceLine; Diagnostic = MakeLegacyDiagnostic(SourceLine, message); } - protected ZilError([CanBeNull] ISourceLine src, [NotNull] string message) + protected ZilError(ISourceLine? src, string message) : base(message) { SourceLine = src ?? DiagnosticContext.Current.SourceLine; Diagnostic = MakeLegacyDiagnostic(SourceLine, message); } - protected ZilError([NotNull] Diagnostic diag) + protected ZilError(Diagnostic diag) : base(diag.ToString()) { Diagnostic = diag; SourceLine = diag.Location; } - protected ZilError([NotNull] SerializationInfo si, StreamingContext sc) + protected ZilError(SerializationInfo si, StreamingContext sc) : base(si, sc) { } + protected ZilError() : base() + { + } + #pragma warning disable RECS0108 // Warns about static fields in generic types protected static readonly IDiagnosticFactory DiagnosticFactory = DiagnosticFactory.Instance; #pragma warning restore RECS0108 // Warns about static fields in generic types protected const int LegacyErrorCode = 0; - [NotNull] - protected static Diagnostic MakeDiagnostic([CanBeNull] ISourceLine sourceLine, int code, [ItemNotNull] [CanBeNull] object[] messageArgs = null) + protected static Diagnostic MakeDiagnostic(ISourceLine? sourceLine, int code, object[]? messageArgs = null) { return DiagnosticFactory.GetDiagnostic( sourceLine ?? DiagnosticContext.Current.SourceLine, @@ -145,8 +170,7 @@ namespace Zilf.Language messageArgs, MakeStackTrace(DiagnosticContext.Current.Frame)); } - [NotNull] - protected static Diagnostic MakeLegacyDiagnostic([NotNull] ISourceLine sourceLine, [NotNull] string message) + protected static Diagnostic MakeLegacyDiagnostic(ISourceLine sourceLine, string message) { return DiagnosticFactory.GetDiagnostic( sourceLine, @@ -154,9 +178,8 @@ namespace Zilf.Language new object[] { message }, MakeStackTrace(DiagnosticContext.Current.Frame)); } - [CanBeNull] [ContractAnnotation("notnull => notnull; null => null")] - static string MakeStackTrace([CanBeNull] Frame errorFrame) + static string? MakeStackTrace(Frame? errorFrame) { if (errorFrame == null) return null; @@ -173,7 +196,7 @@ namespace Zilf.Language ? $"in {frame.Description} called " : ""; - sb.AppendFormat(" {0}at {1}", caller, frame.SourceLine.SourceInfo); + sb.AppendFormat(CultureInfo.InvariantCulture, " {0}at {1}", caller, frame.SourceLine.SourceInfo); } return sb.ToString(); @@ -183,26 +206,37 @@ namespace Zilf.Language [UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature)] [Serializable] abstract class ZilFatal : ZilFatal - where TMessageSet : class + where TMessageSet : class { - protected ZilFatal([NotNull] Diagnostic diag) + protected ZilFatal(Diagnostic diag) : base(diag.ToString()) { Diagnostic = diag; SourceLine = diag.Location; } - protected ZilFatal([NotNull] SerializationInfo si, StreamingContext sc) + protected ZilFatal(SerializationInfo si, StreamingContext sc) : base(si, sc) { } + protected ZilFatal(string message) : base(message) + { + } + + protected ZilFatal() + { + } + + protected ZilFatal(string message, Exception innerException) : base(message, innerException) + { + } + #pragma warning disable RECS0108 // Warns about static fields in generic types protected static readonly IDiagnosticFactory DiagnosticFactory = DiagnosticFactory.Instance; #pragma warning restore RECS0108 // Warns about static fields in generic types - [NotNull] - protected static Diagnostic MakeDiagnostic([CanBeNull] ISourceLine sourceLine, int code, [ItemNotNull] [CanBeNull] object[] messageArgs = null) + protected static Diagnostic MakeDiagnostic(ISourceLine? sourceLine, int code, object[]? messageArgs = null) { return DiagnosticFactory.GetDiagnostic( sourceLine ?? DiagnosticContext.Current.SourceLine, @@ -210,9 +244,8 @@ namespace Zilf.Language messageArgs, MakeStackTrace(DiagnosticContext.Current.Frame)); } - [CanBeNull] [ContractAnnotation("notnull => notnull; null => null")] - static string MakeStackTrace([CanBeNull] Frame errorFrame) + static string? MakeStackTrace(Frame? errorFrame) { if (errorFrame == null) return null; @@ -229,7 +262,7 @@ namespace Zilf.Language ? $"in {frame.Description} called " : ""; - sb.AppendFormat(" {0}at {1}", caller, frame.SourceLine.SourceInfo); + sb.AppendFormat(CultureInfo.InvariantCulture, " {0}at {1}", caller, frame.SourceLine.SourceInfo); } return sb.ToString(); diff --git a/src/Zilf/Program.cs b/src/Zilf/Program.cs index 9c53fa9..755c483 100644 --- a/src/Zilf/Program.cs +++ b/src/Zilf/Program.cs @@ -36,15 +36,13 @@ namespace Zilf { static class Program { - [NotNull] internal static string GetVersion() => typeof(Program).Assembly.GetCustomAttribute() - .InformationalVersion ?? ""; + ?.InformationalVersion ?? ""; - [NotNull] internal static string GetBanner() => $"ZILF {GetVersion()}"; - internal static int Main([ItemNotNull] [NotNull] string[] args) + internal static int Main(string[] args) { var ctx = ParseArgs(args, out var inFile, out var outFile); @@ -65,6 +63,7 @@ namespace Zilf return 0; case RunMode.Expression: + Debug.Assert(inFile != null); using (ctx.PushFileContext("")) { Console.WriteLine(Evaluate(ctx, inFile)); @@ -74,17 +73,19 @@ namespace Zilf return 0; case RunMode.Compiler: + Debug.Assert(inFile != null); Debug.Assert(outFile != null); return WrapInFrontEnd(frontEnd => frontEnd.Compile(ctx, inFile, outFile, ctx.WantDebugInfo)); case RunMode.Interpreter: + Debug.Assert(inFile != null); return WrapInFrontEnd(frontEnd => frontEnd.Interpret(ctx, inFile)); default: throw new UnreachableCodeException(); } - int WrapInFrontEnd(Func func) + static int WrapInFrontEnd(Func func) { var frontEnd = new FrontEnd(); try @@ -132,7 +133,7 @@ namespace Zilf [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This is a top-level loop that reports unhandled exceptions to the user.")] - static void DoREPL([NotNull] Context ctx) + static void DoREPL(Context ctx) { using (ctx.PushFileContext("")) using (new Completer(ctx).Attach()) @@ -237,12 +238,12 @@ namespace Zilf return dt; } - [CanBeNull] [ContractAnnotation("=> null, inFile: null, outFile: null; => notnull, inFile: notnull, outFile: canbenull")] - static Context ParseArgs([NotNull] string[] args, [CanBeNull] out string inFile, [CanBeNull] out string outFile) + [return: NotNullIfNotNull("inFile")] + static Context? ParseArgs(string[] args, [NotNullIfNotNull("outFile")] out string? inFile, out string? outFile) { - string newInFile = inFile = null; - string newOutFile = outFile = null; + string? newInFile = inFile = null; + string? newOutFile = outFile = null; bool traceRoutines = false, debugInfo = false, warningsAsErrors = false, suppressNoisyWarnings = true; bool? caseSensitive = null; @@ -286,45 +287,45 @@ namespace Zilf { for (int i = 0; i < args.Length; i++) { - switch (args[i].ToLowerInvariant()) + switch (args[i].ToUpperInvariant()) { - case "-c": + case "-C": mode = RunMode.Compiler; break; - case "-e": + case "-E": mode = RunMode.Expression; break; - case "-i": + case "-I": mode = RunMode.Interactive; break; - case "-q": + case "-Q": quiet = true; break; - case "-cs": + case "-CS": caseSensitive = true; break; - case "-ci": + case "-CI": caseSensitive = false; break; - case "-tr": + case "-TR": traceRoutines = true; break; - case "-d": + case "-D": debugInfo = true; break; - case "-x": + case "-X": mode = RunMode.Interpreter; break; - case "-ip": + case "-IP": i++; if (i < args.Length) { @@ -338,15 +339,15 @@ namespace Zilf break; - case "-w": + case "-W": suppressNoisyWarnings = false; break; - case "-we": + case "-WE": warningsAsErrors = true; break; - case "-ws": + case "-WS": i++; if (i < args.Length) { @@ -361,7 +362,7 @@ namespace Zilf break; case "-?": - case "--help": + case "--HELP": case "/?": Usage(); return false; @@ -447,11 +448,11 @@ namespace Zilf } } - static void AddImplicitIncludePaths([ItemNotNull] [NotNull] IList includePaths, [CanBeNull] string inFile, RunMode mode) + static void AddImplicitIncludePaths(IList includePaths, string? inFile, RunMode mode) { - if (inFile != null && mode != RunMode.Expression) + if (inFile != null && mode != RunMode.Expression && Path.GetDirectoryName(Path.GetFullPath(inFile)) is string dir) { - includePaths.Insert(0, Path.GetDirectoryName(Path.GetFullPath(inFile))); + includePaths.Insert(0, dir); } if (includePaths.Count == 0) @@ -503,16 +504,16 @@ namespace Zilf break; } - IEnumerable RecursiveLibraryIncludePaths(string parent) + static IEnumerable RecursiveLibraryIncludePaths(string parent) { var first = Enumerable.Repeat(parent, 1); - bool Excluded(string name) + static bool Excluded(string name) { - switch (name.ToLowerInvariant()) + switch (name.ToUpperInvariant()) { - case "test": - case "tests": + case "TEST": + case "TESTS": case var _ when name[0] == '.' || name[0] == '_': return true; } @@ -560,19 +561,19 @@ Warning message options: // TODO: move Parse somewhere more sensible /// Syntax error. - public static IEnumerable Parse([NotNull] Context ctx, [NotNull] IEnumerable chars) + public static IEnumerable Parse(Context ctx, IEnumerable chars) { return Parse(ctx, null, chars, null); } /// Syntax error. - public static IEnumerable Parse([NotNull] Context ctx, [NotNull] IEnumerable chars, params ZilObject[] templateParams) + public static IEnumerable Parse(Context ctx, IEnumerable chars, params ZilObject[] templateParams) { return Parse(ctx, null, chars, templateParams); } /// Syntax error. - public static IEnumerable Parse([NotNull] Context ctx, ISourceLine src, [NotNull] IEnumerable chars, params ZilObject[] templateParams) + public static IEnumerable Parse(Context ctx, ISourceLine? src, IEnumerable chars, params ZilObject[]? templateParams) { var parser = new Parser(ctx, src, templateParams); @@ -606,7 +607,7 @@ Warning message options: } } - static IEnumerable ReadAllChars([NotNull] Stream stream) + static IEnumerable ReadAllChars(Stream stream) { using (var rdr = new StreamReader(stream)) { @@ -618,10 +619,9 @@ Warning message options: } } - [CanBeNull] [ContractAnnotation("wantExceptions: true => notnull")] // ReSharper disable once UnusedMethodReturnValue.Global - public static ZilObject Evaluate([NotNull] Context ctx, [NotNull] Stream stream, bool wantExceptions = false) + public static ZilObject? Evaluate(Context ctx, Stream stream, bool wantExceptions = false) { return Evaluate(ctx, ReadAllChars(stream), wantExceptions); } @@ -636,14 +636,13 @@ Warning message options: /// The result of evaluating the last object in the code; or if either the code contained /// no objects, or was and an was caught. [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] - [CanBeNull] - public static ZilObject Evaluate([NotNull] Context ctx, [NotNull] IEnumerable chars, bool wantExceptions = false) + public static ZilObject? Evaluate(Context ctx, IEnumerable chars, bool wantExceptions = false) { try { var ztree = Parse(ctx, chars); - ZilObject result = null; + ZilObject? result = null; bool first = true; foreach (var node in ztree) { diff --git a/src/Zilf/ZModel/AtomNameEqualityComparer.cs b/src/Zilf/ZModel/AtomNameEqualityComparer.cs index 3307a3e..254b893 100644 --- a/src/Zilf/ZModel/AtomNameEqualityComparer.cs +++ b/src/Zilf/ZModel/AtomNameEqualityComparer.cs @@ -45,7 +45,7 @@ namespace Zilf.ZModel return x.Text == y.Text; } - public int GetHashCode([CanBeNull] ZilAtom obj) + public int GetHashCode(ZilAtom? obj) { if (obj == null) return 0; diff --git a/src/Zilf/ZModel/Language.cs b/src/Zilf/ZModel/Language.cs index 5b7c08f..07b282f 100644 --- a/src/Zilf/ZModel/Language.cs +++ b/src/Zilf/ZModel/Language.cs @@ -27,10 +27,9 @@ namespace Zilf.ZModel public string Charset0 { get; } public string Charset1 { get; } public string Charset2 { get; } - [NotNull] public IReadOnlyDictionary SpecialChars { get; } - Language(int id, string charset0, string charset1, string charset2, [NotNull] params char[] specialChars) + Language(int id, string charset0, string charset1, string charset2, params char[] specialChars) { Id = id; Charset0 = charset0; @@ -46,14 +45,12 @@ namespace Zilf.ZModel SpecialChars = specialCharDict; } - [NotNull] public static readonly Language Default = new Language( 0, "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "0123456789.,!?_#'\"/\\-:()"); - [NotNull] public static readonly Language German = new Language( 1, "abcdefghiklmnoprstuwzäöü.,", @@ -75,9 +72,8 @@ namespace Zilf.ZModel { "GERMAN", German } }; - [CanBeNull] [System.Diagnostics.Contracts.Pure] - public static Language Get([NotNull] string name) + public static Language? Get(string name) { allLanguages.TryGetValue(name, out var result); return result; diff --git a/src/Zilf/ZModel/LowCoreField.cs b/src/Zilf/ZModel/LowCoreField.cs index 428dfe3..ba67480 100644 --- a/src/Zilf/ZModel/LowCoreField.cs +++ b/src/Zilf/ZModel/LowCoreField.cs @@ -96,8 +96,7 @@ namespace Zilf.ZModel }; #pragma warning restore RECS0070 // Redundant explicit argument name specification - [CanBeNull] - public static LowCoreField Get([NotNull] ZilAtom atom) + public static LowCoreField? Get(ZilAtom atom) { allFields.TryGetValue(atom.Text, out var result); return result; diff --git a/src/Zilf/ZModel/Syntax.cs b/src/Zilf/ZModel/Syntax.cs index 4e7d34d..5858565 100644 --- a/src/Zilf/ZModel/Syntax.cs +++ b/src/Zilf/ZModel/Syntax.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using JetBrains.Annotations; @@ -32,29 +33,22 @@ namespace Zilf.ZModel class Syntax : IProvideSourceLine { public readonly int NumObjects; - [NotNull] public readonly IWord Verb; - [CanBeNull] - public readonly IWord Preposition1; - [CanBeNull] - public readonly IWord Preposition2; + public readonly IWord? Preposition1; + public readonly IWord? Preposition2; public readonly byte Options1, Options2; - [CanBeNull] - public readonly ZilAtom FindFlag1, FindFlag2; - [NotNull] + public readonly ZilAtom? FindFlag1, FindFlag2; public readonly ZilAtom Action; - [CanBeNull] - public readonly ZilAtom Preaction; - [NotNull] + public readonly ZilAtom? Preaction; public readonly ZilAtom ActionName; public readonly IList Synonyms; - static readonly ZilAtom[] EmptySynonyms = new ZilAtom[0]; + static readonly ZilAtom[] EmptySynonyms = Array.Empty(); - public Syntax(ISourceLine src, [NotNull] IWord verb, int numObjects, [CanBeNull] IWord prep1, [CanBeNull] IWord prep2, - byte options1, byte options2, [CanBeNull] ZilAtom findFlag1, [CanBeNull] ZilAtom findFlag2, - [NotNull] ZilAtom action, [CanBeNull] ZilAtom preaction, [NotNull] ZilAtom actionName, - [ItemNotNull] [CanBeNull] IEnumerable synonyms = null) + public Syntax(ISourceLine? src, IWord verb, int numObjects, IWord? prep1, IWord? prep2, + byte options1, byte options2, ZilAtom? findFlag1, ZilAtom? findFlag2, + ZilAtom action, ZilAtom? preaction, ZilAtom actionName, + IEnumerable? synonyms = null) { SourceLine = src; @@ -77,13 +71,12 @@ namespace Zilf.ZModel } /// The syntax definition is invalid. - [NotNull] - public static Syntax Parse(ISourceLine src, [NotNull] IEnumerable definition, [NotNull] Context ctx) + public static Syntax Parse(ISourceLine src, IEnumerable definition, Context ctx) { int numObjects = 0; - ZilAtom verb = null, prep1 = null, prep2 = null; - ZilAtom action = null, preaction = null, actionName = null; - ZilList bits1 = null, find1 = null, bits2 = null, find2 = null, syns = null; + ZilAtom? verb = null, prep1 = null, prep2 = null; + ZilAtom? action = null, preaction = null, actionName = null; + ZilList? bits1 = null, find1 = null, bits2 = null, find2 = null, syns = null; bool rightSide = false; int rhsCount = 0; @@ -221,14 +214,15 @@ namespace Zilf.ZModel { // right side: // action [preaction [action-name]] - if (obj is ZilAtom atom) + var atom = obj as ZilAtom; + if (atom != null) { if (atom.StdAtom == StdAtom.Eq) throw new InterpreterError(InterpreterMessages.Too_Many_0_In_Syntax_Definition, "'='"); } else if (obj is ZilFalse) { - atom = null; + Debug.Assert(atom == null); } else { @@ -278,7 +272,7 @@ namespace Zilf.ZModel var flags2 = ScopeFlags.Parse(bits2, ctx); var findFlag1 = ParseFindFlag(find1); var findFlag2 = ParseFindFlag(find2); - IEnumerable synAtoms = null; + IEnumerable? synAtoms = null; if (syns != null) { @@ -324,9 +318,8 @@ namespace Zilf.ZModel } } - [CanBeNull] [ContractAnnotation("null => null; notnull => notnull")] - static ZilAtom ParseFindFlag([CanBeNull] ZilList list) + static ZilAtom? ParseFindFlag(ZilList? list) { if (list == null) return null; @@ -349,31 +342,32 @@ namespace Zilf.ZModel sb.Append(Verb.Atom); // object clauses - var items = new[] { - new { Prep = Preposition1, Find = FindFlag1, Opts = Options1 }, - new { Prep = Preposition2, Find = FindFlag2, Opts = Options2 } + var items = new[] + { + (prep: Preposition1, find: FindFlag1, opts: Options1), + (prep: Preposition2, find: FindFlag2, opts: Options2) }; - foreach (var item in items.Take(NumObjects)) + foreach (var (prep, find, opts) in items.Take(NumObjects)) { - if (item.Prep != null) + if (prep != null) { sb.Append(' '); - sb.Append(item.Prep.Atom); + sb.Append(prep.Atom); } sb.Append(" OBJECT"); - if (item.Find != null) + if (find != null) { sb.Append(" (FIND "); - sb.Append(item.Find); + sb.Append(find); sb.Append(')'); } // TODO: unparse scope flags sb.Append(" ("); - sb.Append(item.Opts); + sb.Append(opts); sb.Append(')'); } @@ -389,6 +383,6 @@ namespace Zilf.ZModel return sb.ToString(); } - public ISourceLine SourceLine { get; } + public ISourceLine? SourceLine { get; } } } \ No newline at end of file diff --git a/src/Zilf/ZModel/TellTokens.cs b/src/Zilf/ZModel/TellTokens.cs index 24598f8..d6d1f55 100644 --- a/src/Zilf/ZModel/TellTokens.cs +++ b/src/Zilf/ZModel/TellTokens.cs @@ -17,6 +17,7 @@ */ using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using JetBrains.Annotations; using Zilf.Diagnostics; @@ -29,7 +30,7 @@ namespace Zilf.ZModel interface ITellPatternMatchResult { bool Matched { get; } - ZilForm Output { get; } + ZilForm? Output { get; } } class TellPattern @@ -37,7 +38,7 @@ namespace Zilf.ZModel class MatchResult : ITellPatternMatchResult { public bool Matched { get; set; } - public ZilForm Output { get; set; } + public ZilForm? Output { get; set; } public IList Captures { get; } @@ -46,9 +47,10 @@ namespace Zilf.ZModel Captures = new List(); } } + abstract class Token { - public abstract bool Match([NotNull] Context ctx, [NotNull] ZilObject input, [NotNull] MatchResult result); + public abstract bool Match(Context ctx, ZilObject input, MatchResult result); } class AtomToken : Token @@ -62,11 +64,7 @@ namespace Zilf.ZModel public override bool Match(Context ctx, ZilObject input, MatchResult result) { - foreach (var atom in Atoms) - if (input == atom) - return true; - - return false; + return Atoms.Any(atom => input == atom); } } @@ -82,11 +80,12 @@ namespace Zilf.ZModel class DeclToken : Token { // ReSharper disable once MemberCanBePrivate.Local - public ZilObject Pattern { get; set; } + [DisallowNull] + public ZilObject? Pattern { get; set; } public override bool Match(Context ctx, ZilObject input, MatchResult result) { - if (!Decl.Check(ctx, input, Pattern)) + if (!Decl.Check(ctx, input, Pattern!)) return false; result.Captures.Add(input); @@ -96,16 +95,13 @@ namespace Zilf.ZModel class GvalToken : Token { - [CanBeNull] // ReSharper disable once MemberCanBePrivate.Local - public ZilAtom Atom { get; set; } + public ZilAtom? Atom { get; set; } - public override bool Match(Context ctx, ZilObject input, MatchResult result) - { - return input is ZilForm form - && form.IsGVAL(out var inputAtom) - && inputAtom == Atom; - } + public override bool Match(Context ctx, ZilObject input, MatchResult result) => + input is ZilForm form + && form.IsGVAL(out var inputAtom) + && inputAtom == Atom; } readonly Token[] tokens; @@ -118,7 +114,7 @@ namespace Zilf.ZModel } /// The pattern syntax is invalid. - public static IEnumerable Parse([NotNull] IEnumerable spec) + public static IEnumerable Parse(IEnumerable spec) { var tokensSoFar = new List(); int capturesSoFar = 0; @@ -127,8 +123,7 @@ namespace Zilf.ZModel { AtomToken atomToken; - var type = zo.StdTypeAtom; - switch (type) + switch (zo.StdTypeAtom) { case StdAtom.LIST: // one or more atoms to introduce the token @@ -138,7 +133,7 @@ namespace Zilf.ZModel if (list.IsEmpty || !list.All(e => e is ZilAtom)) { throw new InterpreterError( - zo.SourceLine, + list.SourceLine, InterpreterMessages._0_In_1_Must_Be_2, "lists", "TELL token specs", @@ -243,8 +238,7 @@ namespace Zilf.ZModel public int Length => tokens.Length; - [NotNull] - public ITellPatternMatchResult Match([NotNull] IList input, int startIndex, [NotNull] Context ctx, [NotNull] ISourceLine src) + public ITellPatternMatchResult Match(IList input, int startIndex, Context ctx, ISourceLine src) { var result = new MatchResult { Matched = false }; @@ -282,7 +276,7 @@ namespace Zilf.ZModel return result; } - static bool IsSimpleOutputElement([NotNull] ZilObject obj) + static bool IsSimpleOutputElement(ZilObject obj) { return obj is ZilAtom || obj is ZilFix || obj is ZilString || obj is ZilFalse || obj.IsLVAL(out _) || obj.IsGVAL(out _) || (obj as ZilForm)?.IsEmpty == true; diff --git a/src/Zilf/ZModel/Values/ComplexPropDef.cs b/src/Zilf/ZModel/Values/ComplexPropDef.cs index 54c7ef9..ffe8615 100644 --- a/src/Zilf/ZModel/Values/ComplexPropDef.cs +++ b/src/Zilf/ZModel/Values/ComplexPropDef.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Text; using JetBrains.Annotations; using Zilf.Common; using Zilf.Diagnostics; @@ -49,27 +50,24 @@ namespace Zilf.ZModel.Values struct InputElement { public readonly InputElementType Type; - public readonly ZilAtom Variable; - public readonly ZilObject Decl; + public readonly ZilAtom? Variable; + public readonly ZilObject? Decl; - public InputElement(InputElementType type, ZilAtom variable, ZilObject decl) + public InputElement(InputElementType type, ZilAtom? variable, ZilObject? decl) { Type = type; Variable = variable; Decl = decl; } - public override string ToString() - { - return $"Type={Type} Variable={Variable} Decl={Decl}"; - } + public override string ToString() => $"Type={Type} Variable={Variable} Decl={Decl}"; public ZilObject ToZilObject() { switch (Type) { case InputElementType.Atom: - return Variable; + return Variable!; case InputElementType.Many: return ZilString.FromString("MANY"); @@ -80,11 +78,11 @@ namespace Zilf.ZModel.Values case InputElementType.Variable: if (Decl != null) { - return new ZilAdecl(Variable, Decl); + return new ZilAdecl(Variable!, Decl); } else { - return Variable; + return Variable!; } default: @@ -115,11 +113,11 @@ namespace Zilf.ZModel.Values struct OutputElement { public readonly OutputElementType Type; - public readonly ZilAtom Constant, Variable, PartOfSpeech; - public readonly ZilFix Fix; + public readonly ZilAtom? Constant, Variable, PartOfSpeech; + public readonly ZilFix? Fix; - public OutputElement(OutputElementType type, ZilAtom constant, [CanBeNull] ZilAtom variable = null, - [CanBeNull] ZilAtom partOfSpeech = null, [CanBeNull] ZilFix fix = null) + public OutputElement(OutputElementType type, ZilAtom? constant, ZilAtom? variable = null, + ZilAtom? partOfSpeech = null, ZilFix? fix = null) { Type = type; Constant = constant; @@ -130,10 +128,18 @@ namespace Zilf.ZModel.Values public override string ToString() { - return $"Type={Type} Constant={Constant} Variable={Variable} PartOfSpeech={PartOfSpeech} Fix={Fix}"; + var sb = new StringBuilder($"Type={Type}"); + if (Constant != null) + sb.AppendFormat(" Constant={0}", Constant); + if (Variable != null) + sb.AppendFormat(" Variable={0}", Variable); + if (PartOfSpeech != null) + sb.AppendFormat(" PartOfSpeech={0}", PartOfSpeech); + if (Fix != null) + sb.AppendFormat(" Fix={0}", Fix); + return sb.ToString(); } - [NotNull] public ZilObject ToZilObject() { ZilObject result; @@ -176,9 +182,9 @@ namespace Zilf.ZModel.Values TwoElementForm: result = new ZilForm(new[] { GetStdAtom(head), - (ZilObject)Fix ?? new ZilForm(new[] { + (ZilObject?)Fix ?? new ZilForm(new[] { GetStdAtom(StdAtom.LVAL), - Variable + Variable! }) }); break; @@ -186,11 +192,11 @@ namespace Zilf.ZModel.Values case OutputElementType.Voc: result = new ZilForm(new[] { GetStdAtom(StdAtom.VOC), - (ZilObject)Fix ?? new ZilForm(new[] { + (ZilObject?)Fix ?? new ZilForm(new[] { GetStdAtom(StdAtom.LVAL), - Variable + Variable! }), - PartOfSpeech + PartOfSpeech! }); break; @@ -219,14 +225,13 @@ namespace Zilf.ZModel.Values readonly List patterns; - ComplexPropDef([NotNull] IEnumerable patterns) + ComplexPropDef(IEnumerable patterns) { this.patterns = new List(patterns); } /// The PROPDEF pattern syntax is invalid. - [NotNull] - public static ComplexPropDef Parse([NotNull] IEnumerable spec) + public static ComplexPropDef Parse(IEnumerable spec) { var inputs = new List(); var outputs = new List(); @@ -293,8 +298,8 @@ namespace Zilf.ZModel.Values else { // outputs - ZilAtom constant = null; - var output = element; + ZilAtom? constant = null; + ZilObject? output = element; if (element is ZilList elemList) { @@ -394,10 +399,10 @@ namespace Zilf.ZModel.Values return new ComplexPropDef(patterns); } - static OutputElement ConvertOutputForm([NotNull] ZilForm form, [CanBeNull] ZilAtom constant) + static OutputElement ConvertOutputForm(ZilForm form, ZilAtom? constant) { // validate and parse - if (!form.StartsWith(out ZilAtom head)) + if (!form.StartsWith(out ZilAtom? head)) { throw new InterpreterError( form, @@ -469,14 +474,14 @@ namespace Zilf.ZModel.Values Debug.Assert(form.Rest?.Rest != null); - ZilAtom outVariable; - ZilFix outFix; - if (form.StartsWith(out ZilAtom _, out ZilObject zo) && zo.IsLVAL(out var atom)) + ZilAtom? outVariable; + ZilFix? outFix; + if (form.StartsWith(out ZilAtom _, out ZilObject? zo) && zo.IsLVAL(out var atom)) { outVariable = atom; outFix = null; } - else if (form.StartsWith(out ZilAtom _, out ZilFix fix)) + else if (form.StartsWith(out ZilAtom _, out ZilFix? fix)) { outVariable = null; outFix = fix; @@ -518,6 +523,7 @@ namespace Zilf.ZModel.Values int constantValue; if (output.Type == OutputElementType.Length) { + Debug.Assert(output.Fix != null); constantValue = output.Fix.Value; } else @@ -603,7 +609,6 @@ namespace Zilf.ZModel.Values .WithCatchAll(x => x.PatternsList); } - [NotNull] public ZilList PatternsList { get @@ -626,9 +631,8 @@ namespace Zilf.ZModel.Values } } - [NotNull] [ChtypeMethod] - public static ComplexPropDef FromList([NotNull] ZilListBase list) => Parse(list); + public static ComplexPropDef FromList(ZilListBase list) => Parse(list); public struct ElementPreBuilders { @@ -638,7 +642,7 @@ namespace Zilf.ZModel.Values public struct ElementConverters { - public Func CompileConstant; + public Func CompileConstant; public Func GetGlobalNumber; public Func GetAdjectiveValue; // (word, src) => A?constant or word builder public Func GetVocabWord; // (word, part of speech, src) => word builder @@ -646,6 +650,7 @@ namespace Zilf.ZModel.Values public bool Matches(Context ctx, ZilList prop) { + Debug.Assert(prop.Rest != null); foreach (var p in patterns) { var prop2 = prop.Rest; @@ -657,9 +662,9 @@ namespace Zilf.ZModel.Values } /// doesn't match any of the supported patterns. - public void PreBuildProperty([NotNull] Context ctx, [NotNull] ZilList prop, ElementPreBuilders preBuilders) + public void PreBuildProperty(Context ctx, ZilList prop, ElementPreBuilders preBuilders) { - + Debug.Assert(prop.First != null && prop.Rest != null); var captures = new Dictionary>(); foreach (var p in patterns) @@ -668,19 +673,20 @@ namespace Zilf.ZModel.Values var propBody = prop.Rest; captures.Clear(); - if (MatchPartialPattern(ctx, ref propBody, p.Inputs, 1, captures) && propBody.IsEmpty) - { - PartialPreBuild(ctx, captures, preBuilders, p.Outputs, 0, prop.SourceLine); - return; - } + if (!MatchPartialPattern(ctx, ref propBody, p.Inputs, 1, captures) || !propBody.IsEmpty) + continue; + + PartialPreBuild(ctx, captures, preBuilders, p.Outputs, 0, prop.SourceLine ?? SourceLines.Unknown); + return; } throw new InterpreterError(InterpreterMessages.Property_0_Initializer_Doesnt_Match_Any_Supported_Patterns, prop.First); } /// doesn't match any of the supported patterns. - public void BuildProperty([NotNull] Context ctx, [NotNull] ZilList prop,